Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
liyeyun
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cfld-frontend
liyeyun
Commits
e349f6bb
Commit
e349f6bb
authored
Dec 04, 2023
by
shilei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 列表筛选
parent
6e714dbc
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
780 additions
and
29 deletions
+780
-29
.eslintrc.cjs
.eslintrc.cjs
+2
-1
components.d.ts
components.d.ts
+6
-0
package-lock.json
package-lock.json
+0
-0
icon-close.png
src/assets/images/icon-close.png
+0
-0
base.scss
src/assets/styles/base.scss
+14
-0
main.scss
src/assets/styles/main.scss
+1
-0
reset.scss
src/assets/styles/reset.scss
+37
-2
CommonHeader.vue
src/components/common/CommonHeader.vue
+1
-1
config.ts
src/components/filter/config.ts
+157
-0
filter-view.vue
src/components/filter/filter-view.vue
+220
-0
list-carrier-item.vue
src/components/list/list-carrier-item.vue
+48
-0
list-land-item.vue
src/components/list/list-land-item.vue
+51
-0
useListView.ts
src/composable/useListView.ts
+3
-3
useQueryList.ts
src/composable/useQueryList.ts
+1
-1
filterEnum.ts
src/stores/filterEnum.ts
+32
-0
api.ts
src/types/api.ts
+6
-0
carrierList.ts
src/types/api/carrierList.ts
+59
-0
common.ts
src/types/common.ts
+18
-0
cities.json
src/utils/cities.json
+1
-2
MapView.vue
src/views/MapView.vue
+8
-8
CarrierList.vue
src/views/carrier/CarrierList.vue
+70
-2
LandList.vue
src/views/land/LandList.vue
+37
-7
vue.config.js
vue.config.js
+8
-2
yarn.lock
yarn.lock
+0
-0
No files found.
.eslintrc.cjs
View file @
e349f6bb
...
...
@@ -34,11 +34,12 @@ module.exports = {
'no-debugger': 'off',
'no-plusplus': 'off',
'no-shadow': 'off',
'no-param-reassign': ['error', { props: false }],
'@typescript-eslint/no-shadow': 'error',
'no-unused-vars': 'off',
'no-else-return': 'off',
'@typescript-eslint/no-unused-vars': 'error',
'vue-scoped-css/enforce-style-type': ['error', { allows: ['plain', 'scoped'] }],
'vue-scoped-css/enforce-style-type': ['error', { allows: ['plain', 'scoped'
, 'module'
] }],
'vue/block-order': [
'error',
{
...
...
components.d.ts
View file @
e349f6bb
...
...
@@ -8,6 +8,7 @@ export {}
declare
module
'vue'
{
export
interface
GlobalComponents
{
CommonHeader
:
typeof
import
(
'./src/components/common/CommonHeader.vue'
)[
'default'
]
copy
:
typeof
import
(
'./src/components/list/list-land-item copy.vue'
)[
'default'
]
DetailInfoCell
:
typeof
import
(
'./src/components/detail/DetailInfoCell.vue'
)[
'default'
]
DetailMain
:
typeof
import
(
'./src/components/detail/DetailMain.vue'
)[
'default'
]
ElButton
:
typeof
import
(
'element-plus/es'
)[
'ElButton'
]
...
...
@@ -20,6 +21,7 @@ declare module 'vue' {
ElForm
:
typeof
import
(
'element-plus/es'
)[
'ElForm'
]
ElFormItem
:
typeof
import
(
'element-plus/es'
)[
'ElFormItem'
]
ElHeader
:
typeof
import
(
'element-plus/es'
)[
'ElHeader'
]
ElIcon
:
typeof
import
(
'element-plus/es'
)[
'ElIcon'
]
ElInput
:
typeof
import
(
'element-plus/es'
)[
'ElInput'
]
ElMain
:
typeof
import
(
'element-plus/es'
)[
'ElMain'
]
ElMenu
:
typeof
import
(
'element-plus/es'
)[
'ElMenu'
]
...
...
@@ -32,8 +34,12 @@ declare module 'vue' {
ElSubMenu
:
typeof
import
(
'element-plus/es'
)[
'ElSubMenu'
]
ElSwitch
:
typeof
import
(
'element-plus/es'
)[
'ElSwitch'
]
ElTimePicker
:
typeof
import
(
'element-plus/es'
)[
'ElTimePicker'
]
Filter
:
typeof
import
(
'./src/components/filter/filter.vue'
)[
'default'
]
FilterView
:
typeof
import
(
'./src/components/filter/filter-view.vue'
)[
'default'
]
ListCarrierItem
:
typeof
import
(
'./src/components/list/list-carrier-item.vue'
)[
'default'
]
ListIndustryCategory
:
typeof
import
(
'./src/components/list/list-industryCategory.vue'
)[
'default'
]
ListLand
:
typeof
import
(
'./src/components/list/list-land.vue'
)[
'default'
]
ListLandItem
:
typeof
import
(
'./src/components/list/list-land-item.vue'
)[
'default'
]
ListPagination
:
typeof
import
(
'./src/components/list/list-pagination.vue'
)[
'default'
]
RouterLink
:
typeof
import
(
'vue-router'
)[
'RouterLink'
]
RouterView
:
typeof
import
(
'vue-router'
)[
'RouterView'
]
...
...
package-lock.json
View file @
e349f6bb
This diff is collapsed.
Click to expand it.
src/assets/images/icon-close.png
0 → 100644
View file @
e349f6bb
312 Bytes
src/assets/styles/base.scss
View file @
e349f6bb
@tailwind
base
;
@tailwind
components
;
@tailwind
utilities
;
/* 单行文字溢出虚点显 示*/
.ell
{
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
overflow
:
hidden
;
}
/* 两行文字溢出虚点显 示*/
.ell2
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
}
src/assets/styles/main.scss
View file @
e349f6bb
@import
'./base'
;
@import
'./reset'
;
src/assets/styles/reset.scss
View file @
e349f6bb
html
,
body
{
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
PingFang
SC
,
Microsoft
YaHei
,
Helvetica
Neue
,
Source
Han
Sans
SC
,
Noto
Sans
CJK
SC
,
WenQuanYi
Micro
Hei
,
sans-serif
;
html
,
body
{
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
PingFang
SC
,
Microsoft
YaHei
,
Helvetica
Neue
,
Source
Han
Sans
SC
,
Noto
Sans
CJK
SC
,
WenQuanYi
Micro
Hei
,
sans-serif
;
}
#app
{
.el-checkbox
{
margin-right
:
20px
;
}
.el-checkbox__input.is-checked
.el-checkbox__inner
{
background-color
:
#c0322b
;
border-color
:
#c0322b
;
}
.el-checkbox__input.is-checked
+
.el-checkbox__label
{
color
:
rgba
(
0
,
0
,
0
,
0
.65
);
}
.el-checkbox__label
{
font-size
:
12px
;
font-weight
:
400
;
color
:
rgba
(
0
,
0
,
0
,
0
.45
);
}
.
el-input__inner
:
:-
webkit-outer-spin-button
,
.
el-input__inner
::-
webkit-inner-spin-button
{
-webkit-appearance
:
none
;
}
.el-input__inner
[
type
=
'number'
]
{
-moz-appearance
:
textfield
;
}
}
src/components/common/CommonHeader.vue
View file @
e349f6bb
<
template
>
<div
class=
"
flex items-center justify-between pt-[12px] pl-[40px] header-view
"
>
<div
class=
"
header-view flex items-center justify-between pl-[40px] pt-[12px]
"
>
<!--
<div>
logo
</div>
-->
<div
class=
"flex flex-1 justify-start"
>
<ElMenu
...
...
src/components/filter/config.ts
0 → 100644
View file @
e349f6bb
export
const
defaultFiltersConfig
=
{
// 产业园级别
park_level
:
{
type
:
'select'
,
label
:
'产业园级别'
,
key
:
'levelName'
,
},
// 招商方向
park_direction
:
{
type
:
'select'
,
label
:
'招商方向'
,
key
:
'investmentDirection'
,
},
// 产业园面积
park_area
:
{
type
:
'select'
,
label
:
'产业园面积'
,
key
:
'coverArea'
,
plugins
:
{
type
:
'section'
,
unit
:
'亩'
,
},
},
// 产业资源
park_resources
:
{
type
:
'select'
,
label
:
'产业资源'
,
key
:
'parkResourcesList'
,
multiple
:
true
,
},
// 产业政策
industry_policy
:
{
type
:
'select'
,
label
:
'产业政策'
,
key
:
'industryPolicyList'
,
multiple
:
true
,
},
// 开发区级别
development_level
:
{
type
:
'select'
,
label
:
'开发区级别'
,
key
:
'levelName'
,
multiple
:
false
,
},
// 开发区类型
development_type
:
{
type
:
'select'
,
label
:
'开发区类型'
,
key
:
'type'
,
multiple
:
false
,
},
// 招商方向
development_direction
:
{
type
:
'select'
,
label
:
'招商方向'
,
key
:
'investmentDirection'
,
multiple
:
false
,
},
// 开发区面积
development_area
:
{
type
:
'select'
,
label
:
'开发区面积'
,
key
:
'planArea'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'平方公里'
,
},
},
// 土地价格
land_price
:
{
type
:
'select'
,
label
:
'土地价格'
,
key
:
'price'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'万元/亩'
,
},
},
// 土地类型
land_type
:
{
type
:
'select'
,
label
:
'土地类型'
,
key
:
'landType'
,
multiple
:
false
,
},
// 土地面积
land_area
:
{
type
:
'select'
,
label
:
'土地面积'
,
key
:
'area'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'亩'
,
},
},
// 载体面积
carrier_area
:
{
type
:
'select'
,
label
:
'载体面积'
,
key
:
'carrierArea'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'㎡'
,
},
},
// 载体类型
carrier_type
:
{
type
:
'select'
,
label
:
'载体类型'
,
key
:
'typeInfo'
,
multiple
:
false
,
},
// 建筑结构
carrier_construction
:
{
type
:
'select'
,
label
:
'建筑结构'
,
key
:
'carrierConstruction'
,
multiple
:
false
,
},
// 标准层高
floor_height
:
{
type
:
'select'
,
label
:
'标准层高'
,
key
:
'floorHeight'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'm'
,
},
},
// 标准承重
load_bearing
:
{
type
:
'select'
,
label
:
'标准承重'
,
key
:
'loadBearing'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'kg/㎡'
,
},
},
// 柱距
pillar_distance
:
{
type
:
'select'
,
label
:
'柱距'
,
key
:
'pillarDistance'
,
multiple
:
false
,
plugins
:
{
type
:
'section'
,
unit
:
'm'
,
},
},
};
src/components/filter/filter-view.vue
0 → 100644
View file @
e349f6bb
<
template
>
<div
class=
"filter-view"
>
<div
v-if=
"selected.length"
class=
"flex text-xs text-black/[.65]"
>
<span
class=
"w-[100px] shrink-0 leading-9 text-black/[.65]"
>
已选条件
</span>
<div
class=
"flex w-[701px] flex-wrap pt-1.5"
>
<span
v-for=
"(item, index) in selected"
:key=
"index"
class=
"selected-item mb-1 mr-2.5 flex items-center px-2 py-1 leading-none"
>
{{
item
.
label
}}
:
{{
Array
.
isArray
(
item
.
value
)
?
item
.
value
.
join
(
' | '
)
:
item
.
valueLabel
}}
<img
class=
"ml-2.5 h-3 w-3 cursor-pointer"
src=
"@/assets/images/icon-close.png"
alt=
""
@
click=
"removeSelected(item)"
/>
</span>
</div>
<div
class=
"ml-[15px] flex h-[25px] w-[104px] cursor-pointer items-center justify-center"
@
click=
"removeAll"
>
<img
class=
"h-3 w-3"
src=
"@/assets/images/icon-del.png"
alt=
""
/>
<span>
清空所有条件
</span>
</div>
</div>
<div
v-for=
"(filter, index) in filterList"
:key=
"index"
class=
"flex flex-wrap"
>
<div
class=
"w-[100px] shrink-0 text-xs leading-9 text-black/[.65]"
>
<span>
{{
filter
.
label
}}
</span>
</div>
<div>
<div
v-if=
"!filter.multiple"
class=
"flex pt-1.5 text-xs"
>
<div
class=
"shrink-0"
@
click=
"
filter.value = '';
filter.valueLabel = '';
"
>
<span
class=
"block cursor-pointer px-2 py-1 text-black/[0.45]"
:class=
"
{ selected: !filter.value }"
>
全部
</span>
</div>
<div
class=
"flex"
>
<div
v-for=
"(item, idx) in filter.list"
:key=
"idx"
class=
"Filter--keysWrap"
>
<div
class=
"Filter-ListWrap cursor-pointer px-2 py-1 text-black/[.45]"
:class=
"
{ selected: filter.value === item.dictValue }"
@click="handleFilterClick(item, filter)"
>
<span>
{{
item
.
dictLabel
}}
</span>
</div>
</div>
</div>
<div
v-if=
"filter.plugins"
class=
"ml-2 flex items-center"
>
<template
v-if=
"filter.plugins.type === 'section'"
>
<ElInput
v-model=
"filter.plugins.value1"
class=
"section-input"
type=
"number"
placeholder=
""
></ElInput>
<span
class=
"mx-1"
>
-
</span>
<ElInput
v-model=
"filter.plugins.value2"
class=
"section-input"
type=
"number"
placeholder=
""
></ElInput>
<span
class=
"ml-1 text-black/[0.45]"
>
{{
filter
.
plugins
.
unit
}}
</span>
<button
class=
"btn-default"
@
click=
"handleEnter(filter)"
>
确定
</button>
</
template
>
</div>
</div>
<div
v-else
>
<ElCheckboxGroup
v-model=
"filter.value"
>
<ElCheckbox
v-for=
"(item, idx) in filter.list"
:key=
"idx"
:label=
"item.dictLabel"
>
{{ item.dictLabel }}
</ElCheckbox>
</ElCheckboxGroup>
</div>
</div>
<div
class=
"Filter--operateWrap"
style=
"width: 100px"
></div>
</div>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
,
computed
,
watch
}
from
'vue'
;
import
{
FilterListItem
}
from
'@/types/common.ts'
;
import
{
filterStore
}
from
'@/stores/filterEnum.ts'
;
import
{
defaultFiltersConfig
}
from
'@/components/filter/config.ts'
;
import
{
isEmpty
}
from
'lodash-es'
;
const
props
=
defineProps
<
{
filterKeyList
:
string
[];
}
>
();
function
handleFilterClick
<
T
>
(
select
:
Ref
<
T
>
,
filters
:
Ref
<
T
>
)
{
console
.
log
(
select
,
filters
);
filters
.
value
=
select
.
dictValue
;
filters
.
valueLabel
=
select
.
dictLabel
;
console
.
log
(
filters
);
}
const
filterList
=
ref
<
FilterListItem
[]
>
([]);
onMounted
(
async
()
=>
{
const
store
=
filterStore
();
const
filterEnum
=
await
store
.
getFilterEnum
();
console
.
log
(
props
);
props
.
filterKeyList
.
forEach
((
item
)
=>
{
const
list
=
filterEnum
[
item
];
filterList
.
value
.
push
({
...
defaultFiltersConfig
[
item
],
list
});
});
});
// 处理输入
function
handleEnter
<
T
>
(
arg
:
Ref
<
T
>
)
{
if
(
!
isEmpty
(
arg
.
plugins
.
value1
)
||
!
isEmpty
(
arg
.
plugins
.
value2
))
{
if
(
isEmpty
(
arg
.
plugins
.
value2
))
{
arg
.
valueLabel
=
`≥
${
arg
.
plugins
.
value1
}${
arg
.
plugins
.
unit
}
`
;
arg
.
value
=
`
${
arg
.
plugins
.
value1
}
-`
;
}
else
if
(
isEmpty
(
arg
.
plugins
.
value1
))
{
arg
.
valueLabel
=
`≤
${
arg
.
plugins
.
value2
}${
arg
.
plugins
.
unit
}
`
;
arg
.
value
=
`0-
${
arg
.
plugins
.
value2
}
`
;
}
else
{
if
(
Number
(
arg
.
plugins
.
value1
)
>
Number
(
arg
.
plugins
.
value2
))
{
const
temp
=
arg
.
plugins
.
value1
;
arg
.
plugins
.
value1
=
arg
.
plugins
.
value2
;
arg
.
plugins
.
value2
=
temp
;
}
arg
.
valueLabel
=
`
${
arg
.
plugins
.
value1
}
-
${
arg
.
plugins
.
value2
}${
arg
.
plugins
.
unit
}
`
;
arg
.
value
=
`
${
arg
.
plugins
.
value1
}
-
${
arg
.
plugins
.
value2
}
`
;
}
}
}
// 删除已选筛选项
function
removeSelected
(
select
:
any
)
{
filterList
.
value
.
forEach
((
item
)
=>
{
if
(
item
.
label
===
select
.
label
)
{
item
.
value
=
Array
.
isArray
(
item
.
value
)
?
[]
:
''
;
if
(
item
.
plugins
)
{
item
.
plugins
.
value1
=
''
;
item
.
plugins
.
value2
=
''
;
}
}
});
}
// 已选项
const
selected
=
computed
(()
=>
{
let
temp
=
[];
temp
=
filterList
.
value
.
filter
((
item
)
=>
{
return
!
isEmpty
(
item
.
value
);
});
return
temp
||
[];
});
// 删除所有已选筛选项
function
removeAll
()
{
console
.
log
(
selected
.
value
);
for
(
const
i
of
selected
.
value
)
{
removeSelected
(
i
);
}
}
// 选项改变事件传递
const
emit
=
defineEmits
([
'change'
]);
watch
(
selected
,
(
newVal
)
=>
{
console
.
log
(
newVal
);
emit
(
'change'
,
selected
);
},
{
immediate
:
false
,
},
);
</
script
>
<
style
lang=
"scss"
scoped
>
.filter-view
{
background
:
#fbfbfb
;
padding-top
:
10px
;
padding-left
:
20px
;
width
:
926px
;
}
.selected
{
background
:
rgba
(
192
,
50
,
43
,
0
.06
);
color
:
#c0322b
;
}
.section-input
{
width
:
52px
;
::v-deep
{
.el-input__wrapper
{
border-radius
:
2px
;
padding
:
4px
8px
;
}
.el-input__inner
{
height
:
17px
;
}
}
}
.btn-default
{
background
:
#c0322b
;
width
:
44px
;
height
:
22px
;
color
:
#fff
;
margin-left
:
8px
;
font-size
:
12px
;
border-radius
:
2px
;
}
.selected-item
{
background
:
#f2f2f2
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0
.15
);
height
:
25px
;
line-height
:
15px
;
}
</
style
>
src/components/list/list-carrier-item.vue
0 → 100644
View file @
e349f6bb
<
template
>
<div
class=
"flex"
>
<div
class=
"media-left mr-[16px]"
>
<img
class=
"h-[156px] w-[208px]"
:src=
"detail.imgUrl"
alt=
""
/>
</div>
<div
class=
"media-right relative flex w-[408px] flex-col justify-between pt-[8px] text-[12px] leading-[20px] text-[#4d4d4d]"
>
<p
class=
"ell2 mb-[7px] text-[20px] font-semibold leading-[20px] text-[#1a1a1a]"
>
{{
detail
.
provinceName
?.
replace
(
'省'
,
''
).
replace
(
'市'
,
''
)
}}{{
detail
.
cityName
?.
replace
(
'市'
,
''
)
}}{{
detail
.
regionName
}}{{
detail
.
area
}}
㎡
{{
detail
.
type
}}
</p>
<div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-local.png"
alt=
""
/>
<p>
所在地区:
{{
detail
.
provinceName
}}
-
{{
detail
.
cityName
}}
-
{{
detail
.
regionName
}}
</p>
</div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-map.png"
alt=
""
/>
<p>
建筑面积:
{{
detail
.
area
}}
㎡
</p>
</div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-draw.png"
alt=
""
/>
<p>
载体类型:
{{
detail
.
type
}}
</p>
</div>
</div>
</div>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
type
{
CarrierListItem
}
from
'@/types/api/carrierList'
;
withDefaults
(
defineProps
<
{
detail
:
CarrierListItem
;
}
>
(),
{},
);
</
script
>
<
style
lang=
"scss"
scoped
>
.info-icon
{
width
:
16px
;
height
:
16px
;
margin-right
:
4px
;
}
</
style
>
src/components/list/list-land-item.vue
0 → 100644
View file @
e349f6bb
<
template
>
<div
class=
"flex"
>
<div
class=
"media-left mr-[16px]"
>
<img
class=
"h-[156px] w-[208px]"
:src=
"detail.imgUrl"
alt=
""
/>
</div>
<div
class=
"media-right relative flex w-[408px] flex-col justify-between pt-[8px] text-[12px] leading-[20px] text-[#4d4d4d]"
>
<p
class=
"ell2 mb-[7px] text-[20px] font-semibold leading-[20px] text-[#1a1a1a]"
>
{{
detail
.
provinceName
?.
replace
(
'省'
,
''
).
replace
(
'市'
,
''
)
}}{{
detail
.
cityName
?.
replace
(
'市'
,
''
)
}}{{
detail
.
regionName
}}{{
detail
.
area
}}
亩
{{
detail
.
landType
}}
</p>
<div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-local.png"
alt=
""
/>
<p>
所在地区:
{{
detail
.
provinceName
}}
-
{{
detail
.
cityName
}}
-
{{
detail
.
regionName
}}
</p>
</div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-map.png"
alt=
""
/>
<p>
占地面积:
{{
detail
.
area
}}
亩
</p>
</div>
<div
class=
"mb-[8px] flex items-center"
>
<img
class=
"info-icon"
src=
"@/assets/images/icon-draw.png"
alt=
""
/>
<p>
土地属性:
{{
detail
.
landType
}}
</p>
</div>
</div>
<div
class=
"absolute bottom-[8px] right-0 text-[20px] font-semibold text-[#C0322B]"
>
{{
detail
.
price
}}
元/亩
</div>
</div>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
type
{
LandListItem
}
from
'@/types/api/landList'
;
withDefaults
(
defineProps
<
{
detail
:
LandListItem
;
}
>
(),
{},
);
</
script
>
<
style
lang=
"scss"
scoped
>
.info-icon
{
width
:
16px
;
height
:
16px
;
margin-right
:
4px
;
}
</
style
>
src/composable/useListView.ts
View file @
e349f6bb
...
...
@@ -9,7 +9,7 @@ import { useRequest } from './useRequest.ts';
export
function
useListView
<
T
extends
{
id
:
number
;
[
index
:
string
]:
any
},
C
extends
Record
<
any
,
any
>
,
>
(
url
:
RequestUrl
)
{
>
(
url
:
RequestUrl
,
searchParams
:
any
=
{}
)
{
const
router
=
useRouter
();
const
{
request
:
requestList
}
=
useRequest
<
CommonListResp
<
T
>
,
CommonListParams
<
C
>>
(
url
,
{
method
:
'POST'
,
...
...
@@ -18,11 +18,11 @@ export function useListView<
const
{
pageNum
,
pageSize
,
totalCount
,
queryList
}
=
useQueryList
<
T
,
C
>
(
requestList
);
const
datas
=
ref
([])
as
Ref
<
T
[]
>
;
const
searchParams
=
ref
({})
as
Ref
<
C
>
;
//
const searchParams = ref({}) as Ref<C>;
watchEffect
(
async
()
=>
{
try
{
const
{
data
}
=
await
queryList
(
searchParams
.
value
);
const
{
data
}
=
await
queryList
(
searchParams
);
datas
.
value
=
data
.
records
;
}
catch
(
error
)
{
console
.
log
(
error
);
...
...
src/composable/useQueryList.ts
View file @
e349f6bb
...
...
@@ -26,7 +26,7 @@ export function useQueryList<T, C>(queryFn: QueryFn<T, CommonListParams<C>>) {
};
const
changePageNum
=
(
page
:
number
)
=>
{
page
Size
.
value
=
page
;
page
Num
.
value
=
page
;
};
const
changeTotalCount
=
(
total
:
number
)
=>
{
...
...
src/stores/filterEnum.ts
0 → 100644
View file @
e349f6bb
import
{
ref
}
from
'vue'
;
import
{
defineStore
}
from
'pinia'
;
import
{
useRequest
}
from
'@/composable/useRequest.ts'
;
import
{
RequestUrl
}
from
'@/types/api.ts'
;
import
type
{
FilterListItem
}
from
'@/types/common.ts'
;
import
type
{
Ref
}
from
'vue'
;
export
const
filterStore
=
defineStore
(
'filterEnum'
,
()
=>
{
const
filterEnum
:
any
=
ref
<
FilterListItem
[]
>
([]);
async
function
getFilterEnum
():
Promise
<
Ref
<
FilterListItem
>
|
Error
>
{
if
(
filterEnum
.
value
.
length
)
{
return
filterEnum
;
}
else
{
try
{
const
queryStr
=
'park_level,park_direction,park_area,park_resources,land_price,industry_policy,development_level,development_type,development_direction,development_area,industry_policy,land_type,land_area,carrier_area,carrier_type,carrier_construction,floor_height,load_bearing,pillar_distance'
;
const
{
request
:
getFilterList
}
=
useRequest
(
RequestUrl
.
getFiltersList
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/x-www-form-urlencoded'
,
},
});
const
data
=
await
getFilterList
({
code
:
queryStr
});
filterEnum
.
value
=
data
;
return
filterEnum
.
value
;
}
catch
(
error
:
any
)
{
return
new
Error
(
error
);
}
}
}
return
{
filterEnum
,
getFilterEnum
};
});
src/types/api.ts
View file @
e349f6bb
...
...
@@ -15,4 +15,10 @@ export enum RequestUrl {
landList
=
'/lyy/api/land/v1.0/page'
,
/** 土地详情 */
landDetail
=
'/lyy/api/land/v1.0/detail'
,
/** 载体列表 */
carrierList
=
'/lyy/api/carrier/v1.0/page'
,
/** 载体详情 */
carrierDetail
=
'/lyy/api/carrier/v1.0/detail'
,
/** 筛选项查询 */
getFiltersList
=
'/lyy/api/sysDictData/listByCodes'
,
}
src/types/api/carrierList.ts
0 → 100644
View file @
e349f6bb
/**
* 载体列表请求条件参数
*/
export
interface
CarrierListCondition
{
/** 面积 */
carrierArea
:
string
;
/** */
cityCode
:
string
;
/** */
cityName
:
string
;
/** 建筑结构 */
carrierConstruction
:
string
;
/** 载体名称 */
name
:
string
;
/** */
provinceCode
:
string
;
/** */
provinceName
:
string
;
/** */
regionCode
:
string
;
/** */
regionName
:
string
;
/** 标准层高 */
floorHeight
?:
string
;
/** 标准承重 */
loadBearing
?:
string
;
/** 柱距 */
pillarDistance
?:
string
;
/** 载体类型 */
typeInfo
?:
string
;
}
/**
* 载体列表项
*/
export
interface
CarrierListItem
{
/** 面积(亩) */
area
:
number
;
/** */
cityCode
:
string
;
/** */
cityName
:
string
;
/** */
id
:
number
;
/** 首屏图片 */
imgUrl
:
string
;
/** 载体类型 */
type
:
number
;
/** 地块名称 */
name
:
string
;
/** */
provinceCode
:
string
;
/** */
provinceName
:
string
;
/** */
regionCode
:
string
;
/** */
regionName
:
string
;
}
src/types/common.ts
View file @
e349f6bb
...
...
@@ -45,3 +45,21 @@ export interface CommonListParams<T> {
property
?:
string
;
}[];
}
/** *
* 筛选项
*/
export
type
FilterListItem
=
{
label
:
string
;
key
:
string
;
list
:
any
[];
type
:
string
;
multiple
?:
boolean
;
value
?:
string
|
string
[];
plugin
?:
{
type
:
string
;
unit
:
string
;
value1
?:
number
|
string
;
value2
?:
number
|
string
;
};
};
src/utils/cities.json
View file @
e349f6bb
...
...
@@ -18608,4 +18608,4 @@
"name"
:
"澳 门"
,
"children"
:
[]
}
]
\ No newline at end of file
]
src/views/MapView.vue
View file @
e349f6bb
...
...
@@ -53,8 +53,8 @@
</div>
<div
class=
"map-search-info"
>
<p
class=
"position-item"
v-for=
"item in infoList"
class=
"position-item"
@
mousemove=
"showInfoWindow(item)"
@
mouseout=
"hideInfoWindow"
>
...
...
@@ -79,7 +79,7 @@ interface Window {
};
let
placeSearch
:
any
=
null
;
let
infoWindow
:
any
=
null
;
le
t
markers
:
any
=
[];
cons
t
markers
:
any
=
[];
let
AMapRoot
:
any
=
null
;
onMounted
(()
=>
{
AMapLoader
.
load
({
...
...
@@ -123,7 +123,7 @@ onMounted(() => {
});
});
le
t
infoList
=
ref
<
any
[]
>
([]);
cons
t
infoList
=
ref
<
any
[]
>
([]);
const
handleSearch
=
(
keyWords
:
String
,
radius
:
Number
,
type
:
String
)
=>
{
map1
.
remove
(
markers
);
placeSearch
.
setType
(
type
);
...
...
@@ -136,7 +136,7 @@ const handleSearch = (keyWords: String, radius: Number, type: String) => {
console
.
log
(
'searchNearBy'
,
status
,
results
);
if
(
status
===
'complete'
)
{
infoList
.
value
=
results
.
poiList
.
pois
;
for
(
le
t
item
of
results
.
poiList
.
pois
)
{
for
(
cons
t
item
of
results
.
poiList
.
pois
)
{
const
marker
=
new
AMapRoot
.
Marker
({
map
:
map1
,
position
:
[
item
.
location
.
lng
,
item
.
location
.
lat
],
...
...
@@ -146,13 +146,13 @@ const handleSearch = (keyWords: String, radius: Number, type: String) => {
marker
.
on
(
'mouseover'
,
()
=>
{
console
.
log
(
'mouseover'
,
item
.
name
);
le
t
info
=
[];
cons
t
info
=
[];
info
.
push
(
"<div class='input-card'>"
);
info
.
push
(
`<p class='input-item'>
${
item
.
name
}
</p>`
);
info
.
push
(
`<p class='input-item'>
${
item
.
distance
}
米</p></div>`
);
infoWindow
=
new
AMapRoot
.
InfoWindow
({
content
:
info
.
join
(
''
),
//使用默认信息窗体框样式,显示信息内容
content
:
info
.
join
(
''
),
//
使用默认信息窗体框样式,显示信息内容
isCustom
:
true
,
autoMove
:
false
,
offset
:
new
AMapRoot
.
Pixel
(
0
,
-
35
),
...
...
@@ -174,12 +174,12 @@ const handleSearch = (keyWords: String, radius: Number, type: String) => {
};
const
showInfoWindow
=
(
info
:
any
)
=>
{
le
t
infoContent
=
[];
cons
t
infoContent
=
[];
infoContent
.
push
(
"<div class='input-card'>"
);
infoContent
.
push
(
`<p class='input-item'>
${
info
.
name
}
</p>`
);
infoContent
.
push
(
`<p class='input-item'>
${
info
.
distance
}
米</p></div>`
);
infoWindow
=
new
AMapRoot
.
InfoWindow
({
content
:
infoContent
.
join
(
''
),
//使用默认信息窗体框样式,显示信息内容
content
:
infoContent
.
join
(
''
),
//
使用默认信息窗体框样式,显示信息内容
isCustom
:
true
,
autoMove
:
false
,
offset
:
new
AMapRoot
.
Pixel
(
0
,
-
35
),
...
...
src/views/carrier/CarrierList.vue
View file @
e349f6bb
<!-- 载体 -->
<
template
>
<div>
载体
</div>
<div
class=
"container"
>
<FilterView
class=
"mb-6"
:filter-key-list=
"filterKeyList"
@
change=
"handleFilterChange"
></FilterView>
<div>
<!-- 载体列表 -->
<p>
搜索到
<span>
{{
totalCount
}}
</span>
个相关载体
</p>
<div>
<div
v-for=
"item in datas"
:key=
"item.id"
class=
"mb-5"
@
click=
"handleDetail(RouteName.landDetail, item)"
>
<CarrierListItemView
:detail=
"item"
></CarrierListItemView>
</div>
<ListPagination
v-model:current-page=
"pageNum"
v-model:page-size=
"pageSize"
:total=
"totalCount"
></ListPagination>
</div>
</div>
</div>
</
template
>
<
script
lang=
"ts"
setup
></
script
>
<
script
lang=
"ts"
setup
>
import
{
useListView
}
from
'@/composable/useListView.ts'
;
import
{
RouteName
}
from
'@/router/router.ts'
;
import
{
RequestUrl
}
from
'@/types/api.ts'
;
import
ListPagination
from
'@/components/list/list-pagination.vue'
;
import
CarrierListItemView
from
'@/components/list/list-carrier-item.vue'
;
import
FilterView
from
'@/components/filter/filter-view.vue'
;
import
type
{
CarrierListCondition
,
CarrierListItem
}
from
'@/types/api/carrierList'
;
import
{
ref
}
from
'vue'
;
const
{
pageNum
,
pageSize
,
totalCount
,
datas
,
handleDetail
,
queryList
}
=
useListView
<
CarrierListItem
,
CarrierListCondition
>
(
RequestUrl
.
carrierList
);
// 筛选项
const
filterKeyList
=
ref
([
'carrier_area'
,
'carrier_type'
,
'carrier_construction'
,
'floor_height'
,
'load_bearing'
,
'pillar_distance'
,
]);
// 处理筛选条件
const
handleFilterChange
=
async
function
(
selectList
)
{
const
temp
:
any
=
{};
for
(
const
item
of
selectList
.
value
)
{
temp
[
item
.
key
]
=
item
.
value
;
}
pageNum
.
value
=
1
;
const
{
data
}
=
await
queryList
(
temp
);
datas
.
value
=
data
.
records
;
};
</
script
>
<
style
lang=
"scss"
scoped
>
.container
{
width
:
926px
;
margin
:
0
auto
;
}
</
style
>
src/views/land/LandList.vue
View file @
e349f6bb
<!-- 土地列表 -->
<
template
>
<div>
<div
class=
"container"
>
<div>
<div
v-for=
"item in datas"
:key=
"item.id"
@
click=
"handleDetail(RouteName.landDetail, item)"
>
<div>
{{
item
.
name
}}
</div>
<FilterView
:filter-key-list=
"filterKeyList"
class=
"mb-6"
@
change=
"handleFilterChange"
></FilterView>
<div
v-for=
"item in datas"
:key=
"item.id"
class=
"mb-5"
@
click=
"handleDetail(RouteName.landDetail, item)"
>
<LandListItemView
:detail=
"item"
></LandListItemView>
</div>
<ListPagination
...
...
@@ -20,10 +30,30 @@ import { useListView } from '@/composable/useListView.ts';
import
{
RouteName
}
from
'@/router/router.ts'
;
import
{
RequestUrl
}
from
'@/types/api.ts'
;
import
ListPagination
from
'@/components/list/list-pagination.vue'
;
import
LandListItemView
from
'@/components/list/list-land-item.vue'
;
import
FilterView
from
'@/components/filter/filter-view.vue'
;
import
type
{
LandListCondition
,
LandListItem
}
from
'@/types/api/landList'
;
import
{
onMounted
,
ref
}
from
'vue'
;
const
{
pageNum
,
pageSize
,
totalCount
,
datas
,
handleDetail
}
=
useListView
<
LandListItem
,
LandListCondition
>
(
RequestUrl
.
landList
);
const
Response
=
useListView
<
LandListItem
,
LandListCondition
>
(
RequestUrl
.
landList
);
const
{
datas
,
pageNum
,
totalCount
,
pageSize
,
handleDetail
,
queryList
}
=
Response
;
const
filterKeyList
=
ref
([
'land_price'
,
'land_type'
,
'land_area'
]);
onMounted
(()
=>
{});
// 处理筛选条件
const
handleFilterChange
=
async
function
(
selectList
)
{
const
temp
:
any
=
{};
for
(
const
item
of
selectList
.
value
)
{
temp
[
item
.
key
]
=
item
.
value
;
}
pageNum
.
value
=
1
;
const
{
data
}
=
await
queryList
(
temp
);
datas
.
value
=
data
.
records
;
};
</
script
>
<
style
scoped
>
.container
{
width
:
926px
;
margin
:
0
auto
;
}
</
style
>
vue.config.js
View file @
e349f6bb
module
.
exports
=
{
lintOnSave
:
false
}
devServer
:
{
overlay
:
{
warnings
:
false
,
errors
:
false
,
},
lintOnSave
:
false
,
},
};
yarn.lock
0 → 100644
View file @
e349f6bb
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment