Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
This commit is contained in:
commit
35d22fffb9
BIN
packages/mobile/src/assets/images/组 104.png
Normal file
BIN
packages/mobile/src/assets/images/组 104.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
packages/mobile/src/assets/images/组 105(1).png
Normal file
BIN
packages/mobile/src/assets/images/组 105(1).png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
packages/mobile/src/assets/images/组 105.png
Normal file
BIN
packages/mobile/src/assets/images/组 105.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
packages/mobile/src/assets/images/组 106.png
Normal file
BIN
packages/mobile/src/assets/images/组 106.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
packages/mobile/src/assets/images/组 63.png
Normal file
BIN
packages/mobile/src/assets/images/组 63.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
62
packages/mobile/src/components/CardItem.vue
Normal file
62
packages/mobile/src/components/CardItem.vue
Normal file
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="card-item">
|
||||
<slot name="header">
|
||||
<div class="header" :style="{marginBottom: titleGap + 'px'}">
|
||||
<div class="header-title">{{ title }}</div>
|
||||
<div class="header-extra" v-if="$slots.headerExtra">
|
||||
<slot name="headerExtra"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</slot>
|
||||
|
||||
<div class="content" v-if="$slots.content" :style="{gap: contentGap + 'px'}">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
titleGap: {
|
||||
type: [Number, String],
|
||||
default: 16
|
||||
},
|
||||
contentGap: {
|
||||
type:[ Number, String],
|
||||
default: 8
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.card-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 21px 50px 17px 10px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.header-title {
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
color: #4a4a4a;
|
||||
line-height: 16px;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
39
packages/mobile/src/components/CurrentSite.vue
Normal file
39
packages/mobile/src/components/CurrentSite.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<!-- 当前站点 -->
|
||||
<template>
|
||||
<div class="current-site">
|
||||
<van-icon class="position-icon" name="location-o" />
|
||||
<span class="site-name">当前站点:{{ name || yhzStore.getYHZInfo?.mc }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useYHZStore } from '../stores/yhzStore';
|
||||
|
||||
const yhzStore = useYHZStore()
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.current-site {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
background-color: transparent;
|
||||
padding: 0 5px;
|
||||
color: #979797;
|
||||
}
|
||||
|
||||
.position-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.site-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
24
packages/mobile/src/components/EmptyBox.vue
Normal file
24
packages/mobile/src/components/EmptyBox.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="empty">
|
||||
{{ props.placeholder }}
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '暂无相关信息'
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
}
|
||||
</style>
|
||||
41
packages/mobile/src/components/PageContainer.vue
Normal file
41
packages/mobile/src/components/PageContainer.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<van-nav-bar title="气象预警" fixed left-arrow @click-left="onClickLeft" />
|
||||
<div class="page-content-wrapper">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div v-if="$slots.footer" class="page-footer-wrapper"><slot name="footer" /></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const emit = defineEmits(['back'])
|
||||
|
||||
const onClickLeft = () => {
|
||||
emit('click-back')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: var(--van-nav-bar-height); /* 自动匹配导航栏高度 */
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
width: 100dvw;
|
||||
height: 100dvh;
|
||||
background-color: #f6f6f7;
|
||||
}
|
||||
|
||||
.page-content-wrapper {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.page-footer-wrapper {
|
||||
padding-top: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
37
packages/mobile/src/components/PanelHeader.vue
Normal file
37
packages/mobile/src/components/PanelHeader.vue
Normal file
@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="panel-header">
|
||||
<span class="icon"></span>
|
||||
<span class="title-text">{{ title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.icon {
|
||||
display: inline-block;
|
||||
width: 5px;
|
||||
height: 18px;
|
||||
background: linear-gradient(180deg, #91c4f1 0%, #5892e0 100%);
|
||||
border-radius: 2px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.title-text {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #4a4a4a;
|
||||
line-height: 16px;
|
||||
}
|
||||
</style>
|
||||
98
packages/mobile/src/components/SearchInput.vue
Normal file
98
packages/mobile/src/components/SearchInput.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="search-input">
|
||||
<div class="input-wrapper">
|
||||
<div class="input-block">
|
||||
<van-icon class="search-icon" name="search" />
|
||||
<input class="inner-input" v-model="modelValue" :placeholder="placeholder" />
|
||||
<van-icon class="close-icon" name="clear" v-if="modelValue !== ''" @click="modelValue = ''" />
|
||||
</div>
|
||||
|
||||
<!-- 占位符 -->
|
||||
<!-- <div class="placeholder-block" v-if="modelValue === '111'">
|
||||
<van-icon class="search-icon" name="search" />
|
||||
<span class="placeholder-text">{{ placeholder }}</span>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const modelValue = defineModel('modelValue')
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请输入关键词'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.search-input {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.input-block {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.search-icon, .close-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 20px;
|
||||
transform: translateY(-50%);
|
||||
font-size: 20px;
|
||||
color: #9b9b9b;
|
||||
}
|
||||
.close-icon {
|
||||
left: unset;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.inner-input {
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.placeholder-block {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
|
||||
.search-icon {
|
||||
font-size: 20px;
|
||||
margin-right: 3px;
|
||||
color: #9b9b9b;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
color: #9b9b9b;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -67,15 +67,20 @@ const routes = [
|
||||
component: () => import('../views/IceEvent/IceEventDetails.vue')
|
||||
},
|
||||
{
|
||||
path: '/warningMessage/:data',
|
||||
path: '/warningMessage',
|
||||
name: 'WarningMessage',
|
||||
component: () => import('../views/WarningMessage/WarningMessage.vue')
|
||||
},
|
||||
{
|
||||
path: '/warningMessage-detail/:data',
|
||||
path: '/warningMessage-detail',
|
||||
name: 'WarningMessageDetail',
|
||||
component: () => import('../views/WarningMessage/WarningMessageDetail.vue')
|
||||
},
|
||||
{
|
||||
path: '/warningMessageHandle',
|
||||
name: 'WarningMessageHandle',
|
||||
component: () => import('../views/WarningMessage/WarningMessageHandle.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
29
packages/mobile/src/stores/yhzStore.js
Normal file
29
packages/mobile/src/stores/yhzStore.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useYHZStore = defineStore('config', {
|
||||
state: () => ({
|
||||
yhzInfo: null
|
||||
}),
|
||||
getters: {
|
||||
getYHZInfo: (state) => {
|
||||
if(state.yhzInfo) {
|
||||
return state.yhzInfo
|
||||
}
|
||||
try {
|
||||
const yhzInfo = JSON.parse(localStorage.getItem('yhzInfo'))
|
||||
if(yhzInfo) {
|
||||
return yhzInfo
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setYHZInfo(yhzInfo) {
|
||||
this.yhzInfo = yhzInfo
|
||||
localStorage.setItem('yhzInfo', JSON.stringify(yhzInfo))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1,53 +1,22 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<van-nav-bar title="愉快政" fixed left-arrow />
|
||||
|
||||
<van-cell-group>
|
||||
<van-cell title="当前站点" :value="yhzinfo.mc" />
|
||||
</van-cell-group>
|
||||
<PageContainer title="愉快政">
|
||||
<CurrentSite />
|
||||
|
||||
<div class="content">
|
||||
<van-grid :gutter="10" :column-num="3" class="grid">
|
||||
<van-grid-item
|
||||
icon="setting-o"
|
||||
text="设备管理"
|
||||
:to="{
|
||||
name: 'EquipManage',
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo)) },
|
||||
}"
|
||||
/>
|
||||
<van-grid-item
|
||||
icon="setting-o"
|
||||
text="物资管理"
|
||||
:to="{
|
||||
name: 'MaterialManage',
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo)) },
|
||||
}"
|
||||
/>
|
||||
<van-grid-item
|
||||
icon="setting-o"
|
||||
text="人员管理"
|
||||
:to="{
|
||||
name: 'StaffManage',
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo)) },
|
||||
}"
|
||||
/>
|
||||
<van-grid-item
|
||||
icon="setting-o"
|
||||
text="冰雪灾害"
|
||||
:to="{
|
||||
name: 'IceEventManage',
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo)) },
|
||||
}"
|
||||
/>
|
||||
<van-grid-item
|
||||
icon="setting-o"
|
||||
text="气象预警"
|
||||
:to="{
|
||||
name: 'WarningMessage',
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo)) },
|
||||
}"
|
||||
/>
|
||||
class="grid-item"
|
||||
v-for="item in gridItems"
|
||||
:key="item.text"
|
||||
:to="item.to"
|
||||
>
|
||||
<template #icon>
|
||||
<img :src="item.icon" class="grid-icon" />
|
||||
</template>
|
||||
<template #text>
|
||||
<span class="grid-text">{{ item.text }}</span>
|
||||
</template>
|
||||
</van-grid-item>
|
||||
</van-grid>
|
||||
</div>
|
||||
<van-popup
|
||||
@ -69,7 +38,7 @@
|
||||
>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -77,16 +46,69 @@ import "vant/es/toast/style";
|
||||
import "vant/es/popup/style";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { useYHZStore } from "../stores/yhzStore";
|
||||
import { showToast } from "vant";
|
||||
import { request } from "../../../shared/utils/request";
|
||||
import PageContainer from "@/components/PageContainer.vue";
|
||||
import CurrentSite from "@/components/CurrentSite.vue";
|
||||
|
||||
import group63Icon from "@/assets/images/组 63.png";
|
||||
import group105Icon from "@/assets/images/组 105.png";
|
||||
import group10501Icon from "@/assets/images/组 105(1).png";
|
||||
import group104Icon from "@/assets/images/组 104.png";
|
||||
import group106Icon from "@/assets/images/组 106.png";
|
||||
|
||||
const router = useRouter();
|
||||
const yhzinfo = ref({});
|
||||
const yhzStore = useYHZStore();
|
||||
|
||||
const route = useRoute();
|
||||
const token = route.query.token;
|
||||
const YHZConfirmpopup = ref(false);
|
||||
|
||||
// 配置项
|
||||
const gridItems = [
|
||||
{
|
||||
icon: group63Icon,
|
||||
text: "设备管理",
|
||||
to: {
|
||||
name: "EquipManage",
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: group10501Icon,
|
||||
text: "物资管理",
|
||||
to: {
|
||||
name: "MaterialManage",
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: group104Icon,
|
||||
text: "人员管理",
|
||||
to: {
|
||||
name: "StaffManage",
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: group106Icon,
|
||||
text: "冰雪灾害",
|
||||
to: {
|
||||
name: "IceEventManage",
|
||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: group105Icon,
|
||||
text: "预警信息",
|
||||
to: {
|
||||
name: "WarningMessage",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 获取当前登录用于就职的养护站信息
|
||||
const getYHZinfo = async () => {
|
||||
try {
|
||||
@ -96,6 +118,14 @@ const getYHZinfo = async () => {
|
||||
});
|
||||
if (res.code === "00000") {
|
||||
yhzinfo.value = res.data[0];
|
||||
yhzStore.setYHZInfo(res.data[0]);
|
||||
|
||||
// 更新配置项中的params,确保使用最新的yhzinfo
|
||||
gridItems.forEach(item => {
|
||||
if (item.to.params && item.to.params.data) {
|
||||
item.to.params.data = encodeURIComponent(JSON.stringify(yhzinfo.value));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error(res.message);
|
||||
}
|
||||
@ -111,6 +141,11 @@ const onYHZConfirmClose = () => {
|
||||
YHZConfirmpopup.value = false;
|
||||
};
|
||||
|
||||
const getLocation = () => {
|
||||
// 定位逻辑
|
||||
YHZConfirmpopup.value = false;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (token) {
|
||||
localStorage.setItem("token", token);
|
||||
@ -132,19 +167,7 @@ const goToUser = () => {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.home {
|
||||
padding-top: var(--van-nav-bar-height);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@ -158,4 +181,24 @@ const goToUser = () => {
|
||||
.confirmpopup__content {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
.grid-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.grid-text {
|
||||
font-size: 14px;
|
||||
color: #323233;
|
||||
}
|
||||
:deep(.grid-item) {
|
||||
.grid-text {
|
||||
margin-top: 16px;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,360 +1,145 @@
|
||||
<template>
|
||||
<div class="warning-message-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="nav-bar">
|
||||
<div class="back-btn" @click="goBack">
|
||||
<van-icon name="arrow-left" />
|
||||
</div>
|
||||
<div class="title">气象预警</div>
|
||||
<div class="placeholder"></div>
|
||||
</div>
|
||||
<PageContainer title="气象预警" @click-back="handleClickBack">
|
||||
<SearchInput v-model="searchValue" />
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<div class="search-section">
|
||||
<div class="search-box">
|
||||
<span class="search-text">关键词</span>
|
||||
<van-icon name="search" class="search-icon" />
|
||||
</div>
|
||||
</div>
|
||||
<CurrentSite />
|
||||
|
||||
<!-- 当前站点 -->
|
||||
<div class="current-site">
|
||||
<span class="site-label">当前站点:</span>
|
||||
<span class="site-name">{{ currentSite }}</span>
|
||||
</div>
|
||||
<div class="list-panel">
|
||||
<CardItem v-for="(item, index) in list" :key="index" :title="item.area" @click="handleClickItem(item)">
|
||||
<template #headerExtra>
|
||||
<span class="red-ball"></span>
|
||||
</template>
|
||||
|
||||
<!-- 预警列表 -->
|
||||
<div class="warning-list">
|
||||
<div
|
||||
v-for="(item, index) in warningList"
|
||||
:key="index"
|
||||
class="warning-item"
|
||||
:class="{ unread: !item.isRead }"
|
||||
@click="viewDetail(item)"
|
||||
>
|
||||
<div class="item-content">
|
||||
<div class="warning-title">{{ item.title }}</div>
|
||||
<div class="warning-time">
|
||||
<span class="time-label">发布时间:</span>
|
||||
<span class="time-value">{{ item.publishTime }}</span>
|
||||
<!-- 发布时间 block -->
|
||||
<div class="time-block">
|
||||
<div class="time-box">
|
||||
<span class="time-label-text">发布时间:</span>
|
||||
<span class="time-value-text">{{ item.publishTime }}</span>
|
||||
</div>
|
||||
<van-icon class="jump-icon" name="arrow" />
|
||||
</div>
|
||||
<div class="item-right">
|
||||
<div v-if="!item.isRead" class="unread-dot"></div>
|
||||
<van-icon name="arrow" class="arrow-icon" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardItem>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-if="warningList.length === 0" class="empty-state">
|
||||
<van-icon name="warning-o" class="empty-icon" />
|
||||
<div class="empty-text">暂无预警消息</div>
|
||||
<!-- 空状态提示 -->
|
||||
<EmptyBox v-if="list.length === 0" placeholder="暂无相关预警信息" />
|
||||
</div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import PageContainer from '@/components/PageContainer.vue'
|
||||
import SearchInput from '@/components/SearchInput.vue'
|
||||
import CurrentSite from '@/components/CurrentSite.vue'
|
||||
import CardItem from '@/components/CardItem.vue'
|
||||
import EmptyBox from '@/components/EmptyBox.vue'
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const router = useRouter()
|
||||
|
||||
// 当前站点
|
||||
const currentSite = ref("李家坝仓库");
|
||||
onMounted(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
// 解析传递的站点信息
|
||||
const initSiteInfo = () => {
|
||||
const { data } = route.params;
|
||||
if (data) {
|
||||
try {
|
||||
const yhzinfo = JSON.parse(decodeURIComponent(data));
|
||||
currentSite.value = yhzinfo.mc || "李家坝仓库";
|
||||
} catch (e) {
|
||||
console.error("解析站点信息失败", e);
|
||||
// 搜索关键词
|
||||
const searchValue = ref('')
|
||||
|
||||
watch(
|
||||
() => searchValue.value,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal !== oldVal) {
|
||||
getData(newVal)
|
||||
}
|
||||
}
|
||||
};
|
||||
)
|
||||
|
||||
|
||||
initSiteInfo();
|
||||
|
||||
// 预警列表数据
|
||||
const warningList = ref([
|
||||
const list = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: "合川区暴雨红色预警",
|
||||
publishTime: "2025/10/10 20:29",
|
||||
isRead: false,
|
||||
level: "red",
|
||||
type: "rain",
|
||||
area: '合川区',
|
||||
level: '红色气象预警',
|
||||
publishTime: '2026/01/10 20:29'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "合川区红色气象预警",
|
||||
publishTime: "2025/10/09 20:29",
|
||||
isRead: true,
|
||||
level: "red",
|
||||
type: "weather",
|
||||
area: '万州区',
|
||||
level: '红色气象预警',
|
||||
publishTime: '2025/10/10 20:29'
|
||||
},
|
||||
]);
|
||||
{
|
||||
area: '涪陵区',
|
||||
level: '红色气象预警',
|
||||
publishTime: '2025/10/10 20:29'
|
||||
}
|
||||
])
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
};
|
||||
const getData = async () => {
|
||||
|
||||
// 查看详情
|
||||
const viewDetail = (item) => {
|
||||
// 标记为已读
|
||||
item.isRead = true;
|
||||
// 跳转到详情页
|
||||
}
|
||||
|
||||
const handleClickItem = (item) => {
|
||||
router.push({
|
||||
name: "WarningMessageDetail",
|
||||
params: {
|
||||
id: item.id,
|
||||
data: route.params.data,
|
||||
},
|
||||
});
|
||||
};
|
||||
path: '/warningMessage-detail',
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const handleClickBack = () => {
|
||||
router.push('/')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 移动端适配变量
|
||||
$primary-color: #409eff;
|
||||
$text-color: #333;
|
||||
$text-secondary: #666;
|
||||
$text-tertiary: #999;
|
||||
$bg-color: #f5f5f5;
|
||||
$border-color: #e0e0e0;
|
||||
$unread-color: #f56c6c;
|
||||
|
||||
.warning-message-page {
|
||||
min-height: 100vh;
|
||||
background-color: $bg-color;
|
||||
padding-bottom: 20px;
|
||||
|
||||
// 顶部导航栏
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
background-color: #fff;
|
||||
padding: 0 15px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
|
||||
.back-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: $text-color;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索栏
|
||||
.search-section {
|
||||
padding: 12px 15px;
|
||||
background-color: #fff;
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 36px;
|
||||
background-color: #e8e8e8;
|
||||
border-radius: 18px;
|
||||
padding: 0 15px;
|
||||
|
||||
.search-text {
|
||||
font-size: 14px;
|
||||
color: $text-tertiary;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
font-size: 18px;
|
||||
color: $text-tertiary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当前站点
|
||||
.current-site {
|
||||
padding: 10px 15px;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.site-label {
|
||||
color: $text-secondary;
|
||||
}
|
||||
|
||||
.site-name {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
// 预警列表
|
||||
.warning-list {
|
||||
padding: 10px 15px;
|
||||
|
||||
.warning-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
|
||||
&:active {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.warning-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: $text-color;
|
||||
margin-bottom: 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.warning-time {
|
||||
font-size: 12px;
|
||||
color: $text-tertiary;
|
||||
|
||||
.time-label {
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-left: 10px;
|
||||
|
||||
.unread-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: $unread-color;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
font-size: 16px;
|
||||
color: $text-tertiary;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 未读状态样式
|
||||
&.unread {
|
||||
.warning-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 空状态
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
color: $text-tertiary;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
/* ==================== Panel 层级 ==================== */
|
||||
.list-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
// 适配 iPhone 刘海屏
|
||||
@supports (padding-top: env(safe-area-inset-top)) {
|
||||
.warning-message-page {
|
||||
.nav-bar {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
height: calc(44px + env(safe-area-inset-top));
|
||||
}
|
||||
}
|
||||
.card-item {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
// 适配不同屏幕尺寸
|
||||
@media screen and (max-width: 320px) {
|
||||
.warning-message-page {
|
||||
.warning-list {
|
||||
.warning-item {
|
||||
.item-content {
|
||||
.warning-title {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ==================== Block 层级 ==================== */
|
||||
.time-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 414px) {
|
||||
.warning-message-page {
|
||||
.nav-bar {
|
||||
height: 48px;
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.warning-list {
|
||||
.warning-item {
|
||||
padding: 18px;
|
||||
|
||||
.item-content {
|
||||
.warning-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.warning-time {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ==================== Box 层级 ==================== */
|
||||
.time-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
/* ==================== Text / Num 层级 ==================== */
|
||||
.red-ball {
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
background: linear-gradient(180deg, #fd4646 0%, #fb2222 100%);
|
||||
box-shadow: 0px 1px 4px 0px rgba(91, 8, 8, 0.34);
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.jump-icon {
|
||||
font-size: 16px;
|
||||
color: rgb(102, 102, 102, .4);
|
||||
}
|
||||
|
||||
.time-label-text {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.time-value-text {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
}
|
||||
</style>
|
||||
@ -1,395 +1,175 @@
|
||||
<template>
|
||||
<div class="warning-detail-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="nav-bar">
|
||||
<div class="back-btn" @click="goBack">
|
||||
<van-icon name="arrow-left" />
|
||||
</div>
|
||||
<div class="title">气象预警</div>
|
||||
<div class="placeholder"></div>
|
||||
<PageContainer class="page-container" title="预警详情" @click-back="handleClickBack">
|
||||
<CurrentSite />
|
||||
|
||||
<PanelHeader title="气象预警" />
|
||||
<div class="list-panel margin">
|
||||
<CardItem class="card-item" v-for="(item, index) in list" :key="index" :title="item.area" titleGap="10">
|
||||
<template #content>
|
||||
<div class="time-block">
|
||||
<div class="time-box">
|
||||
<span class="time-label-text">发布时间:</span>
|
||||
<span class="time-value-text">{{ item.publishTime }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc-block">
|
||||
<div class="desc-text">{{ item.content }}</div>
|
||||
</div>
|
||||
|
||||
<van-icon class="jump-icon" name="arrow" />
|
||||
</template>
|
||||
</CardItem>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<EmptyBox v-if="list.length === 0" placeholder="暂无相关预警信息" />
|
||||
</div>
|
||||
|
||||
<!-- 当前站点 -->
|
||||
<div class="current-site">
|
||||
<span class="site-label">当前站点:</span>
|
||||
<span class="site-name">{{ currentSite }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 预警详情内容 -->
|
||||
<div class="detail-content" v-if="warningDetail">
|
||||
<!-- 预警标题区域 -->
|
||||
<div class="warning-header">
|
||||
<div class="header-title">气象预警</div>
|
||||
</div>
|
||||
|
||||
<!-- 预警信息卡片 -->
|
||||
<div class="info-card">
|
||||
<div class="warning-name">{{ warningDetail.title }}</div>
|
||||
<div class="publish-time">
|
||||
<span class="time-label">发布时间:</span>
|
||||
<span class="time-value">{{ warningDetail.publishTime }}</span>
|
||||
<PanelHeader title="防御措施" />
|
||||
<div class="list-panel">
|
||||
<CardItem v-for="(item, index) in list" :key="index" :title="item.area">
|
||||
<div class="method-block">
|
||||
<div class="method-text">{{ item.method }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-icon class="jump-icon" name="arrow" />
|
||||
</CardItem>
|
||||
|
||||
<!-- 预警描述 -->
|
||||
<div class="description-card">
|
||||
<div class="desc-text">{{ warningDetail.description }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 防御措施 -->
|
||||
<div class="measures-section">
|
||||
<div class="section-title">防御措施</div>
|
||||
<div class="measures-card">
|
||||
<div class="measures-text">{{ warningDetail.measures }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 空状态提示 -->
|
||||
<EmptyBox v-if="list.length === 0" placeholder="暂无相关防御措施" />
|
||||
</div>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<div class="bottom-action">
|
||||
<van-button type="primary" block round @click="handleResponse">
|
||||
立即响应
|
||||
</van-button>
|
||||
<div class="footer-panel">
|
||||
<van-button block type="primary" @click="handleClickBack()">我已知晓</van-button>
|
||||
<van-button block type="primary" @click="goToHandle()">我要响应</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { showToast } from "vant";
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import PageContainer from '@/components/PageContainer.vue'
|
||||
import CurrentSite from '@/components/CurrentSite.vue'
|
||||
import PanelHeader from '@/components/PanelHeader.vue'
|
||||
import CardItem from '@/components/CardItem.vue'
|
||||
import EmptyBox from '@/components/EmptyBox.vue'
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 当前站点
|
||||
const currentSite = ref("李家坝仓库");
|
||||
|
||||
// 预警详情数据
|
||||
const warningDetail = ref({
|
||||
id: 1,
|
||||
title: "合川区暴雨红色预警",
|
||||
publishTime: "2025/10/10 20:29",
|
||||
description:
|
||||
"区气象台发布暴雨红色预警,按照相关要求,启动I级防御响应,并请及时关注地质、水文等风险提示信息,落实主动封闭管控/“关停撤转”措施",
|
||||
measures:
|
||||
"请立即按照2小时一次频率对你管养的重点路段/重点部位进行巡查,重点巡查较高及以上风险路段、涉灾隐患点、地质条件复杂路段、临河临崖路段/两区三厂、大型设施设备、取弃土(渣)场、砂石料场、涉水桥梁、富水隧道、围堰、支架脚手架、高切坡、滑坡处置等部位,重点关注涉水桥梁基础及墩台、不良地质隧道、隧道洞口边仰坡及侧切结构、高陡边坡支挡防护以及防排水设施,发现异常情况,立即向上报告,采取紧急排危、告警阻拦、吹哨撤转等措施,并及时报送工作开展情况。",
|
||||
level: "red",
|
||||
type: "rain",
|
||||
});
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
// 立即响应
|
||||
const handleResponse = () => {
|
||||
showToast({
|
||||
message: "响应成功",
|
||||
type: "success",
|
||||
});
|
||||
// 实际项目中调用API提交响应
|
||||
console.log("立即响应", warningDetail.value);
|
||||
};
|
||||
const router = useRouter()
|
||||
|
||||
onMounted(() => {
|
||||
// 从路由参数获取预警ID,然后请求详情数据
|
||||
const { id } = route.params;
|
||||
if (id) {
|
||||
console.log("获取预警详情 ID:", id);
|
||||
// 实际项目中调用API获取详情
|
||||
// fetchWarningDetail(id);
|
||||
}
|
||||
getData()
|
||||
})
|
||||
|
||||
// 解析传递的站点信息
|
||||
const { data } = route.params;
|
||||
if (data) {
|
||||
try {
|
||||
const yhzinfo = JSON.parse(decodeURIComponent(data));
|
||||
currentSite.value = yhzinfo.mc || "李家坝仓库";
|
||||
} catch (e) {
|
||||
console.error("解析站点信息失败", e);
|
||||
}
|
||||
// 列表数据
|
||||
const list = ref([
|
||||
{
|
||||
area: '合川区',
|
||||
level: '红色气象预警',
|
||||
content: '今天,北京将进入大雪,请做好',
|
||||
publishTime: '2026/01/10 20:29',
|
||||
method: '立即启动防汛Ⅰ级应急响应,立即转移危险区'
|
||||
},
|
||||
{
|
||||
area: '万州区',
|
||||
level: '红色气象预警',
|
||||
publishTime: '2025/10/10 20:29',
|
||||
method: '立即启动防汛Ⅰ级应急响应,立即转移危险区'
|
||||
},
|
||||
{
|
||||
area: '涪陵区',
|
||||
level: '红色气象预警',
|
||||
publishTime: '2025/10/10 20:29',
|
||||
method: '立即启动防汛Ⅰ级应急响应,立即转移危险区'
|
||||
}
|
||||
});
|
||||
])
|
||||
|
||||
const getData = async () => {}
|
||||
|
||||
const handleClickBack = () => {
|
||||
router.go(-1)
|
||||
}
|
||||
const goToHandle = () => {
|
||||
router.push({path: '/warningMessageHandle'})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 移动端适配变量
|
||||
$primary-color: #1989fa;
|
||||
$text-color: #333;
|
||||
$text-secondary: #666;
|
||||
$text-tertiary: #999;
|
||||
$bg-color: #f5f5f5;
|
||||
$border-color: #e0e0e0;
|
||||
$card-bg: #fff;
|
||||
$section-title-color: #666;
|
||||
.page-container {
|
||||
position: relative;
|
||||
padding-bottom: 74px;
|
||||
}
|
||||
|
||||
.warning-detail-page {
|
||||
min-height: 100vh;
|
||||
background-color: $bg-color;
|
||||
padding-bottom: 80px;
|
||||
/* ==================== Panel 层级 ==================== */
|
||||
.list-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
// 顶部导航栏
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
background-color: #fff;
|
||||
padding: 0 15px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
|
||||
.back-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: $text-color;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
// 当前站点
|
||||
.current-site {
|
||||
padding: 10px 15px;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.site-label {
|
||||
color: $text-secondary;
|
||||
}
|
||||
|
||||
.site-name {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
// 详情内容
|
||||
.detail-content {
|
||||
padding: 15px;
|
||||
|
||||
// 预警标题区域
|
||||
.warning-header {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.header-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: $text-color;
|
||||
position: relative;
|
||||
padding-left: 12px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background-color: $primary-color;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 信息卡片
|
||||
.info-card {
|
||||
background-color: $card-bg;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.warning-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: $text-color;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.publish-time {
|
||||
font-size: 13px;
|
||||
color: $text-tertiary;
|
||||
|
||||
.time-label {
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 描述卡片
|
||||
.description-card {
|
||||
background-color: $card-bg;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.desc-text {
|
||||
font-size: 14px;
|
||||
color: $text-secondary;
|
||||
line-height: 1.8;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
|
||||
// 防御措施区域
|
||||
.measures-section {
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: $text-color;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
padding-left: 12px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background-color: $primary-color;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.measures-card {
|
||||
background-color: $card-bg;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.measures-text {
|
||||
font-size: 14px;
|
||||
color: $text-secondary;
|
||||
line-height: 1.8;
|
||||
text-align: justify;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部按钮
|
||||
.bottom-action {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 10px 15px 20px;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid $border-color;
|
||||
|
||||
.van-button {
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
}
|
||||
&.margin {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// 适配 iPhone 刘海屏
|
||||
@supports (padding-top: env(safe-area-inset-top)) {
|
||||
.warning-detail-page {
|
||||
.nav-bar {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
height: calc(44px + env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
.bottom-action {
|
||||
padding-bottom: calc(20px + env(safe-area-inset-bottom));
|
||||
}
|
||||
}
|
||||
.footer-panel {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 64px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -5px 12px 0px rgba(200, 200, 200, 0.37);
|
||||
opacity: 0.97;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
// 适配不同屏幕尺寸
|
||||
@media screen and (max-width: 320px) {
|
||||
.warning-detail-page {
|
||||
.detail-content {
|
||||
.info-card {
|
||||
.warning-name {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.description-card,
|
||||
.measures-section {
|
||||
.desc-text,
|
||||
.measures-text {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ==================== Block 层级 ==================== */
|
||||
.time-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 414px) {
|
||||
.warning-detail-page {
|
||||
.nav-bar {
|
||||
height: 48px;
|
||||
/* ==================== Box 层级 ==================== */
|
||||
.time-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
/* ==================== Text 层级 ==================== */
|
||||
|
||||
.detail-content {
|
||||
.warning-header {
|
||||
.header-title {
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
.jump-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 15px;
|
||||
font-size: 16px;
|
||||
color: rgb(102, 102, 102, 0.4);
|
||||
}
|
||||
|
||||
.info-card {
|
||||
padding: 18px;
|
||||
.time-label-text {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.warning-name {
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.publish-time {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.description-card,
|
||||
.measures-card {
|
||||
padding: 18px;
|
||||
|
||||
.desc-text,
|
||||
.measures-text {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.measures-section {
|
||||
.section-title {
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.time-value-text {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
.desc-text {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
line-height: 13px;
|
||||
}
|
||||
.method-text {
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
color: #4a4a4a;
|
||||
line-height: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<PageContainer class="page-container" title="预警详情" @click-back="handleClickBack">
|
||||
<CurrentSite />
|
||||
|
||||
<div class="form-panel">
|
||||
<van-field v-model="form.a" label="现场情况描述" placeholder="请输入备注" label-align="top" rows="3" type="textarea" />
|
||||
|
||||
<van-field class="mt-8" v-model="form.b" label="备注(非必填)" placeholder="请填写" input-align="right" />
|
||||
|
||||
<div class="image-upload-block">
|
||||
<div class="label-box">
|
||||
<span class="main-text">现场照片</span>
|
||||
<span class="sub-text">最多上传6张</span>
|
||||
</div>
|
||||
<div class="com-">
|
||||
<van-uploader
|
||||
v-model="fileList"
|
||||
@delete="handleDelete"
|
||||
name="photos"
|
||||
:file-list="fileList"
|
||||
:file-type="['image/jpeg', 'image/png']"
|
||||
:after-read="afterRead"
|
||||
multiple
|
||||
:max-count="6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-panel">
|
||||
<van-button block type="primary" @click="confirm()">确认</van-button>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import PageContainer from '@/components/PageContainer.vue'
|
||||
import CurrentSite from '@/components/CurrentSite.vue'
|
||||
import { showToast, showLoadingToast, showImagePreview } from 'vant'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// 上传附件相关
|
||||
const fileList = ref([])
|
||||
|
||||
const form = ref({
|
||||
a: '',
|
||||
b: '',
|
||||
photos: []
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getData()
|
||||
})
|
||||
|
||||
// 文件删除
|
||||
const handleDelete = (file) => {
|
||||
if (file.serverUrl) {
|
||||
const index = form.value.photos.findIndex((p) => p.photoUrl === file.serverUrl)
|
||||
if (index !== -1) {
|
||||
form.value.photos.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 文件上传
|
||||
const afterRead = async (file) => {
|
||||
const toast = showLoadingToast({
|
||||
message: '上传中...',
|
||||
forbidClick: true,
|
||||
duration: 0 // 设置为0表示不会自动关闭
|
||||
})
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file)
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/file/upload',
|
||||
method: 'post',
|
||||
data: formData
|
||||
})
|
||||
toast.close()
|
||||
if (res.code === '00000') {
|
||||
form.value.photos.push({ photoUrl: res.data })
|
||||
const index = fileList.value.findIndex((f) => f.file === file.file)
|
||||
if (index !== -1) {
|
||||
fileList.value[index].serverUrl = res.data
|
||||
}
|
||||
|
||||
console.log('form.value.photos', toRaw(form.value.photos))
|
||||
console.log('fileList.value', fileList.value)
|
||||
} else {
|
||||
throw new Error(res.message)
|
||||
}
|
||||
} catch (error) {
|
||||
toast.close()
|
||||
showToast({
|
||||
type: 'fail',
|
||||
message: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getData = async () => {}
|
||||
|
||||
const handleClickBack = () => {
|
||||
router.go(-1)
|
||||
}
|
||||
const confirm = async () => {
|
||||
console.log(form.value)
|
||||
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
position: relative;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-bottom: 74px;
|
||||
}
|
||||
|
||||
.mt-8 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* ==================== Panel 层级 ==================== */
|
||||
|
||||
.footer-panel {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 64px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -5px 12px 0px rgba(200, 200, 200, 0.37);
|
||||
opacity: 0.97;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.image-upload-block {
|
||||
background-color: #fff;
|
||||
padding: 16px;
|
||||
|
||||
.label-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
color: #4a4a4a;
|
||||
line-height: 16px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.sub-text {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #4a4a4a;
|
||||
line-height: 17px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user