fc
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist.zip
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
7
README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Vue 3 + Vite
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
13
index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + Vue</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1982
package-lock.json
generated
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "btgxq-population-housing",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vicons/fluent": "^0.12.0",
|
||||||
|
"@vicons/utils": "^0.1.4",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"naive-ui": "^2.35.0",
|
||||||
|
"stylus": "^0.60.0",
|
||||||
|
"vue": "^3.3.4",
|
||||||
|
"vue-router": "^4.2.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
|
"vite": "^4.4.5"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/assets/images/card.png
Normal file
After Width: | Height: | Size: 311 B |
6
public/assets/images/dial-phone.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" width="15" height="15" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
|
||||||
|
|
||||||
|
<g>
|
||||||
|
<path d="M32 6.88c0-1.12-2.176-2.592-4.864-3.040-3.338-0.58-7.182-0.912-11.104-0.912s-7.766 0.332-11.506 0.969l0.402-0.057c-2.72 0.448-4.896 1.92-4.896 3.040 0 0.032 0.032 0.064 0.032 0.096-0.038 0.104-0.061 0.225-0.064 0.351l-0 0.001v3.776c0 0.512 0.448 0.96 0.992 0.96h4.928c0.544 0 0.992-0.448 0.992-0.96v-3.456c6.016-0.8 12.16-0.8 18.176 0v3.68c0 0.544 0.448 0.96 0.992 0.96h4.928c0.544 0 0.992-0.416 0.992-0.96v-3.936c0-0.096-0.032-0.192-0.064-0.288 0.032-0.064 0.064-0.128 0.064-0.224zM29.472 18.464l-5.408-1.824c-0.416-0.128-0.992-0.256-1.568-0.384v-5.984h-2.272v3.52h-8.384v-3.52h-2.304v6.016c-0.512 0.128-0.992 0.224-1.376 0.352l-5.28 1.792c-1.024 0.352-1.856 1.536-1.856 2.624v6.048c-0 0.004-0 0.008-0 0.012 0 1.071 0.869 1.94 1.94 1.94 0.004 0 0.008 0 0.013-0h26.399c0.004 0 0.008 0 0.012 0 1.071 0 1.94-0.869 1.94-1.94 0-0.004 0-0.008-0-0.013v0.001-6.048c0-1.088-0.832-2.272-1.856-2.592zM15.872 26.88c-2.944 0-5.312-2.4-5.312-5.344s2.368-5.344 5.312-5.344c2.976 0 5.344 2.4 5.344 5.344s-2.368 5.344-5.344 5.344zM15.872 18.688c-1.568 0-2.848 1.28-2.848 2.848s1.28 2.848 2.848 2.848c1.6 0 2.88-1.28 2.88-2.848s-1.28-2.848-2.88-2.848z" fill="rgba(233.07000000000002,157.07999999999998,66.045,1)"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/assets/images/house.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
public/assets/images/man.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
6
public/assets/images/md-person.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="16" height="16" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
|
||||||
|
|
||||||
|
<g>
|
||||||
|
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" fill="rgba(129.03,179.01,55.08,1)"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 416 B |
BIN
public/assets/images/women.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
1
public/vite.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
7
src/App.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<router-view></router-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
1
src/assets/vue.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
10
src/components/info/HouseInfo.vue
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
|
</style>
|
10
src/components/info/PopulationInfo.vue
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
|
</style>
|
278
src/components/list/HouseList.vue
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
<template>
|
||||||
|
<n-space class="container" vertical>
|
||||||
|
<n-space class="title" align="center">
|
||||||
|
<label>以人找房</label>
|
||||||
|
<div class="search">
|
||||||
|
<input type="text" v-model="keywords" placeholder="请输入人名以查找房">
|
||||||
|
<Icon class="search-btn" @click="onSearchClick">
|
||||||
|
<Search24Filled />
|
||||||
|
</Icon>
|
||||||
|
</div>
|
||||||
|
</n-space>
|
||||||
|
<n-space class="body">
|
||||||
|
<div class="no-data" v-if="dataRows.length === 0">暂无数据</div>
|
||||||
|
<n-grid x-gap="30" :y-gap="15" :cols="2" v-if="dataRows.length > 0">
|
||||||
|
<n-grid-item v-for="data in dataRows" :key="data">
|
||||||
|
<n-space class="card" vertical justify="between">
|
||||||
|
<div class="top">
|
||||||
|
<n-image width="60" height="60" src="assets/images/house.png" :preview-disabled="true" />
|
||||||
|
<div class="info">
|
||||||
|
<div class="line">
|
||||||
|
<span class="title">{{ data.houseDTO.communityName }}</span>
|
||||||
|
<span class="type">{{ data.houseDTO.houseType }}</span>
|
||||||
|
<span class="housing-estate">{{ data.houseDTO.residentialName }}</span>
|
||||||
|
<span class="population">
|
||||||
|
<n-image width="15" height="15" src="assets/images/md-person.svg" :preview-disabled="true" />
|
||||||
|
<span class="name">{{ data.houseDTO.homeowner }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<span class="building-no">{{ data.houseDTO.buildingName }}楼/排</span>
|
||||||
|
<span class="building-unit">{{ data.houseDTO.affiliationUnit }}单元/列</span>
|
||||||
|
<span class="floor">{{ data.houseDTO.affiliationFloors }}层</span>
|
||||||
|
<span class="room-no">{{ data.houseDTO.houseNum }}号</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-space class="bottom">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>姓名</th>
|
||||||
|
<th>出生日期</th>
|
||||||
|
<th>证件类型</th>
|
||||||
|
<th>证件号码</th>
|
||||||
|
<th>联系方式</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="text" :title="data.populationInfoDTO.name">{{ data.populationInfoDTO.name }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text" :title="data.populationInfoDTO.birthday">{{ data.populationInfoDTO.birthday }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text" :title="data.populationInfoDTO.idcardType">{{ data.populationInfoDTO.idcardType }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text" :title="data.populationInfoDTO.idcard">{{ data.populationInfoDTO.idcard }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text" :title="data.populationInfoDTO.phone">{{ data.populationInfoDTO.phone }}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</n-space>
|
||||||
|
<div class="divider"></div>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
</n-grid>
|
||||||
|
</n-space>
|
||||||
|
<n-space class="footer">
|
||||||
|
<Pager :page="currentPage" :rows="rows" :total="total" @change="onPageChange" :key="pagerUpdateIndex"/>
|
||||||
|
</n-space>
|
||||||
|
</n-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, inject } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { NSpace, NInput, NGrid, NGridItem, NImage } from 'naive-ui';
|
||||||
|
import { Search24Filled } from '@vicons/fluent';
|
||||||
|
import { Icon } from '@vicons/utils';
|
||||||
|
import Pager from '../pager/Pager.vue'
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const axios = inject('axios');
|
||||||
|
const keywords = ref(route.query.keywords);
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const total = ref(0);
|
||||||
|
const rows = ref(10);
|
||||||
|
const pagerUpdateIndex = ref(0);
|
||||||
|
const dataRows = reactive([]);
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
axios.get('/api/population/findHouse', {
|
||||||
|
params: {
|
||||||
|
keywords: keywords.value,
|
||||||
|
page: currentPage.value,
|
||||||
|
rows: rows.value
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
currentPage.value = data.page;
|
||||||
|
total.value = data.total;
|
||||||
|
dataRows.splice(0, dataRows.length);
|
||||||
|
dataRows.push(...data.rows);
|
||||||
|
pagerUpdateIndex.value++;
|
||||||
|
}).catch(resp => {
|
||||||
|
console.log()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSearchClick = () => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPageChange = (pager) => {
|
||||||
|
currentPage.value = pager.page;
|
||||||
|
rows.value = pager.rows;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.container
|
||||||
|
.title
|
||||||
|
border-bottom 1px solid #FFFFFF
|
||||||
|
padding 10px 0
|
||||||
|
label
|
||||||
|
font-size 20px
|
||||||
|
a
|
||||||
|
font-size 13px
|
||||||
|
.search
|
||||||
|
border-radius 3px
|
||||||
|
position relative
|
||||||
|
.search-btn
|
||||||
|
font-size 30px
|
||||||
|
padding 3px
|
||||||
|
color #525e71
|
||||||
|
position absolute
|
||||||
|
top 1px
|
||||||
|
right 0px
|
||||||
|
cursor pointer
|
||||||
|
input
|
||||||
|
width 320px
|
||||||
|
padding 0 40px 0 15px
|
||||||
|
height 32px
|
||||||
|
border none
|
||||||
|
outline none
|
||||||
|
.body
|
||||||
|
width 840px
|
||||||
|
min-height 10px
|
||||||
|
padding 10px 0
|
||||||
|
.no-data
|
||||||
|
width 840px
|
||||||
|
text-align center
|
||||||
|
.card
|
||||||
|
width 385px
|
||||||
|
padding 10px
|
||||||
|
background-color rgba(255, 255, 255, 0.75)
|
||||||
|
border-radius 10px
|
||||||
|
position relative
|
||||||
|
cursor pointer
|
||||||
|
transition box-shadow 0.3s
|
||||||
|
&:hover
|
||||||
|
box-shadow 3px 3px 6px rgba(0,0,0,0.3)
|
||||||
|
.top
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
text-align left
|
||||||
|
.info
|
||||||
|
color #000000
|
||||||
|
font-size 12px
|
||||||
|
width 380px
|
||||||
|
margin-left 10px
|
||||||
|
.line
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content start
|
||||||
|
span
|
||||||
|
margin-right 10px
|
||||||
|
.title
|
||||||
|
font-size 14px
|
||||||
|
font-weight bold
|
||||||
|
border none
|
||||||
|
padding 0
|
||||||
|
.type
|
||||||
|
background-color #4095E5
|
||||||
|
padding 2px 10px
|
||||||
|
color #FFFFFF
|
||||||
|
border-radius 15px
|
||||||
|
transform scale(0.8)
|
||||||
|
.population
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
.name
|
||||||
|
margin-left 5px
|
||||||
|
margin-right 0
|
||||||
|
.tags
|
||||||
|
color #FFFFFF
|
||||||
|
width 320px
|
||||||
|
height 38px
|
||||||
|
display -webkit-box
|
||||||
|
-webkit-box-orient vertical
|
||||||
|
overflow hidden
|
||||||
|
-webkit-line-clamp 2
|
||||||
|
span
|
||||||
|
margin-right 3px
|
||||||
|
background-color red
|
||||||
|
padding 1px 10px
|
||||||
|
border-radius 10px
|
||||||
|
font-size 12px
|
||||||
|
transform scale(0.8)
|
||||||
|
& .orange
|
||||||
|
background-color orange
|
||||||
|
& .yellow
|
||||||
|
background-color yellow
|
||||||
|
color black
|
||||||
|
& .blue
|
||||||
|
background-color blue
|
||||||
|
& .green
|
||||||
|
background-color green
|
||||||
|
& .grey
|
||||||
|
background-color grey
|
||||||
|
.bottom
|
||||||
|
margin-top 14px
|
||||||
|
table
|
||||||
|
width 386px
|
||||||
|
border 0
|
||||||
|
border-collapse collapse
|
||||||
|
thead
|
||||||
|
background-color rgba(129, 179, 55, 0.23)
|
||||||
|
color #567722
|
||||||
|
tbody
|
||||||
|
.text
|
||||||
|
width 75px
|
||||||
|
overflow hidden
|
||||||
|
text-overflow ellipsis
|
||||||
|
white-space nowrap
|
||||||
|
color #333333
|
||||||
|
transform scale(0.8)
|
||||||
|
.divider
|
||||||
|
border 1px dotted #FEFEFE
|
||||||
|
position absolute
|
||||||
|
top 74px
|
||||||
|
left 0px
|
||||||
|
width 404px
|
||||||
|
&:before
|
||||||
|
content ' '
|
||||||
|
display block
|
||||||
|
width 10px
|
||||||
|
height 10px
|
||||||
|
background-color rgba(52, 88, 140, 1)
|
||||||
|
position absolute
|
||||||
|
left -6px
|
||||||
|
top -5px
|
||||||
|
border-radius 10px
|
||||||
|
&:after
|
||||||
|
content ' '
|
||||||
|
display block
|
||||||
|
width 10px
|
||||||
|
height 10px
|
||||||
|
background-color rgba(52, 88, 140, 1)
|
||||||
|
position absolute
|
||||||
|
right -6px
|
||||||
|
top -5px
|
||||||
|
border-radius 10px
|
||||||
|
.footer
|
||||||
|
border-top 1px solid #FFFFFF
|
||||||
|
padding 10px 0
|
||||||
|
</style>
|
291
src/components/list/PopulationList.vue
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
<template>
|
||||||
|
<n-space class="container" vertical>
|
||||||
|
<n-space class="title" align="center">
|
||||||
|
<label>以房找人</label>
|
||||||
|
<a href="javascript:void(0)" @click="onReseachClick">重新搜索</a>
|
||||||
|
</n-space>
|
||||||
|
<n-space class="body">
|
||||||
|
<div class="no-data" v-if="dataRows.length === 0">暂无数据</div>
|
||||||
|
<n-grid x-gap="30" :y-gap="15" :cols="2" v-if="dataRows.length > 0">
|
||||||
|
<n-grid-item v-for="data in dataRows" :key="data">
|
||||||
|
<n-space class="card" vertical justify="between">
|
||||||
|
<div class="top">
|
||||||
|
<n-image width="60" height="60" src="assets/images/women.png" :preview-disabled="true" v-if="data.sex === '女性'"/>
|
||||||
|
<n-image width="60" height="60" src="assets/images/man.png" :preview-disabled="true" v-else/>
|
||||||
|
<div class="info">
|
||||||
|
<div class="line">
|
||||||
|
<span class="name">{{ data.populationInfoHouseDTO.name }}</span>
|
||||||
|
<span class="sex" :class="{ female: data.populationInfoHouseDTO.sex === '女性' }">{{ data.populationInfoHouseDTO.sex }}</span>
|
||||||
|
<span class="age">17</span>
|
||||||
|
<span class="id-card">
|
||||||
|
<span class="type">{{ data.populationInfoHouseDTO.idcardType }}</span>
|
||||||
|
<span class="num">{{ data.populationInfoHouseDTO.idcard }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="line">
|
||||||
|
<span class="birth">{{ data.populationInfoHouseDTO.birthday }}</span>
|
||||||
|
<span class="phone">
|
||||||
|
<n-image width="15" height="15" src="assets/images/dial-phone.svg"
|
||||||
|
:preview-disabled="true" />
|
||||||
|
<span class="num">{{ data.populationInfoHouseDTO.phone }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="nation">{{ data.populationInfoHouseDTO.nation }}</span>
|
||||||
|
<span class="education">{{ data.populationInfoHouseDTO.education }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tags">
|
||||||
|
<span class="yellow" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isCorrect === '是'">社区矫正</span>
|
||||||
|
<span class="yellow" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isRelease === '是'">刑满释放</span>
|
||||||
|
<span class="grey" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isDispute === '是'">矛盾纠纷</span>
|
||||||
|
<span class="grey" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isSecurity === '是'">社会治安</span>
|
||||||
|
<span class="grey" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isDrug === '是'">吸毒人员</span>
|
||||||
|
<span class="grey" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isCult === '是'">涉邪人员</span>
|
||||||
|
<span class="grey" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isPetition === '是'">重点上访户</span>
|
||||||
|
<span class="red" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isSeriousIllness === '是'">重病</span>
|
||||||
|
<span class="orange" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isOldage === '是'">老年人</span>
|
||||||
|
<span class="blue" v-if="data.populationInfoHouseDTO.populationInfoBaseDTO.isMinority === '是'">未成年</span>
|
||||||
|
<span class="green" v-if="data.populationInfoHouseDTO.isNormal">正常</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-space class="bottom">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>社区</th>
|
||||||
|
<th>小区</th>
|
||||||
|
<th>楼/排</th>
|
||||||
|
<th>单元/列</th>
|
||||||
|
<th>院/层</th>
|
||||||
|
<th>门牌号</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.communityName }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.residentialName }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.buildingName }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.affiliationUnit }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.affiliationFloors }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text">{{ data.houseDTO.houseNum }}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</n-space>
|
||||||
|
<div class="divider"></div>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
</n-grid>
|
||||||
|
</n-space>
|
||||||
|
<n-space class="footer">
|
||||||
|
<Pager :page="currentPage" :rows="rows" :total="total" @change="onPageChange" :key="pagerUpdateIndex"/>
|
||||||
|
</n-space>
|
||||||
|
</n-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, inject } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { NSpace, NInput, NGrid, NGridItem, NImage } from 'naive-ui';
|
||||||
|
import Pager from '../pager/Pager.vue'
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const axios = inject('axios');
|
||||||
|
const query = route.query;
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const total = ref(0);
|
||||||
|
const rows = ref(10);
|
||||||
|
const pagerUpdateIndex = ref(0);
|
||||||
|
const dataRows = reactive([]);
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
axios.get('/api/population/findPopulation', {
|
||||||
|
params: {
|
||||||
|
...query,
|
||||||
|
page: currentPage.value,
|
||||||
|
rows: rows.value
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
currentPage.value = data.page;
|
||||||
|
total.value = data.total;
|
||||||
|
dataRows.splice(0, dataRows.length);
|
||||||
|
data.rows.forEach(item => {
|
||||||
|
item.populationInfoHouseDTO.isNormal = (
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isCorrect === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isRelease === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isDispute === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isSecurity === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isDrug === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isCult === '否' &&
|
||||||
|
item.populationInfoHouseDTO.populationInfoBaseDTO.isPetition === '否'
|
||||||
|
)
|
||||||
|
dataRows.push(item);
|
||||||
|
});
|
||||||
|
pagerUpdateIndex.value++;
|
||||||
|
}).catch(resp => {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPageChange = (pager) => {
|
||||||
|
currentPage.value = pager.page;
|
||||||
|
rows.value = pager.rows;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onReseachClick = () => {
|
||||||
|
router.push({
|
||||||
|
path: 'population-search'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.container
|
||||||
|
.title
|
||||||
|
border-bottom 1px solid #FFFFFF
|
||||||
|
padding 10px 0
|
||||||
|
label
|
||||||
|
font-size 20px
|
||||||
|
a
|
||||||
|
color #eeeeee
|
||||||
|
font-size 13px
|
||||||
|
.body
|
||||||
|
width 840px
|
||||||
|
min-height 10px
|
||||||
|
padding 10px 0
|
||||||
|
.no-data
|
||||||
|
width 840px
|
||||||
|
text-align center
|
||||||
|
.card
|
||||||
|
width 385px
|
||||||
|
padding 10px
|
||||||
|
background-color rgba(255, 255, 255, 0.75)
|
||||||
|
border-radius 10px
|
||||||
|
position relative
|
||||||
|
cursor pointer
|
||||||
|
transition box-shadow 0.3s
|
||||||
|
&:hover
|
||||||
|
box-shadow 3px 3px 6px rgba(0,0,0,0.3)
|
||||||
|
.top
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
text-align left
|
||||||
|
.info
|
||||||
|
color #000000
|
||||||
|
font-size 12px
|
||||||
|
width 380px
|
||||||
|
.line
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content space-between
|
||||||
|
.name
|
||||||
|
font-size 14px
|
||||||
|
font-weight bold
|
||||||
|
.sex
|
||||||
|
background-color #4095E5
|
||||||
|
padding 2px 10px
|
||||||
|
color #FFFFFF
|
||||||
|
border-radius 15px
|
||||||
|
transform scale(0.8)
|
||||||
|
.female
|
||||||
|
background-color #FF919C
|
||||||
|
.id-card
|
||||||
|
.type
|
||||||
|
margin-right 5px
|
||||||
|
.phone
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
|
||||||
|
.num
|
||||||
|
margin-left 5px
|
||||||
|
margin-right 0
|
||||||
|
.tags
|
||||||
|
color #FFFFFF
|
||||||
|
width 320px
|
||||||
|
height 38px
|
||||||
|
display -webkit-box
|
||||||
|
-webkit-box-orient vertical
|
||||||
|
overflow hidden
|
||||||
|
-webkit-line-clamp 2
|
||||||
|
span
|
||||||
|
margin-right 3px
|
||||||
|
background-color red
|
||||||
|
padding 1px 10px
|
||||||
|
border-radius 10px
|
||||||
|
font-size 12px
|
||||||
|
transform scale(0.8)
|
||||||
|
& .orange
|
||||||
|
background-color orange
|
||||||
|
& .yellow
|
||||||
|
background-color yellow
|
||||||
|
color black
|
||||||
|
& .blue
|
||||||
|
background-color blue
|
||||||
|
& .green
|
||||||
|
background-color green
|
||||||
|
& .grey
|
||||||
|
background-color grey
|
||||||
|
.bottom
|
||||||
|
padding-top 14px
|
||||||
|
table
|
||||||
|
width 386px
|
||||||
|
border 0
|
||||||
|
border-collapse collapse
|
||||||
|
thead
|
||||||
|
background-color rgba(129, 179, 55, 0.23)
|
||||||
|
color #567722
|
||||||
|
tbody
|
||||||
|
.text
|
||||||
|
width 62px
|
||||||
|
text-align center
|
||||||
|
overflow hidden
|
||||||
|
text-overflow ellipsis
|
||||||
|
white-space nowrap
|
||||||
|
color #333333
|
||||||
|
transform scale(0.8)
|
||||||
|
.divider
|
||||||
|
border 1px dotted #FEFEFE
|
||||||
|
position absolute
|
||||||
|
top 100px
|
||||||
|
left 0px
|
||||||
|
width 404px
|
||||||
|
&:before
|
||||||
|
content ' '
|
||||||
|
display block
|
||||||
|
width 10px
|
||||||
|
height 10px
|
||||||
|
background-color rgba(52, 88, 140, 1)
|
||||||
|
position absolute
|
||||||
|
left -6px
|
||||||
|
top -5px
|
||||||
|
border-radius 10px
|
||||||
|
&:after
|
||||||
|
content ' '
|
||||||
|
display block
|
||||||
|
width 10px
|
||||||
|
height 10px
|
||||||
|
background-color rgba(52, 88, 140, 1)
|
||||||
|
position absolute
|
||||||
|
right -6px
|
||||||
|
top -5px
|
||||||
|
border-radius 10px
|
||||||
|
.footer
|
||||||
|
border-top 1px solid #FFFFFF
|
||||||
|
padding 10px 0
|
||||||
|
</style>
|
171
src/components/pager/Pager.vue
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<span class="btn first" v-if="currentPage > 1" @click="onPageClick(1)">
|
||||||
|
<Icon>
|
||||||
|
<ArrowPrevious20Regular/>
|
||||||
|
</Icon>
|
||||||
|
</span>
|
||||||
|
<span class="btn before" v-if="currentPage > 1" @click="onPageClick(currentPage - 1)">
|
||||||
|
<Icon>
|
||||||
|
<ChevronLeft20Filled/>
|
||||||
|
</Icon>
|
||||||
|
</span>
|
||||||
|
<div class="btn-page">
|
||||||
|
<span class="btn" :class="{'active': currentPage === page}" v-for="page in pagerBtnArray" :key="page" @click="onPageClick(page)">{{ page }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="btn after" v-if="currentPage < totalPage" @click="onPageClick(currentPage + 1)">
|
||||||
|
<Icon>
|
||||||
|
<ChevronRight20Filled/>
|
||||||
|
</Icon>
|
||||||
|
</span>
|
||||||
|
<span class="btn last" v-if="currentPage < totalPage" @click="onPageClick(totalPage)">
|
||||||
|
<Icon>
|
||||||
|
<ArrowNext20Filled/>
|
||||||
|
</Icon>
|
||||||
|
</span>
|
||||||
|
<n-select size="small" v-model:value="pageSize.value" v-if="totalPage > 0" :options="pageSize.options" @update:value="onPageSizeUpdate"/>
|
||||||
|
<div class="jump" v-if="totalPage > 0">
|
||||||
|
<span>跳转</span>
|
||||||
|
<n-input-number size="small" placeholder="请输入" v-model:value="jumpPage.value" :min="jumpPage.min" :show-button="false"/>
|
||||||
|
<span>页</span>
|
||||||
|
<n-button @click="onPageJumpConfirmClick">确定</n-button>
|
||||||
|
</div>
|
||||||
|
<span>共 {{ totalPage }} 页 {{ props.total }} 条数据</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref, reactive, defineProps, defineEmits} from 'vue';
|
||||||
|
import {ArrowPrevious20Regular, ChevronLeft20Filled, ChevronRight20Filled, ArrowNext20Filled} from '@vicons/fluent';
|
||||||
|
import {Icon} from '@vicons/utils';
|
||||||
|
import {NSelect, NInputNumber, NButton} from 'naive-ui';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
page: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: Number,
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emits = defineEmits(['change']);
|
||||||
|
const pageSize = reactive({
|
||||||
|
value: props.rows,
|
||||||
|
options: [
|
||||||
|
{label: '10条/页', value: 10},
|
||||||
|
{label: '20条/页', value: 20},
|
||||||
|
{label: '40条/页', value: 40},
|
||||||
|
{label: '60条/页', value: 60},
|
||||||
|
{label: '80条/页', value: 80},
|
||||||
|
{label: '100条/页', value: 100},
|
||||||
|
{label: '200条/页', value: 200},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const jumpPage = reactive({
|
||||||
|
value: 1,
|
||||||
|
min: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分页按钮数量
|
||||||
|
const pagerSize = 5;
|
||||||
|
// 分页按钮分割数
|
||||||
|
const pagerHalfSize = pageSize % 2 === 0 ? parseInt(pagerSize / 2) : parseInt((pagerSize + 1) / 2);
|
||||||
|
// 总页数
|
||||||
|
const totalPage = ref(props.total % pageSize.value === 0 ? parseInt(props.total / pageSize.value) : parseInt(props.total / pageSize.value + 1));
|
||||||
|
const currentPage = ref(props.page);
|
||||||
|
const pagerBtnArray = reactive([]);
|
||||||
|
|
||||||
|
const renderPagerBtn = () => {
|
||||||
|
pagerBtnArray.splice(0, pagerBtnArray.length);
|
||||||
|
if(currentPage.value < pagerHalfSize) {
|
||||||
|
let pageBtnLength = pagerSize > totalPage.value ? totalPage.value : pagerSize;
|
||||||
|
for(let i = 0; i < pageBtnLength; i++) {
|
||||||
|
pagerBtnArray.push(i + 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(currentPage.value > totalPage.value - pagerHalfSize) {
|
||||||
|
for(let i = 0; i < pagerSize; i++) {
|
||||||
|
pagerBtnArray.push(totalPage.value - pagerSize + i + 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(let i = 0; i < pagerSize; i++) {
|
||||||
|
pagerBtnArray.push(currentPage.value - pagerHalfSize + i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPagerBtn();
|
||||||
|
|
||||||
|
const onPageClick = (page) => {
|
||||||
|
renderPagerBtn();
|
||||||
|
emits('change', {
|
||||||
|
page: page,
|
||||||
|
rows: pageSize.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const onPageSizeUpdate = (value, option) => {
|
||||||
|
emits('change', {
|
||||||
|
page: currentPage.value,
|
||||||
|
rows: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const onPageJumpConfirmClick = () => {
|
||||||
|
if(!jumpPage.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emits('change', {
|
||||||
|
page: jumpPage.value,
|
||||||
|
rows: pageSize.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.container
|
||||||
|
font-size 14px
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
user-select none
|
||||||
|
.btn
|
||||||
|
height 26px
|
||||||
|
line-height 26px
|
||||||
|
display inline-block
|
||||||
|
padding 0 10px
|
||||||
|
border-radius 5px
|
||||||
|
margin 0 2px
|
||||||
|
cursor pointer
|
||||||
|
&.active
|
||||||
|
color #3894FF
|
||||||
|
&.first
|
||||||
|
&.before
|
||||||
|
&.after
|
||||||
|
&.last
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
font-size 18px
|
||||||
|
min-width 30px
|
||||||
|
border 1px solid #FFFFFF
|
||||||
|
.jump
|
||||||
|
padding 0 5px
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
.n-input-number
|
||||||
|
margin 0 3px
|
||||||
|
width 60px
|
||||||
|
.n-button
|
||||||
|
height 28px
|
||||||
|
color #FFFFFF
|
||||||
|
margin-left 5px
|
||||||
|
.n-select
|
||||||
|
width 120px
|
||||||
|
margin 0 2px
|
||||||
|
</style>
|
66
src/components/search/HouseSearch.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="title">以人找房</div>
|
||||||
|
<div class="search">
|
||||||
|
<input type="text" placeholder="请输入人名以查找房" v-model="keywords">
|
||||||
|
<Icon class="search-btn" @click="onSearchClick">
|
||||||
|
<Search24Filled />
|
||||||
|
</Icon>
|
||||||
|
</div>
|
||||||
|
<div class="notes">请输入关键字:姓名、身份证、手机号等</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, inject } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { Search24Filled } from '@vicons/fluent';
|
||||||
|
import { Icon } from '@vicons/utils';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const keywords = ref('');
|
||||||
|
|
||||||
|
const onSearchClick = () => {
|
||||||
|
router.push({
|
||||||
|
path: '/house-list',
|
||||||
|
query: {
|
||||||
|
keywords: keywords.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.container
|
||||||
|
margin-top 200px
|
||||||
|
display flex
|
||||||
|
flex-direction column
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
.title
|
||||||
|
font-size 28px
|
||||||
|
font-weight bold
|
||||||
|
.search
|
||||||
|
margin-top 30px
|
||||||
|
border 2px solid #03DCDCDC
|
||||||
|
border-radius 3px
|
||||||
|
position relative
|
||||||
|
.search-btn
|
||||||
|
font-size 30px
|
||||||
|
padding 3px
|
||||||
|
color #525e71
|
||||||
|
position absolute
|
||||||
|
top 1px
|
||||||
|
right 0px
|
||||||
|
cursor pointer
|
||||||
|
input
|
||||||
|
width 600px
|
||||||
|
padding 0 40px 0 15px
|
||||||
|
height 37px
|
||||||
|
border none
|
||||||
|
outline none
|
||||||
|
.notes
|
||||||
|
margin-top 22px
|
||||||
|
font-size 12px
|
||||||
|
</style>
|
353
src/components/search/PopulationSearch.vue
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="title">以房找人</div>
|
||||||
|
<div class="search">
|
||||||
|
<n-grid x-gap="30" :y-gap="15" :cols="3">
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>所在街道</label>
|
||||||
|
<n-select v-model:value="street.value" :options="street.options" @update:value="onStreetUpdate"/>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>所在社区</label>
|
||||||
|
<n-select v-model:value="village.value" :options="village.options" @update:value="onVillageUpdate"/>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>所在小区</label>
|
||||||
|
<n-select v-model:value="housingEstate.value" :options="housingEstate.options" @update:value="onHousingEstateUpdate"/>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>楼/牌名称</label>
|
||||||
|
<n-select v-model:value="building.value" :options="building.options" @update:value="onBuildingUpdate"/>
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>所在单元/列</label>
|
||||||
|
<n-select v-model:value="buildingUnit.value" :options="buildingUnit.options" />
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>所在院层</label>
|
||||||
|
<n-select v-model:value="buildingFloor.value" :options="buildingFloor.options" />
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>门牌号</label>
|
||||||
|
<n-input v-model:value="houseNumber" placeholder="请输入门牌号" />
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>是否出租房</label>
|
||||||
|
<n-select v-model:value="rentalHousing.value" :options="rentalHousing.options" />
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
<n-grid-item>
|
||||||
|
<n-space class="search-condition" justify="space-between" align="center">
|
||||||
|
<label>是否空置房</label>
|
||||||
|
<n-select v-model:value="vacantHouse.value" :options="vacantHouse.options" />
|
||||||
|
</n-space>
|
||||||
|
</n-grid-item>
|
||||||
|
</n-grid>
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<n-button @click="onSearchClick">
|
||||||
|
<Icon class="icon">
|
||||||
|
<Search24Filled />
|
||||||
|
</Icon>
|
||||||
|
<label>搜索</label>
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { inject } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { NSpace, NGrid, NGridItem, NSelect, NInput, NButton } from 'naive-ui';
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { Search24Filled } from '@vicons/fluent';
|
||||||
|
import { Icon } from '@vicons/utils';
|
||||||
|
import { isSlotEmpty } from 'naive-ui/es/_utils';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const axios = inject('axios');
|
||||||
|
// 街道
|
||||||
|
const street = reactive({
|
||||||
|
value: 'song1',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 社区
|
||||||
|
const village = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 小区
|
||||||
|
const housingEstate = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 楼宇
|
||||||
|
const building = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 楼宇单元
|
||||||
|
const buildingUnit = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 楼宇楼层
|
||||||
|
const buildingFloor = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: '',
|
||||||
|
floors: '',
|
||||||
|
units: ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
// 门牌号
|
||||||
|
const houseNumber = ref('');
|
||||||
|
//
|
||||||
|
// 是否出租房
|
||||||
|
const rentalHousing = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}, {
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
}, {
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
// 是否空置房
|
||||||
|
const vacantHouse = reactive({
|
||||||
|
value: '',
|
||||||
|
options: [{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}, {
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
}, {
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
// 初始化街道
|
||||||
|
const initStreet = () => {
|
||||||
|
street.value = '';
|
||||||
|
street.options.splice(1, street.options.length - 1);
|
||||||
|
axios.get('/api/residential/getStreetList', {}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
data.forEach(item => {
|
||||||
|
street.options.push({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch(res => {});
|
||||||
|
}
|
||||||
|
// 初始化社区
|
||||||
|
const initVillage = (areaId) => {
|
||||||
|
village.value = '';
|
||||||
|
village.options.splice(1, village.options.length - 1);
|
||||||
|
if(!areaId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
axios.get('/api/residential/getCommunityList', {
|
||||||
|
params: {
|
||||||
|
areaId: areaId
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
data.forEach(item => {
|
||||||
|
village.options.push({
|
||||||
|
label: item.communityName,
|
||||||
|
value: item.communityId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch(res => {});
|
||||||
|
}
|
||||||
|
// 初始化小区
|
||||||
|
const initHousingEstate = (communityId) => {
|
||||||
|
housingEstate.value = '';
|
||||||
|
housingEstate.options.splice(1, housingEstate.options.length - 1);
|
||||||
|
if(!communityId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
axios.get('/api/residential/list', {
|
||||||
|
params: {
|
||||||
|
street: street.value,
|
||||||
|
community: communityId
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
data.forEach(item => {
|
||||||
|
housingEstate.options.push({
|
||||||
|
label: item.name,
|
||||||
|
value: item.residentialId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch(res => {});
|
||||||
|
}
|
||||||
|
// 初始化楼/牌
|
||||||
|
const initBuilding = (residentialId) => {
|
||||||
|
building.value = '';
|
||||||
|
building.options.splice(1, building.options.length - 1);
|
||||||
|
if(!residentialId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
axios.get('/api/building/list', {
|
||||||
|
params: {
|
||||||
|
residentialId: residentialId
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
let data = res.data;
|
||||||
|
data.forEach(item => {
|
||||||
|
building.options.push({
|
||||||
|
label: item.name,
|
||||||
|
value: item.buildingId,
|
||||||
|
floors: item.floorsNum,
|
||||||
|
units: item.unitNum
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch(res => {});
|
||||||
|
}
|
||||||
|
// 单元/列
|
||||||
|
const initBuildingUnit = (buildingUnitSize) => {
|
||||||
|
buildingUnit.value = '';
|
||||||
|
buildingUnit.options.splice(1, buildingUnit.options.length - 1);
|
||||||
|
if(!buildingUnitSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(let i = 1; i <= buildingUnitSize; i++) {
|
||||||
|
buildingUnit.options.push({
|
||||||
|
label: `${i}单元/列`,
|
||||||
|
value: i
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 楼层
|
||||||
|
const initBuildingFloor = (buildingFloorSize) => {
|
||||||
|
buildingFloor.value = '';
|
||||||
|
buildingFloor.options.splice(1, buildingFloor.options.length - 1);
|
||||||
|
if(!buildingFloorSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(let i = 1; i <= buildingFloorSize; i++) {
|
||||||
|
buildingFloor.options.push({
|
||||||
|
label: `${i}层/院`,
|
||||||
|
value: i
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 街道选择
|
||||||
|
const onStreetUpdate = (value, option) => {
|
||||||
|
initVillage(value);
|
||||||
|
initHousingEstate();
|
||||||
|
initBuilding();
|
||||||
|
initBuildingUnit();
|
||||||
|
initBuildingFloor();
|
||||||
|
}
|
||||||
|
// 社区选择
|
||||||
|
const onVillageUpdate = (value, option) => {
|
||||||
|
initHousingEstate(value);
|
||||||
|
initBuilding();
|
||||||
|
initBuildingUnit();
|
||||||
|
initBuildingFloor();
|
||||||
|
}
|
||||||
|
// 小区选择
|
||||||
|
const onHousingEstateUpdate = (value, option) => {
|
||||||
|
initBuilding(value);
|
||||||
|
initBuildingUnit();
|
||||||
|
initBuildingFloor();
|
||||||
|
}
|
||||||
|
// 楼宇选择
|
||||||
|
const onBuildingUpdate = (value, option) => {
|
||||||
|
initBuildingUnit(value ? option.units : null);
|
||||||
|
initBuildingFloor(value ? option.floors : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSearchClick = () => {
|
||||||
|
router.push({
|
||||||
|
path: '/population-list',
|
||||||
|
query: {
|
||||||
|
street: street.value,
|
||||||
|
community: village.value,
|
||||||
|
residentialId: housingEstate.value,
|
||||||
|
buildingId: building.value,
|
||||||
|
affiliationUnit: buildingUnit.value,
|
||||||
|
affiliationFloors: buildingFloor.value,
|
||||||
|
houseNum: houseNumber.value,
|
||||||
|
isRental: rentalHousing.value,
|
||||||
|
isVacant: vacantHouse.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initStreet();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.container
|
||||||
|
margin-top 200px
|
||||||
|
display flex
|
||||||
|
flex-direction column
|
||||||
|
justify-content center
|
||||||
|
align-content center
|
||||||
|
text-align center
|
||||||
|
.title
|
||||||
|
font-size 28px
|
||||||
|
font-weight bold
|
||||||
|
.search
|
||||||
|
margin-top 30px
|
||||||
|
.search-condition
|
||||||
|
.n-input
|
||||||
|
.n-select
|
||||||
|
border-radius 50px
|
||||||
|
overflow hidden
|
||||||
|
width 168px
|
||||||
|
.btn
|
||||||
|
margin-top 60px
|
||||||
|
.n-button
|
||||||
|
width 240px
|
||||||
|
height 30px
|
||||||
|
border-radius 15px
|
||||||
|
background-color #FFBF6B
|
||||||
|
color #FFFFFF
|
||||||
|
.icon
|
||||||
|
font-size 18px
|
||||||
|
label
|
||||||
|
margin-left 5px
|
||||||
|
cursor pointer
|
||||||
|
</style>
|
19
src/main.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import {router} from './route/route'
|
||||||
|
import './style.css'
|
||||||
|
import App from './App.vue'
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const createAxios = {
|
||||||
|
install(app, options) {
|
||||||
|
axios.defaults.baseURL = 'http://192.168.0.9:7023/population';
|
||||||
|
// axios.defaults.baseURL = '/population';
|
||||||
|
axios.defaults.timeout = 20000;
|
||||||
|
app.provide('axios', axios);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = createApp(App);
|
||||||
|
app.use(router);
|
||||||
|
app.use(createAxios);
|
||||||
|
app.mount('#app');
|
39
src/route/route.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||||
|
import PopulationSearch from '../components/search/PopulationSearch.vue';
|
||||||
|
import HouseSearch from '../components/search/HouseSearch.vue';
|
||||||
|
import PopulationList from '../components/list/PopulationList.vue';
|
||||||
|
import HouseList from '../components/list/HouseList.vue';
|
||||||
|
import PopulationInfo from '../components/info/PopulationInfo.vue';
|
||||||
|
import HouseInfo from '../components/info/HouseInfo.vue';
|
||||||
|
|
||||||
|
const routes = [{
|
||||||
|
name: '以人找房搜索',
|
||||||
|
path: '/population-search',
|
||||||
|
component: PopulationSearch
|
||||||
|
}, {
|
||||||
|
name: '以房找人搜索',
|
||||||
|
path: '/house-search',
|
||||||
|
component: HouseSearch
|
||||||
|
}, {
|
||||||
|
name: '以房找人列表',
|
||||||
|
path: '/population-list',
|
||||||
|
component: PopulationList
|
||||||
|
}, {
|
||||||
|
name: '以人找房列表',
|
||||||
|
path: '/house-list',
|
||||||
|
component: HouseList
|
||||||
|
}, {
|
||||||
|
name: '人口详情',
|
||||||
|
path: '/population-info',
|
||||||
|
component: PopulationInfo
|
||||||
|
}, {
|
||||||
|
name: '房屋详情',
|
||||||
|
path: '/house-info',
|
||||||
|
component: HouseInfo
|
||||||
|
}]
|
||||||
|
|
||||||
|
export const router = createRouter({
|
||||||
|
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
|
||||||
|
history: createWebHashHistory(),
|
||||||
|
routes, // `routes: routes` 的缩写
|
||||||
|
})
|
40
src/style.css
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
:root {
|
||||||
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: rgba(52, 88, 140, 1);
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-width: 320px;
|
||||||
|
min-height: 100%;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
max-width: 840px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
color: #213547;
|
||||||
|
background-color: rgba(52, 88, 140, 1);
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #747bff;
|
||||||
|
}
|
||||||
|
}
|
8
vite.config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
base: './',
|
||||||
|
plugins: [vue()],
|
||||||
|
})
|