Commit 724d237c authored by 程卓's avatar 程卓

左侧完成并合并

parents 5460d60c bbbd85a7
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"qs": "^6.9.6", "qs": "^6.9.6",
"vue": "^3.0.5", "vue": "^3.0.5",
"vue-router": "^4.0.6",
"vuex": "^4.0.0" "vuex": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
......
<template> <template>
<Main /> <router-view />
<m-loader v-if="showLoading" /> <m-loader v-if="showLoading" />
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed } from 'vue' import { defineComponent, computed } from 'vue'
import Main from '@/view/main.vue'
import store from '@/store' import store from '@/store'
export default defineComponent({ export default defineComponent({
name: 'App', name: 'App',
components: { Main },
setup() { setup() {
const showLoading = computed(() => store.state.showLoading) const showLoading = computed(() => store.state.showLoading)
return { return {
......
...@@ -34,4 +34,9 @@ export default { ...@@ -34,4 +34,9 @@ export default {
GET_PUBLICSAFE_STREETPOWER: '/service-special-nandong/streetPower', // 网格工作站(原名街道力量) GET_PUBLICSAFE_STREETPOWER: '/service-special-nandong/streetPower', // 网格工作站(原名街道力量)
GET_PUBLICSAFE_PARTY: '/service-special-nandong/party', // 党建 GET_PUBLICSAFE_PARTY: '/service-special-nandong/party', // 党建
GET_PUBLICSAFE_ECONOMIC: '/service-special-nandong/economic', // 经济 GET_PUBLICSAFE_ECONOMIC: '/service-special-nandong/economic', // 经济
/** 小区屏 */
GET_COMMUNITY_INFO: '/service-special-nandong/bigscreenCommunity/statistical', // 小区档案
GET_COMMUNITY_FACILITY: '/service-special-nandong/communityRelations', // 小区设施
GET_ISSUE_LIST: '/service-special-nandong/management/factors', // 管理要素列表
GET_COMBINE_LIST: '/service-special-nandong/league/linkage', // 联勤联动列表
} }
...@@ -11,7 +11,7 @@ Axios.interceptors.request.use( ...@@ -11,7 +11,7 @@ Axios.interceptors.request.use(
(config) => { (config) => {
// 添加token // 添加token
config.headers.Authorization = config.headers.Authorization =
'bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMSIsImVuYWJsZSI6dHJ1ZSwic2NvcGUiOlsicmVhZCIsIndyaXRlIiwidHJ1c3QiXSwiZXhwIjoxNjE4Mzk3MTk3LCJqdGkiOiI1MDRmZjA1Ni04MzRjLTQzY2YtOWJkNC0zYmNkNjYyNGU3NzkiLCJjbGllbnRfaWQiOiJzc28iLCJ0aW1lc3RhbXAiOjE2MTgzODk5OTcyNzd9.DSqXZfmt7gsFpwaJrbwa_s-bETXaIL9f-kl4gzua158KiZi_TAkGfftFw-BFLF0irCcm_ZFVRoF5_BHhm4c73g7I-rPQw_lq54AoR2u0aejew1sTmXGh_0RLcAELPlQSQNJZfgqYVl9cEUABrupvXEBgU58-YseLFUvbGPR5NR_GbksV12r5sGAnNWvq5o0mtHHpBiI8eLWHN6q0pFlmfynRSqQ4KBLjwEPyhACgdtOPFMnHAN8I5Bjya1MP4vSbLHb5IHiii4rDfkYOZIyk_fNkb5P_Uvf6l7mUBeAx-RaUtcBtJ8tjzqKqZDUFs8Y5OBRQT4a1nsddonnpbMUPUQ' 'bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMCIsImVuYWJsZSI6dHJ1ZSwic2NvcGUiOlsicmVhZCIsIndyaXRlIiwidHJ1c3QiXSwiZXhwIjoxNjE4Mzg1MjgxLCJqdGkiOiI5ZTEyOTE0Zi1lNWJlLTRiZjktOTY4Zi0yYzk3ZjMwNmM0OWQiLCJjbGllbnRfaWQiOiJzc28iLCJ0aW1lc3RhbXAiOjE2MTgzNzgwODE2MTR9.PZQbXEaYoKqhZbpvan4rSCJNCJwYRr2Y9fAp_bj3l5FpAORHp6QDDHIBcFfdbQtBEOBOIFhqhji5DicD2-wJeqgEczfEUnWI_XGVTkw-aWBx7Qh4JTOeXOV2Gp1n_mY2tv4xGopoIOdfT2V9U19HyPJ25AtB0NZBzSxNfQtIw5Lt7PJX-jQf_W3b_N5U3cbU7qXtiGZSs-YxnoU-d65cXTIkODW5sU61jBg0RRAtBXeSlyznCrdTqrYIESp3ZgXUs7ie4MUxGurzNBDVCgplP6GRyLU1bQZlgxIi4ZnJPwxFKLMjIdko6JB6soNGIQu4WLyx3acK4zZo14Uk4_F8WQ'
return config return config
}, },
(error) => { (error) => {
...@@ -37,32 +37,32 @@ interface ParamsProp { ...@@ -37,32 +37,32 @@ interface ParamsProp {
interface RequestOptions { interface RequestOptions {
method?: method?:
| 'GET' | 'GET'
| 'get' | 'get'
| 'delete' | 'delete'
| 'DELETE' | 'DELETE'
| 'head' | 'head'
| 'HEAD' | 'HEAD'
| 'options' | 'options'
| 'OPTIONS' | 'OPTIONS'
| 'post' | 'post'
| 'POST' | 'POST'
| 'put' | 'put'
| 'PUT' | 'PUT'
| 'patch' | 'patch'
| 'PATCH' | 'PATCH'
| 'purge' | 'purge'
| 'PURGE' | 'PURGE'
| 'link' | 'link'
| 'LINK' | 'LINK'
| 'unlink' | 'unlink'
| 'UNLINK' | 'UNLINK'
| undefined | undefined
url: string url: string
params?: ParamsProp params?: ParamsProp
contentType?: contentType?:
| 'application/json;charset=UTF-8' | 'application/json;charset=UTF-8'
| 'application/x-www-form-urlencoded;charset=UTF-8' | 'application/x-www-form-urlencoded;charset=UTF-8'
showLoading?: boolean showLoading?: boolean
} }
......
<template>
<div class="card-wrapper">
<div class="card-title">
{{ title }}
<img class="tri" src="@/assets/images/modal-head-tri.png" />
<img class="tri" src="@/assets/images/modal-head-tri.png" />
</div>
<div class="card-content">
<slot />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
import flag from '@/assets/images/card-model2-flag.png'
export interface AdditionProp {
name?: string
value?: number
unit?: string
}
export default defineComponent({
name: 'Mode3',
props: {
title: {
type: String as PropType<string>,
required: true,
},
},
setup() {
return {
flag,
}
},
})
</script>
<style scoped lang="stylus">
@import '../main.styl'
.card-wrapper
$full()
.card-title
display flex
background linear-gradient(to bottom, transparent, rgba(0,148,255,.3))
position relative
color #D0EBEC
font-family $font-zcool
font-size $card-title-size
height .2rem
padding-left .2rem
align-items center
font-size .13rem
box-sizing border-box
border-bottom .01rem solid $primary-border
.tri
position absolute
left 0
width .2rem
&:nth-of-type(2)
left auto
right 0
transform rotate(180deg)
.card-content
display flex
flex-direction column
justify-content space-around
position relative
box-sizing border-box
padding .02rem .05rem
overflow hidden !important
>div
$full()
</style>
...@@ -13,10 +13,11 @@ import { computed, defineComponent, PropType } from 'vue' ...@@ -13,10 +13,11 @@ import { computed, defineComponent, PropType } from 'vue'
import MyAnimate from '../MyAnimate/my-animate.vue' import MyAnimate from '../MyAnimate/my-animate.vue'
import mode1 from './mode-1.vue' import mode1 from './mode-1.vue'
import mode2 from './mode-2.vue' import mode2 from './mode-2.vue'
import mode3 from './mode-3.vue'
import modeBorder from './mode-border.vue' import modeBorder from './mode-border.vue'
import '../main.styl' import '../main.styl'
type ModeType = '1' | '2' | 'border' type ModeType = '1' | '2' | '3' | 'border'
export default defineComponent({ export default defineComponent({
name: 'MyCard', name: 'MyCard',
...@@ -52,6 +53,8 @@ export default defineComponent({ ...@@ -52,6 +53,8 @@ export default defineComponent({
return mode1 return mode1
case '2': case '2':
return mode2 return mode2
case '3':
return mode3
case 'border': case 'border':
return modeBorder return modeBorder
default: default:
......
...@@ -38,27 +38,23 @@ export default defineComponent({ ...@@ -38,27 +38,23 @@ export default defineComponent({
top: '20%', top: '20%',
containLabel: true, containLabel: true,
}, },
xAxis: [ xAxis: {
{ type: 'category',
type: 'category', boundaryGap: false,
boundaryGap: false, axisLine: {
axisLine: { lineStyle: {
lineStyle: { color: 'rgba(47,134,238,0.3)',
color: 'rgba(47,134,238,0.3)',
},
}, },
}, },
], },
yAxis: [ yAxis: {
{ type: 'value',
type: 'value', splitLine: {
splitLine: { lineStyle: {
lineStyle: { color: 'rgba(47,134,238,0.3)',
color: 'rgba(47,134,238,0.3)',
},
}, },
}, },
], },
} }
const defaultSeriesItem = { const defaultSeriesItem = {
type: 'line', type: 'line',
......
<template> <template>
<teleport to="#MyLoader"> <teleport to="#MyLoader">
<div class="my-loader-mask"> <div class="my-loader-mask" :style="`background:${background}`">
<div class="my-loader"> <div class="my-loader">
<div class="outer" /> <div class="outer" />
<div class="middle" /> <div class="middle" />
<div class="inner" /> <div class="inner" />
</div> </div>
<slot />
</div> </div>
</teleport> </teleport>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent, PropType } from 'vue'
import useDOMCreate from '@/hooks/useDOMCreate' import useDOMCreate from '@/hooks/useDOMCreate'
export default defineComponent({ export default defineComponent({
name: 'MyLoader', name: 'MyLoader',
displayName: 'm-loader', displayName: 'm-loader',
props: {
background: {
type: String as PropType<string>,
default: 'rgba(0,0,0,0.3)',
},
},
setup() { setup() {
useDOMCreate('MyLoader') useDOMCreate('MyLoader')
}, },
...@@ -30,9 +37,9 @@ export default defineComponent({ ...@@ -30,9 +37,9 @@ export default defineComponent({
right 0 right 0
bottom 0 bottom 0
left 0 left 0
background rgba(0,0,0,0.3)
z-index 99999 z-index 99999
$center() $center()
flex-direction column
.my-loader .my-loader
position relative position relative
.outer, .outer,
......
...@@ -3,15 +3,30 @@ ...@@ -3,15 +3,30 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, nextTick, onMounted, ref } from 'vue' import { defineComponent, nextTick, onMounted, PropType } from 'vue'
declare const SMap: any declare const SMap: any
declare const Plugins: any declare const Plugins: any
interface PointProp {
data: unknown[]
key: string
labelKey?: string
icon?: string
size?: number | number[]
color?: string
}
export default defineComponent({ export default defineComponent({
name: 'MyMap', name: 'MyMap',
displayName: 'm-map', displayName: 'm-map',
props: {
config: {
type: Object as PropType<{ [key: string]: unknown }>,
default: null,
},
},
emits: ['complete', 'event'], emits: ['complete', 'event'],
setup(_, ctx) { setup(props, ctx) {
let map: any = null let map: any = null
onMounted(async () => { onMounted(async () => {
await nextTick() await nextTick()
...@@ -21,21 +36,22 @@ export default defineComponent({ ...@@ -21,21 +36,22 @@ export default defineComponent({
map = new SMap.Map('MapContainer', { map = new SMap.Map('MapContainer', {
viewMode: '3D', viewMode: '3D',
center: [1141.75319496382872, -480.0854532701907], center: [1141.75319496382872, -480.0854532701907],
zooms: [6, 9], zooms: [5, 10],
zoom: 7, zoom: 7,
pitch: 45, pitch: 45,
mapStyle: 'smap://styles/dark', // 'smap://styles/dark' 'smap://styles/image' mapStyle: 'smap://styles/dark',
showBuildingBlock: true, showBuildingBlock: true,
...props.config,
}).on(SMap.MapEvent.maploaded, () => { }).on(SMap.MapEvent.maploaded, () => {
ctx.emit('complete') ctx.emit('complete', map)
hideCommunity() hideCommunity()
addListener() addListener()
map.getLayer('model_white_zw').visible = true // map.getLayer('model_white_zw').visible = true
map.getLayer('model_white_WEIHAI33').visible = true // map.getLayer('model_white_WEIHAI33').visible = true
map.getLayer('model_white_zhenxing2').visible = true // map.getLayer('model_white_zhenxing2').visible = true
map.getLayer('model_white_zw').opacity = 0.8 // map.getLayer('model_white_zw').opacity = 0.8
map.getLayer('model_white_WEIHAI33').opacity = 0.8 // map.getLayer('model_white_WEIHAI33').opacity = 0.8
map.getLayer('model_white_zhenxing2').opacity = 0.8 // map.getLayer('model_white_zhenxing2').opacity = 0.8
}) })
} }
function hideCommunity() { function hideCommunity() {
...@@ -43,12 +59,13 @@ export default defineComponent({ ...@@ -43,12 +59,13 @@ export default defineComponent({
map.hideMPZ() map.hideMPZ()
map.hideXQ_Point() map.hideXQ_Point()
} }
// function showCommunity() { function showCommunity() {
// map.showXQ_Poly() map.showXQ_Poly()
// map.showMPZ() map.showMPZ()
// map.showXQ_Point() map.showXQ_Point()
// } }
function addListener() { function addListener() {
map.enableMouseEvent(false)
// 触发地图点击事件 // 触发地图点击事件
map.on(SMap.MapEvent.click, (view: any, eventParamter: any) => { map.on(SMap.MapEvent.click, (view: any, eventParamter: any) => {
const { x, y } = eventParamter.mapPoint const { x, y } = eventParamter.mapPoint
...@@ -74,7 +91,7 @@ export default defineComponent({ ...@@ -74,7 +91,7 @@ export default defineComponent({
console.error('传入的坐标点不能为空') console.error('传入的坐标点不能为空')
return return
} }
map.setZoomAndCenter(zoom, [+x, +y]) map.setZoomAndCenter(zoom, [+x, +y, 0])
} }
// 添加边界 // 添加边界
...@@ -98,9 +115,72 @@ export default defineComponent({ ...@@ -98,9 +115,72 @@ export default defineComponent({
return Boundary return Boundary
} }
function rotate(deg: number) {
map.setRotation(deg)
}
// 将数据转换为符合地图的点数组
function getMapPoints({
data = [],
key,
labelKey,
icon,
size,
color = '#47B3FF',
}: PointProp) {
return data.map((item: any) => {
let sizeProp = Array.isArray(size)
? new SMap.Size(size[0], size[1])
: new SMap.Size(size, size)
if (item.size) {
sizeProp = Array.isArray(item.size)
? new SMap.Size(item.size[0], item.size[1])
: new SMap.Size(item.size, item.size)
}
const result = {
icon: new SMap.Icon({
size: sizeProp,
image: item.icon || icon,
}),
attributes: { key, ...item },
position: [
item.communityMinx || item.X || item.x || item.gpsx,
item.communityMiny || item.Y || item.y || item.gpsy,
item.communityMinz || item.Z || item.z || item.gpsz || 0,
],
label: null,
}
if (labelKey) {
result.label = new SMap.Label({
text: (item[labelKey] || item[key]) + '',
size,
color,
})
}
return new SMap.Marker(result)
})
}
// 添加点
function addPoint({
key,
data = [],
labelKey = '',
icon = 'test.png',
size = 14,
color = '#47B3FF',
}: PointProp) {
if (!map) return
const points = getMapPoints({ data, key, labelKey, icon, size, color })
map.add(points)
return points
}
return { return {
focus, focus,
hideCommunity,
showCommunity,
addBoundary, addBoundary,
rotate,
addPoint,
} }
}, },
}) })
......
...@@ -64,7 +64,7 @@ export default defineComponent({ ...@@ -64,7 +64,7 @@ export default defineComponent({
() => props.length <= 100 && props.length >= props.limit () => props.length <= 100 && props.length >= props.limit
) )
const start = () => { const start = () => {
if (!props.length) { if (!props.length && props.length !== 0) {
console.error('MyScroll 需要length参数!') console.error('MyScroll 需要length参数!')
return return
} }
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
> >
<div class="before" :style="{ top: `${percent}%`, background: color }" /> <div class="before" :style="{ top: `${percent}%`, background: color }" />
<div class="after" :style="{ top: `${percent}%`, background: color }" /> <div class="after" :style="{ top: `${percent}%`, background: color }" />
<p><m-count :value="value" /> %</p> <slot>
<p><m-count :value="value" /> %</p>
</slot>
</div> </div>
</template> </template>
......
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import MyComponent from '@/components/MyComponent' import MyComponent from '@/components/MyComponent'
import router from '@/router'
import { Progress, Select, Input } from 'ant-design-vue' import { Progress, Select, Input } from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css' import 'ant-design-vue/dist/antd.css'
import './assets/style/reset.styl' import './assets/style/reset.styl'
createApp(App) createApp(App)
.use(router)
.use(MyComponent) .use(MyComponent)
.use(Progress) .use(Progress)
.use(Select) .use(Select)
......
import { createRouter, createWebHashHistory } from 'vue-router'
import routes from './routes'
const router = createRouter({
history: createWebHashHistory(),
routes,
})
export default router
import Main from '@/view/main.vue'
import CommunityView from '@/view/community.vue'
export default [
{ name: 'main', path: '/', component: Main },
{ name: 'community', path: '/community', component: CommunityView },
]
...@@ -281,4 +281,39 @@ export default { ...@@ -281,4 +281,39 @@ export default {
// console.log(content, '经济') // console.log(content, '经济')
commit('SET_PUBLICSAFE_ECONOMIC', content) commit('SET_PUBLICSAFE_ECONOMIC', content)
}, },
/** 小区屏 */
initCommunityData({ dispatch }: { dispatch: Dispatch }, id: string): void {
dispatch('getCommunityInfo', id)
dispatch('getIssueList', id)
dispatch('getCombineList', id)
},
async getCommunityInfo({ commit }: { commit: Commit }): Promise<void> {
const { content } = (await ajax.get({ url: api.GET_COMMUNITY_INFO })).data
commit('SET_COMMUNITY_INFO', content[1])
},
async getIssueList(
{ commit }: { commit: Commit },
id: string
): Promise<void> {
const { content } = (
await ajax.get({
url: api.GET_ISSUE_LIST,
params: { bigscreenCommunityId: id },
})
).data
commit('SET_ISSUE_DATA', content)
},
async getCombineList(
{ commit }: { commit: Commit },
id: string
): Promise<void> {
const { content } = (
await ajax.get({
url: api.GET_COMBINE_LIST,
params: { bigscreenCommunityId: id },
})
).data
commit('SET_COMBINE_DATA', content)
},
} }
...@@ -6,8 +6,35 @@ import actions from './actions' ...@@ -6,8 +6,35 @@ import actions from './actions'
export type ThemeType = 'manage' | 'service' | 'safety' export type ThemeType = 'manage' | 'service' | 'safety'
export interface ViewType { export interface ViewType {
name: string name: string
type: 'street' | 'work1' | 'work2' | 'work3' type: 'street' | 'work1' | 'work2' | 'work3' | 'community'
} }
export interface CommunityInfoProp {
bigscreenCommunityName: string // 小区名称
chargingPile: number //充电桩
totCommunity: number //小区数
totCmp: number //物业企业数
totForOld: number //为老设施
parkingSpace: number //车棚
totHous: number //总户数
communityList: { sectName: string; sectId: string }[] // 小区列表
icMember: unknown[] // 业委会列表
}
export interface IssueProp {
date: string //日期
securityScore: number //安全
cleanScore: number //干净
orderlyScore: number //有序
totalScore: number //综合评分
}
export interface CombineProp {
cleanList: { [key: string]: any }[]
securityList: { [key: string]: any }[]
orderlyList: { [key: string]: any }[]
[key: string]: { [key: string]: any }[]
}
export interface GlobalStateProps { export interface GlobalStateProps {
showLoading: boolean showLoading: boolean
curView: ViewType curView: ViewType
...@@ -33,6 +60,11 @@ export interface GlobalStateProps { ...@@ -33,6 +60,11 @@ export interface GlobalStateProps {
pubulicLeftStreetPower: any[] pubulicLeftStreetPower: any[]
pubulicLeftParty: { [key: string]: number } pubulicLeftParty: { [key: string]: number }
pubulicLeftEconomic: { [key: string]: string } pubulicLeftEconomic: { [key: string]: string }
/** 小区页面 */
communityInfo: Partial<CommunityInfoProp>
issueData: IssueProp[]
combineData: CombineProp
} }
export default createStore<GlobalStateProps>({ export default createStore<GlobalStateProps>({
state, state,
......
import { GlobalStateProps, ThemeType, ViewType } from './index' import {
GlobalStateProps,
ThemeType,
ViewType,
CommunityInfoProp,
IssueProp,
CombineProp,
} from './index'
export default { export default {
SET_LOADING(state: GlobalStateProps, val: boolean): void { SET_LOADING(state: GlobalStateProps, val: boolean): void {
...@@ -19,7 +26,7 @@ export default { ...@@ -19,7 +26,7 @@ export default {
SET_CASE_LIST(state: GlobalStateProps, data: unknown[]): void { SET_CASE_LIST(state: GlobalStateProps, data: unknown[]): void {
state.caseList = data state.caseList = data
}, },
SET_MUTATION_LIST(state: GlobalStateProps, data: unknown[]): void { SET_STATION_LIST(state: GlobalStateProps, data: unknown[]): void {
state.stationList = data state.stationList = data
}, },
SET_PUBLICSAFE_GATESENTRY_SHEHUIWUYE( SET_PUBLICSAFE_GATESENTRY_SHEHUIWUYE(
...@@ -142,4 +149,14 @@ export default { ...@@ -142,4 +149,14 @@ export default {
): void { ): void {
state.pubulicLeftEconomic = data state.pubulicLeftEconomic = data
}, },
/** 小区页面 */
SET_COMMUNITY_INFO(state: GlobalStateProps, data: CommunityInfoProp): void {
state.communityInfo = data
},
SET_ISSUE_DATA(state: GlobalStateProps, data: IssueProp[]): void {
state.issueData = data
},
SET_COMBINE_DATA(state: GlobalStateProps, data: CombineProp): void {
state.combineData = data
},
} }
...@@ -30,4 +30,7 @@ export default { ...@@ -30,4 +30,7 @@ export default {
pubulicLeftStreetPower: [], pubulicLeftStreetPower: [],
pubulicLeftParty: {}, pubulicLeftParty: {},
pubulicLeftEconomic: {}, pubulicLeftEconomic: {},
communityInfo: {},
issueData: [],
combineData: { cleanList: [], securityList: [], orderlyList: [] },
} as GlobalStateProps } as GlobalStateProps
<template>
<m-loader v-if="loading" background="#000">
<p style="color: #fff; margin-top: 0.3rem">地图初始化…</p>
</m-loader>
<m-grid
:template="['title title title', 'left . right']"
columns="16vw auto 49vw"
rows="0.4rem auto"
gap="0.05rem"
>
<m-title area="title">南东城运</m-title>
<m-map
ref="map"
:config="{ center: [-75.5563452697323, -718.3061904627932], zoom: 8 }"
@complete="handleComplete"
@event="handleMapClick"
/>
<m-animate enter="fadeInLeft" leave="fadeOutLeft">
<LeftSection area="left" />
</m-animate>
<m-animate enter="fadeInRight" leave="fadeOutRight">
<RightSection area="right" />
</m-animate>
<div class="btns">
<div
v-for="btn in btns"
:key="btn"
:class="{ on: btn === curBtn }"
@click="handleClick(btn)"
>
<p>{{ btn }}</p>
</div>
</div>
</m-grid>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue'
import LeftSection from '@/view/community/left-section.vue'
import RightSection from '@/view/community/right-section.vue'
import store from '@/store'
import point from '@/assets/images/point.png'
import { useRoute } from 'vue-router'
export default defineComponent({
name: 'Main',
components: { LeftSection, RightSection },
setup() {
const loading = ref(true)
const initData = (id: unknown) => {
store.dispatch('initCommunityData', id || '527635870583459840')
}
onMounted(() => {
initData(useRoute().query.id)
})
store.commit('SET_CURRENT_VIEW', { name: '', type: 'community' }) // 使标题不显示公共的3个按钮
const map = ref<any>(null)
const initMap = () => {
const points = map.value.addPoint({
key: 'test',
size: [100, 500],
icon: point,
data: [{ name: '测试', x: -275.5563452697323, y: -718.3061904627932 }],
})
console.log('points', points)
}
const handleMapClick = (e: any) => {
console.log('point-data: ', e)
}
const handleComplete = (instance: any) => {
instance.getLayer('model_white_zhenxing2').visible = true
instance.getLayer('model_white_zhenxing2').opacity = 0.8
// instance.getLayer('model_white_zw').visible = true
// instance.getLayer('model_white_WEIHAI33').visible = true
// instance.getLayer('model_white_zw').opacity = 0.8
// instance.getLayer('model_white_WEIHAI33').opacity = 0.8
let i = -90
map.value.rotate(i)
setTimeout(() => {
loading.value = false
setTimeout(() => {
const timer = setInterval(() => {
i += 2
if (i > 0) {
setTimeout(() => {
map.value.focus(-75.5563452697323, -718.3061904627932, 9)
}, 500)
clearInterval(timer)
initMap()
}
map.value.rotate(i)
}, 2)
}, 1000)
}, 7000)
}
const btns = ref(['微更新', '电梯加装', '智能监控', '楼宇安全'])
const curBtn = ref<string | null>(null)
const handleClick = (btn: string) => {
if (curBtn.value === btn) {
curBtn.value = null
return
}
curBtn.value = btn
}
return {
loading,
map,
handleComplete,
handleMapClick,
btns,
curBtn,
handleClick,
}
},
})
</script>
<style lang="stylus" scoped>
@import '../components/MyComponent/main.styl'
.btns
position fixed
z-index 9999
width 35vw
left 16vw
bottom .1rem
display flex
justify-content space-around
>div
min-width 1.1rem
text-align center
background url('@/assets/images/map-btn-bg.png') 100% / 100% 100% no-repeat
font-family $font-zcool
font-size .18rem
color #ccc
cursor pointer
opacity .8
transition all .3s ease-in-out
position relative
p
transform translateY(-40%)
&:hover
color #fff
opacity 1
&.on
color #fff
opacity 1
p
-webkit-box-reflect below -0.17rem linear-gradient(transparent, rgba(255,255,255,.6))
&:after
content ''
display block
position absolute
height .06rem
bottom 0
left 0
right 0
background rgba(91,213,255,.4)
box-shadow 0 0 0.1rem 0.02rem rgba(91,213,255,.5)
</style>
<template>
<m-card mode="3" title="联勤联动">
<div class="tabs">
<span
v-for="tab in tabs"
:key="tab.key"
:class="{ on: curTab === tab.key }"
@click="curTab = tab.key"
>
{{ tab.name }}
</span>
</div>
<div class="card-container">
<m-scroll
v-if="list.length > 0"
:length="list.length"
:mode="2"
:limit="5"
:step="1.25"
>
<div v-for="(item, i) in list" :key="i" class="card">
<div class="title">
{{ item.bigscreenCommunityName }}
<span />
<p>{{ item.troublePhenomenon }}</p>
</div>
<div class="info">
<p>{{ item.address }}</p>
<p>{{ item.acceptTime }}</p>
</div>
<Step :current="steps.indexOf(item.phase)" :steps="steps" />
</div>
</m-scroll>
<m-empty v-else style="height:5rem;" />
</div>
</m-card>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import Step from '../components/step.vue'
import store from '@/store'
export default defineComponent({
name: 'Combine',
components: { Step },
setup() {
const curTab = ref('securityList')
const tabs = ref([
{ key: 'securityList', name: '安全' },
{ key: 'cleanList', name: '干净' },
{ key: 'orderlyList', name: '有序' },
])
const list = computed(() => store.state.combineData[curTab.value] || [])
// const list = ref([
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 2,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 3,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 4,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 5,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 2,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 3,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 4,
// },
// {
// name: '振兴小区',
// type: '电梯困人',
// address: '上海市黄浦区延安东路1292弄6~40号',
// date: '2020-03-13 13:23:08',
// cur: 5,
// },
// ])
return {
steps: ['发现', '立案', '派遣', '处置', '核查', '结案'],
tabs,
curTab,
list,
}
},
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.tabs
border-bottom .01rem solid rgba(255,255,255,.2)
padding-bottom .02rem
span
padding .025rem 0
color #ccc
margin 0 .15rem
cursor pointer
transition all .3s ease
border-bottom .03rem solid transparent
&:hover
color #fff
&.on
color #fff
font-weight bold
border-color $secondary-color
.card-container
overflow hidden
max-height 5rem
.card
background url('@/assets/images/card-bg.png') 100% / 100% 100% no-repeat
box-sizing border-box
padding .15rem .1rem 0
height 1.25rem
overflow hidden
display flex
flex-direction column
justify-content space-between
.title
font-size .12rem
display flex
align-items center
span
margin 0 .1rem
flex 1
display block
height .01rem
background $blue
p
font-size .1rem
color $secondary-color
.info
display flex
justify-content space-between
color $blue
</style>
<template>
<div class="community-photo">
<div
v-for="item in list"
:key="item.name"
:style="`background:url(${item.photo}) 100% / 100% 100% no-repeat`"
>
<p>{{ item.name }}</p>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import photo1 from '@/assets/images/community1.png'
import photo2 from '@/assets/images/community2.png'
import photo3 from '@/assets/images/community3.png'
export default defineComponent({
name: 'CommunityPhoto',
setup() {
return {
list: [
{ name: '重庆北路205号入口', photo: photo1 },
{ name: '重庆北路205号道路', photo: photo2 },
{ name: '重庆北路205号电梯', photo: photo3 },
],
}
},
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.community-photo
$full()
display flex
flex-direction column
justify-content space-between
padding .05rem
>div
height 32%
position relative
>p
position absolute
right 0
bottom 0
padding .05rem .1rem
border-radius .1rem 0 0 0
color $secondary-color
background rgba(8,28,52,.5)
</style>
<template>
<m-card mode="border">
<m-card title="小区档案" mode="3">
<div class="info">
<div><img src="@/assets/images/zhenxing.png" /></div>
<div>
<h3>振兴小区</h3>
<div>
<div>
<img src="@/assets/images/p11.png" />
<div>
<p>健康</p>
<m-count class="count" :value="92" />
</div>
</div>
<div>
<img src="@/assets/images/p12.png" />
<div>
<p>疫苗接种率</p>
<m-count class="count" :value="57" />%
</div>
</div>
</div>
</div>
</div>
<div>
<Brief :list="summary.slice(0, 3)" size="0.32rem" />
<h1></h1>
<Brief :list="summary.slice(3)" size="0.32rem" />
</div>
<div class="buildings">
<div
v-for="item in buildingList"
:key="item.sectId"
:class="{ on: curBuilding === item.sectId }"
@click="selectBuilding(item.sectId)"
>
{{ item.sectName }}
</div>
</div>
<div class="address">
<div
v-for="(item, i) in addrList"
:key="i"
:style="`border-left-color: ${getColor(item.classification)}`"
>
<div>
<img :src="getIcon(item.relationName)" />
<p>{{ item.sectName }}</p>
</div>
<div class="type">
<span>{{ item.relationName }}</span>
<span>{{ item.classification }}</span>
</div>
<i :style="`background:${getColor(item.classification)}`" />
</div>
</div>
<div class="industry">
<div class="title">
<img src="@/assets/images/p9.png" />
业委会
</div>
<div class="content">
<div v-for="(item, i) in memberList" :key="i">
<p>{{ item.dirName }}</p>
<p>{{ getDuty(item.dirDuty) }}</p>
<p>{{ item.hocName }}</p>
</div>
</div>
</div>
</m-card>
</m-card>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue'
import Brief, { BriefProp } from '@/view/components/brief.vue'
import p1 from '@/assets/images/p1.png'
import p2 from '@/assets/images/p2.png'
import p3 from '@/assets/images/p3.png'
import p4 from '@/assets/images/p4.png'
import p5 from '@/assets/images/p5.png'
import p6 from '@/assets/images/p6.png'
import type1 from '@/assets/images/type1.png'
import type2 from '@/assets/images/type2.png'
import type3 from '@/assets/images/type3.png'
import type4 from '@/assets/images/type4.png'
import type5 from '@/assets/images/type5.png'
import type6 from '@/assets/images/type6.png'
import type7 from '@/assets/images/type7.png'
import store from '@/store'
import { ajax, api } from '@/ajax'
export default defineComponent({
name: 'LeftSection',
components: { Brief },
setup() {
const summary = ref<BriefProp[]>([])
const buildingList = ref<unknown[]>([])
const curBuilding = ref<string | null>(null)
const memberList = ref<unknown[]>([])
const addrList = ref([])
watch(
() => store.state.communityInfo,
(cur) => {
const {
totCommunity = 0,
totHous = 0,
totCmp = 0,
chargingPile = 0,
parkingSpace = 0,
totForOld = 0,
communityList = [],
} = cur
summary.value = [
{ name: '小区数', value: totCommunity, icon: p1 },
{ name: '总户数', value: totHous, icon: p2 },
{ name: '物业企业', value: totCmp, icon: p3 },
{ name: '充电桩', value: chargingPile, icon: p4 },
{ name: '车棚', value: parkingSpace, icon: p5 },
{ name: '为老设施', value: totForOld, icon: p6 },
]
buildingList.value = communityList
curBuilding.value =
(communityList[0] && communityList[0].sectId) || null
selectBuilding(curBuilding.value)
},
{ deep: true, immediate: true }
)
const getColor = (type: string): string => {
switch (type) {
case '门岗':
return '#826AFA'
case '为老':
return '#FF6161'
case '小区设施':
return '#8ED617'
default:
return '#fff'
}
}
const getIcon = (type: string): string => {
if (!type) return type2
if (type.indexOf('集合') >= 0) return type3
if (type.indexOf('助餐') >= 0) return type6
if (type.indexOf('助浴') >= 0) return type7
if (type.indexOf('充电') >= 0) return type1
if (type.indexOf('车棚') >= 0) return type5
if (type.indexOf('垃圾') >= 0) return type4
return type2
}
const getDuty = (type: string): string => {
switch (type) {
case '1':
return '主任'
case '2':
return '预留印鉴副主任'
case '3':
return '副主任'
default:
return '业委会成员'
}
}
async function selectBuilding(id: string | null): Promise<void> {
if (!id) return
curBuilding.value = id
addrList.value = (
await ajax.get({
url: api.GET_COMMUNITY_FACILITY,
params: { sectId: id },
})
).data.content.filter((item: any) => item.classification != '微更新')
memberList.value =
(
buildingList.value &&
(buildingList.value.find(
(b: any) => b.sectId === curBuilding.value
) as any)
).icMember || []
}
return {
summary,
buildingList,
curBuilding,
addrList,
getColor,
getIcon,
memberList,
getDuty,
selectBuilding,
}
},
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.info
display flex
min-height .8rem
margin-top .03rem
>div
flex 1
color #ccc
text-align justify
&:first-child
flex .56
$center()
background url('@/assets/images/border3.png') 50% 50% / 100% 100% no-repeat
margin-right .1rem
> img
width 88%
&:last-child
display flex
flex-direction column
justify-content space-around
h3
color #ccc
font-size .13rem
margin 0
>div
display flex
>div
flex 1
display flex
img
width .25rem
height @width
margin-right .1rem
p
color #aaa
font-size .09rem
.count
color #fff
font-size .2rem
font-family $font-pang
.buildings
display flex
justify-content space-between
>div
$center()
width 23%
height .4rem
background url('@/assets/images/num-card.png') 100% / 100% 100% no-repeat
cursor pointer
position relative
color #aaa
opacity .8
text-align center
padding 0 .08rem
&:hover
opacity 1
color #fff
&.on
color #fff
opacity 1
&:after
content ''
display block
position absolute
width 40%
height 100%
border .01rem solid $edge
left 0
right 0
margin 0 auto
opacity .2
box-shadow 0 0 .05rem .02rem $edge
.address
display flex
flex-wrap wrap
>div
display flex
flex-direction column
justify-content space-around
width 48%
padding .03rem .07rem
box-sizing border-box
position relative
margin-bottom .06rem
margin-right @margin-bottom
background rgba(33,58,89,.2)
border .01rem solid rgba(91,213,255,.1)
border-left .02rem solid transparent
overflow hidden
min-height .6rem
>div
display flex
align-items center
p
color #aaa
flex 1
img
width .15rem
height @width
margin-right .1rem
.type
display flex
justify-content space-between
font-size .08rem
i
position absolute
right -0.1rem
bottom -0.1rem
width .2rem
height .2rem
transform rotate(45deg)
opacity .4
.industry
.title
display flex
align-items center
font-family $font-zcool
font-size .14rem
color $edge
img
width .18rem
height @width
margin-right .05rem
.content
display flex
justify-content space-between
flex-wrap wrap
overflow hidden
>div
flex 1
display flex
flex-direction column
justify-content center
padding .05rem .08rem
min-height .5rem
margin-bottom .05rem
margin-right @margin-bottom
background url('@/assets/images/border.png') 100% / 100% 100% no-repeat
p
font-size .08rem
color #aaa
&:first-child
font-size .09rem
color #fff
</style>
<template>
<m-card mode="3" title="管理要素">
<div class="sum">
<m-wave
class="ball"
size=".76rem"
:value="92"
color="rgba(91,213,255,.6)"
>
<span class="sum-txt">
评分 <m-count class="count" :value="totalValue"></m-count>
</span>
</m-wave>
</div>
<div class="counts">
<div v-for="item in counts" :key="item.name">
<Circle
:value="item.value"
type="dashboard"
:show-info="false"
:color="[getColor(item.value), '#FF0C0C']"
:rate="1.2"
:stroke-width="8"
:gap-degree="100"
>
<div class="count-txt">
<m-count
class="count"
:value="item.value"
:style="`color:${getColor(item.value)};
text-shadow:0 0 .05rem ${getColor(item.value)}`"
/>
<p>{{ item.name }}</p>
</div>
</Circle>
</div>
</div>
<div class="chart">
<m-line :dataset="data" :option="option" />
</div>
<div class="issue">
<div class="title">
<img src="@/assets/images/p9.png" />
评分要素
</div>
<div class="content">
<div v-for="item in issues" :key="item.name">
<p>{{ item.name }}</p>
<m-count class="count" :value="item.value" />
</div>
</div>
</div>
</m-card>
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { ChartTypes } from '@/components/MyComponent'
import Circle from '../components/circle.vue'
import store from '@/store'
import dayjs from 'dayjs'
export default defineComponent({
name: 'ManageIssue',
components: { Circle },
setup() {
const counts = ref<{ name: string; value: number }[]>([])
const totalValue = ref(0)
const data = ref()
watch(
() => store.state.issueData,
(issueData) => {
if (!issueData || issueData.length === 0) return
const {
securityScore = 0,
cleanScore = 0,
orderlyScore = 0,
totalScore = 0,
} = issueData && issueData[0]
counts.value = [
{ name: '安全', value: securityScore },
{ name: '干净', value: cleanScore },
{ name: '有序', value: orderlyScore },
]
totalValue.value = totalScore
data.value = {
dimensions: [
{ name: 'date', displayName: '日期' },
{ name: 'securityScore', displayName: '安全' },
{ name: 'cleanScore', displayName: '干净' },
{ name: 'orderlyScore', displayName: '有序' },
],
source: issueData.map((item: any) =>
Object.assign({}, item, {
date: item.date && dayjs(item.date).format('MMDD'),
})
),
}
},
{ deep: true, immediate: true }
)
const getColor = (count: number) => {
if (count <= 60) return '#FF9C15'
if (count < 90) return '#FFE211'
else return '#19FF2B'
}
const option = ref<ChartTypes.LineOption>({
color: [
'#0094FF',
'#7F72F5',
'#F76B1C',
// ['#1EFBFF', '#0094FF'],
// ['#7F72F5', '#C86DD7'],
// ['#FAD961', '#F76B1C'],
],
legend: { right: '5%' },
xAxis: { axisLabel: { interval: 0 } },
yAxis: {
min: (value: any) => value.min - 2,
max: 100,
},
})
const issues = ref([
{ name: '绿化面积㎡', value: 658 },
{ name: '监控点位', value: 28 },
{ name: '垃圾箱房', value: 15 },
{ name: '非机动车位', value: 150 },
{ name: '物业服务人员', value: 168 },
])
return {
counts,
totalValue,
getColor,
data,
option,
issues,
}
},
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.sum
position relative
height 1.2rem
background url('@/assets/images/issue-bg2.png') 100% / 100% 100% no-repeat
.ball
margin-top 8%
margin-left 15%
.sum-txt
z-index 99
font-size .09rem
color #ccc
.count
color #fff
font-size .16rem
font-family $font-pang
.counts
display flex
margin-top .1rem
>div
flex 1
.count-txt
position absolute
left 50%
top 50%
transform translate(-50%, -50%)
text-align center
font-size .09rem
color #ccc
.count
font-size .18rem
font-family $font-pang
font-weight 500
.chart
height 1.5rem
.issue
.title
display flex
align-items center
font-family $font-zcool
font-size .14rem
color $edge
img
width .18rem
height @width
margin-right .05rem
.content
display flex
flex-wrap wrap
justify-content space-around
>div
width 32%
min-height .6rem
background url('@/assets/images/count-bg.png') 100% / 100% 100% no-repeat
text-align center
font-size .08rem
color $blue
.count
font-family $font-pang
font-size .16rem
color #fff
</style>
<template>
<div class="right-section">
<m-card mode="border">
<CommunityPhoto />
</m-card>
<m-card mode="border">
<ManageIssue />
</m-card>
<m-card mode="border">
<Combine />
</m-card>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import CommunityPhoto from './community-photo.vue'
import ManageIssue from './manage-issue.vue'
import Combine from './combine.vue'
export default defineComponent({
name: 'RightSection',
components: { CommunityPhoto, ManageIssue, Combine },
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.right-section
$full()
display flex
justify-content space-between
>div
height 100%
width 33%
.beauty1
flex 1
.beauty2
flex 1.6
</style>
<template> <template>
<div class="brief-container"> <div class="brief-container">
<div v-for="item in list" :key="item.name"> <div v-for="item in list" :key="item.name">
<img v-if="item.icon" :src="item.icon" /> <img
v-if="item.icon"
:src="item.icon"
:style="`width:${size};height:${size}`"
/>
<div v-if="Array.isArray(item.value)"> <div v-if="Array.isArray(item.value)">
<div class="count-group"> <div class="count-group">
<m-count class="count yellow" :value="item.value[0]" /> <m-count class="count yellow" :value="item.value[0]" />
...@@ -41,6 +45,10 @@ export default defineComponent({ ...@@ -41,6 +45,10 @@ export default defineComponent({
type: String as PropType<string>, type: String as PropType<string>,
default: null, default: null,
}, },
size: {
type: String as PropType<string>,
default: '0.22rem',
},
}, },
}) })
</script> </script>
...@@ -60,8 +68,6 @@ export default defineComponent({ ...@@ -60,8 +68,6 @@ export default defineComponent({
display flex display flex
align-items center align-items center
>img >img
width .22rem
height @width
margin-right .05rem margin-right .05rem
>div >div
font-weight bold font-weight bold
......
<template> <template>
<div ref="circleWrapperRef" class="circle-wrapper"> <div ref="circleWrapperRef" class="circle-wrapper">
<a-progress <a-progress
type="circle"
:width="width" :width="width"
:stroke-color="strokeColor" :stroke-color="strokeColor"
:percent="value" :percent="value"
:type="type"
:show-info="showInfo"
:stroke-width="strokeWidth"
:gap-degree="gapDegree"
/> />
<p v-if="name">{{ name }}</p> <slot>
<p>{{ name }}</p>
</slot>
</div> </div>
</template> </template>
...@@ -16,6 +21,10 @@ import { computed, defineComponent, PropType, ref } from 'vue' ...@@ -16,6 +21,10 @@ import { computed, defineComponent, PropType, ref } from 'vue'
export default defineComponent({ export default defineComponent({
name: 'Circle', name: 'Circle',
props: { props: {
type: {
type: String as PropType<'line' | 'circle' | 'dashboard'>,
default: 'circle',
},
color: { color: {
type: [String, Array] as PropType<string | string[]>, type: [String, Array] as PropType<string | string[]>,
default: ['#0094FF', '#1DF9FF'], default: ['#0094FF', '#1DF9FF'],
...@@ -28,6 +37,22 @@ export default defineComponent({ ...@@ -28,6 +37,22 @@ export default defineComponent({
type: String as PropType<string>, type: String as PropType<string>,
default: '', default: '',
}, },
showInfo: {
type: Boolean as PropType<boolean>,
default: true,
},
rate: {
type: Number as PropType<number>,
default: 1.8,
},
strokeWidth: {
type: Number as PropType<number>,
default: 6,
},
gapDegree: {
type: Number as PropType<number>,
default: 0,
},
}, },
setup(props) { setup(props) {
const circleWrapperRef = ref<HTMLElement | null>(null) const circleWrapperRef = ref<HTMLElement | null>(null)
...@@ -42,9 +67,7 @@ export default defineComponent({ ...@@ -42,9 +67,7 @@ export default defineComponent({
}) })
const width = computed(() => { const width = computed(() => {
if (circleWrapperRef.value) { if (circleWrapperRef.value) {
console.log('width', circleWrapperRef.value.clientWidth) return circleWrapperRef.value.clientWidth / (props.rate || 1.8)
return circleWrapperRef.value.clientWidth / 1.8
} }
return 0 return 0
}) })
...@@ -63,6 +86,7 @@ export default defineComponent({ ...@@ -63,6 +86,7 @@ export default defineComponent({
$full() $full()
$center() $center()
flex-direction column flex-direction column
position relative
>p >p
margin-top .1rem margin-top .1rem
font-size .12rem font-size .12rem
......
declare const SMap: any
declare const Plugins: any
export interface ConfigProp {
el: string
options: MapOptionsProp
sources: string[]
}
export interface MapOptionsProp {
viewMode?: string
center?: number[]
zooms?: number[]
zoom?: number
pitch?: number
mapStyle?: string
showBuildingBlock?: boolean
}
class Map {
map: any
config: ConfigProp
constructor(config: ConfigProp) {
this.config = config
}
injectSource(): Promise<unknown[]> {
const promises = this.config.sources.map(
(source: string, index: number) => {
return new Promise((resolve) => {
if (document.getElementById(`_source${index}`)) {
resolve(true)
return
}
const sourceJs = document.createElement('script')
sourceJs.type = 'text/javascript'
sourceJs.src = source
sourceJs.setAttribute('id', `_source${index}`)
document.head.appendChild(sourceJs)
window.onload = () => resolve(true)
})
}
)
return Promise.all(promises)
}
}
export class S_Map extends Map {
constructor(config: ConfigProp) {
super(config)
this.injectSource().then(this.initMap)
}
initMap(): void {
this.map = new SMap.Map(this.config.el, this.config.options)
}
onLoaded(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.maploaded, cb)
}
onZoomChange(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.zoomchanged, cb)
}
onCenterChange(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.centerchanged, cb)
}
onBlur(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.blur, cb)
}
onFocus(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.focus, cb)
}
onDrag(cb: (arg: unknown) => void): void {
this.map.on(SMap.MapEvent.drag, cb)
}
onClick(cb: (arg: unknown, point: unknown) => void): void {
this.map.on(SMap.MapEvent.click, (view: any, eventParamter: any) => {
view.hitTest(eventParamter).then((res: any) => {
if (res.results && res.results.length > 0) {
cb(
res.results[0] && res.results[0].graphic.attributes,
eventParamter.mapPoint
)
}
})
})
}
}
<template>
<div class="step">
<div class="step-container">
<div
v-for="(step, i) in steps"
:key="i"
class="item"
:class="{ on: i == current }"
>
<p :title="step">
{{ step }}
</p>
</div>
</div>
<div class="lines">
<span v-for="(item, i) in steps" :key="i" :class="{ on: i == current }" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
export default defineComponent({
name: 'Step',
props: {
steps: {
type: Array as PropType<string[]>,
required: true,
},
current: {
type: [Number, String] as PropType<number | string>,
default: 0,
},
},
})
</script>
<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.step-container
display flex
justify-content space-around
.item
text-align center
z-index 1
p
color #999
font-size .08rem
position relative
&:after
content ''
position absolute
display block
width 0
height 0
bottom -0.1rem
left 0
right 0
margin 0 auto
border .04rem solid transparent
border-top-color rgba(91,213,255,.2)
&.on
p
color $edge
font-weight bold
&:after
border-top-color $edge
.lines
width 100%
height .05rem
display flex
justify-content space-around
background rgba(91,213,255,.2)
margin .1rem 0 .15rem
>span
display block
min-width .28rem
height 100%
z-index 1
&.on
background linear-gradient(to right, $edge, rgba(255,255,255,.8), $edge)
box-shadow 0 0 0.06rem 0.02rem rgba(0,242,255,.8)
</style>
...@@ -76,6 +76,7 @@ export default defineComponent({ ...@@ -76,6 +76,7 @@ export default defineComponent({
PopulationDrawer, PopulationDrawer,
}, },
setup() { setup() {
store.commit('SET_CURRENT_VIEW', { name: '南京东路街道', type: 'street' })
store.dispatch('initData') store.dispatch('initData')
const curViewType = computed(() => store.state.curView.type) const curViewType = computed(() => store.state.curView.type)
const curTheme = computed(() => store.state.curTheme) const curTheme = computed(() => store.state.curTheme)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment