This commit is contained in:
fanjia 2026-05-07 09:32:09 +08:00
commit 0d0f2d3937
22 changed files with 622 additions and 398 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -15,11 +15,20 @@
<span>校准时间</span> <span>校准时间</span>
</div> </div>
<BasePicker
v-model="routeFilterForm.routeType"
:options="options['roadType']"
label="路线类型"
placeholder="请选择"
@change="handleRouteTypeChange"
/>
<!-- 线路编号 (顶层 routeNo) --> <!-- 线路编号 (顶层 routeNo) -->
<RoadRoutesPicker <RoadRoutesPicker
v-model="formData.event.routeNo" v-model="formData.event.routeNo"
label="线路编号" label="线路编号"
placeholder="请选择" placeholder="请选择"
:extra-params="{ xzdj: routeFilterForm.routeType }"
@change="handleRouteNoChange" @change="handleRouteNoChange"
/> />
@ -192,6 +201,10 @@ const formData = ref({
yhzMaterialList: [], yhzMaterialList: [],
}); });
const routeFilterForm = ref({
routeType: '',
});
const parsePointValue = point => { const parsePointValue = point => {
if (!point) { if (!point) {
return { longitude: null, latitude: null }; return { longitude: null, latitude: null };
@ -221,6 +234,20 @@ const parsePointValue = point => {
return { longitude: null, latitude: null }; return { longitude: null, latitude: null };
}; };
const resetRouteFields = () => {
formData.value.event.routeNo = '';
formData.value.event.startStakeNo = '';
formData.value.event.startStakeLng = '';
formData.value.event.startStakeLat = '';
formData.value.event.endStakeNo = '';
formData.value.event.endStakeLng = '';
formData.value.event.endStakeLat = '';
};
const handleRouteTypeChange = () => {
resetRouteFields();
};
const handleRouteNoChange = (item = {}) => { const handleRouteNoChange = (item = {}) => {
formData.value.event.routeNo = item.routeCode; formData.value.event.routeNo = item.routeCode;
formData.value.event.startStakeNo = item.startStakeNo; formData.value.event.startStakeNo = item.startStakeNo;

View File

@ -29,8 +29,22 @@
<span>校准时间</span> <span>校准时间</span>
</div> </div>
<BasePicker
v-model="routeFilterForm.routeType"
:options="options['roadType']"
label="路线类型"
placeholder="请选择"
@change="handleRouteTypeChange"
/>
<!-- 线路编号 (顶层 routeNo) --> <!-- 线路编号 (顶层 routeNo) -->
<RoadRoutesPicker v-model="formData.event.routeNo" label="线路编号" placeholder="请选择" @change="handleRouteNoChange" /> <RoadRoutesPicker
v-model="formData.event.routeNo"
label="线路编号"
placeholder="请选择"
:extra-params="{ xzdj: routeFilterForm.routeType }"
@change="handleRouteNoChange"
/>
<!-- 起点桩号 (event.startStakeNo) --> <!-- 起点桩号 (event.startStakeNo) -->
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" /> <van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
@ -204,6 +218,10 @@ const formData = ref({
fileList: [] fileList: []
}) })
const routeFilterForm = ref({
routeType: ''
})
const submitting = ref(false) const submitting = ref(false)
// //
@ -251,6 +269,20 @@ const parsePointValue = (point) => {
return { longitude: null, latitude: null } return { longitude: null, latitude: null }
} }
const resetRouteFields = () => {
formData.value.event.routeNo = ''
formData.value.event.startStakeNo = ''
formData.value.event.startStakeLng = ''
formData.value.event.startStakeLat = ''
formData.value.event.endStakeNo = ''
formData.value.event.endStakeLng = ''
formData.value.event.endStakeLat = ''
}
const handleRouteTypeChange = () => {
resetRouteFields()
}
const handleRouteNoChange = (item) => { const handleRouteNoChange = (item) => {
formData.value.event.routeNo = item.routeCode formData.value.event.routeNo = item.routeCode
formData.value.event.startStakeNo = item.startStakeNo formData.value.event.startStakeNo = item.startStakeNo

View File

@ -17,7 +17,11 @@
<van-field v-if="item.lossTypeCode == 'OTHER_LOSS'" v-model="item.remark" label="其它损失描述" placeholder="请填写"></van-field> <van-field v-if="item.lossTypeCode == 'OTHER_LOSS'" v-model="item.remark" label="其它损失描述" placeholder="请填写"></van-field>
</template> </template>
</template> </template>
<van-button size="small" block type="primary" plain @click="addLoss">添加损失</van-button> <van-field>
<template #input>
<van-button icon="plus" block type="primary" plain @click="addLoss">添加损失</van-button>
</template>
</van-field>
<CalculateDialog ref="cubeCalculateDialog" @confirm="confirmCalculate" /> <CalculateDialog ref="cubeCalculateDialog" @confirm="confirmCalculate" />
<LossPicker ref="lossPicker" :options="getOptions()" @confirm="confirmAddLoss" /> <LossPicker ref="lossPicker" :options="getOptions()" @confirm="confirmAddLoss" />
</div> </div>

View File

@ -18,9 +18,13 @@
</template> </template>
</van-field> </van-field>
<van-button class="add-wzbtn" type="primary" icon="plus" block plain @click="handleOpen"> <van-field>
添加物资 <template #input>
</van-button> <van-button class="add-wzbtn" type="primary" icon="plus" block plain @click="handleOpen">
添加物资
</van-button>
</template>
</van-field>
<van-popup <van-popup
:show="showPopup" :show="showPopup"

View File

@ -7,7 +7,7 @@
</span> </span>
<van-icon name="arrow-down" class="selector-icon" /> <van-icon name="arrow-down" class="selector-icon" />
</div> --> </div> -->
<van-field :modelValue="modelValue" is-link readonly :label="label" :placeholder="placeholder" :rules="rules" :required="required" @click="showPicker = true" /> <van-field :modelValue="modelValue" is-link readonly :label="label" :placeholder="placeholder" :rules="rules" :required="required" @click="openPicker" />
<!-- 移动端弹出层使用 van-action-sheet + 内部列表 --> <!-- 移动端弹出层使用 van-action-sheet + 内部列表 -->
<van-action-sheet v-model:show="showPicker" :title="dialogTitle" :close-on-click-action="false" round :style="{ maxHeight: '80vh' }" @close="handlePickerClose"> <van-action-sheet v-model:show="showPicker" :title="dialogTitle" :close-on-click-action="false" round :style="{ maxHeight: '80vh' }" @close="handlePickerClose">

View File

@ -3,22 +3,27 @@
<CurrentSite /> <CurrentSite />
<div class="content"> <div class="content">
<van-grid :gutter="10" :column-num="3" class="grid"> <div class="banner-card">
<van-grid-item <img :src="bannerImage" alt="安全保通服务" class="banner-image" />
class="grid-item" </div>
v-for="item in gridItems"
:key="item.text" <section class="nav-card" v-for="(card, index) in navCardList" :key="index">
:to="item.to" <div class="nav-card-header">
> <span class="card-icon"></span>
<template #icon> <span class="card-title">{{ card.text }}</span>
<img :src="item.icon" class="grid-icon" /> </div>
</template>
<template #text> <div class="nav-list">
<span class="grid-text">{{ item.text }}</span> <div v-for="item in card.navs" :key="item.text" class="nav-item" @click="toNav(item)">
</template> <div class="nav-icon-wrap">
</van-grid-item> <img :src="item.icon" :alt="item.text" class="nav-icon" />
</van-grid> </div>
<span class="nav-text">{{ item.text }}</span>
</div>
</div>
</section>
</div> </div>
<van-popup <van-popup
:show="YHZConfirmpopup" :show="YHZConfirmpopup"
position="center" position="center"
@ -26,168 +31,250 @@
close-on-click-overlay close-on-click-overlay
:style="{ height: '20%', width: '80%' }" :style="{ height: '20%', width: '80%' }"
@close="onYHZConfirmClose" @close="onYHZConfirmClose"
class="confirmpopup"
> >
<div class="confirmpopup__content"> <div class="confirmpopup__content">
<h3>请在服务站授权定位</h3> <h3>请在服务站授权定位</h3>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<van-button class="btn" @click="onYHZConfirmClose">取消</van-button> <van-button class="btn" @click="onYHZConfirmClose">取消</van-button>
<van-button class="btn" type="primary" @click="getLocation" <van-button class="btn" type="primary" @click="getLocation"> 授权定位 </van-button>
>授权定位</van-button
>
</div> </div>
</van-popup> </van-popup>
</PageContainer> </PageContainer>
</template> </template>
<script setup> <script setup>
import "vant/es/toast/style"; import 'vant/es/toast/style'
import "vant/es/popup/style"; import 'vant/es/popup/style'
import { ref, onMounted } from "vue"; import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from 'vue-router'
import { useYHZStore } from "../stores/yhzStore"; import { useYHZStore } from '../stores/yhzStore'
import { showToast } from "vant"; import { showToast } from 'vant'
import { request } from "../../../shared/utils/request"; import { request } from '../../../shared/utils/request'
import PageContainer from "@/components/PageContainer.vue"; import PageContainer from '@/components/PageContainer.vue'
import CurrentSite from "@/components/CurrentSite.vue"; import CurrentSite from '@/components/CurrentSite.vue'
import group63Icon from "@/assets/images/组 63.png"; import bannerImage from '@/assets/images/banenr.png'
import group105Icon from "@/assets/images/组 105.png"; import equipmentIcon from '@/assets/images/设备管理icon.png'
import group10501Icon from "@/assets/images/组 105(1).png"; import materialIcon from '@/assets/images/物资管理icon.png'
import group104Icon from "@/assets/images/组 104.png"; import staffIcon from '@/assets/images/人员管理icon.png'
import group106Icon from "@/assets/images/组 106.png"; import disasterIcon from '@/assets/images/灾毁管理icon.png'
import warningIcon from '@/assets/images/预警信息icon.png'
import rebuildIcon from '@/assets/images/恢复重建icon.png'
const router = useRouter(); const router = useRouter()
const yhzinfo = ref({}); const yhzinfo = ref({})
const yhzStore = useYHZStore(); const yhzStore = useYHZStore()
const route = useRoute(); const route = useRoute()
const token = route.query.token; const token = route.query.token
const YHZConfirmpopup = ref(false); const YHZConfirmpopup = ref(false)
// const navCardList = [
const gridItems = [
{ {
icon: group63Icon, text: '灾毁管理',
text: "设备管理", navs: [
to: { {
name: "EquipManage", icon: disasterIcon,
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) }, text: '灾害管理',
}, to: {
name: 'DisasterManagement',
},
},
{
icon: rebuildIcon,
text: '恢复重建',
to: {
name: 'Rebuild',
},
},
],
}, },
{ {
icon: group10501Icon, text: '预警信息',
text: "物资管理", navs: [
to: { {
name: "MaterialManage", icon: warningIcon,
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) }, text: '预警信息',
}, to: {
name: 'WarningMessage',
},
},
],
}, },
{ {
icon: group104Icon, text: '应急力量',
text: "人员管理", navs: [
to: { {
name: "StaffManage", icon: equipmentIcon,
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) }, text: '设备管理',
}, to: {
name: 'EquipManage',
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
},
},
{
icon: materialIcon,
text: '物资管理',
to: {
name: 'MaterialManage',
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
},
},
{
icon: staffIcon,
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: group106Icon,
text: "灾害管理",
to: {
name: "DisasterManagement",
},
},
{
icon: group105Icon,
text: "预警信息",
to: {
name: "WarningMessage",
},
},
{
icon: group106Icon,
text: '恢复重建',
to: {
name: 'Rebuild',
}
}
];
//
const getYHZinfo = async () => { const getYHZinfo = async () => {
try { try {
const res = await request({ const res = await request({
url: `/snow-ops-platform/yhz/getStationByUser`, url: `/snow-ops-platform/yhz/getStationByUser`,
method: "GET", method: 'GET',
}); })
if (res.code === "00000") { if (res.code === '00000') {
yhzinfo.value = res.data[0]; yhzinfo.value = res.data[0]
yhzStore.setYHZInfo(res.data[0]); yhzStore.setYHZInfo(res.data[0])
// params使yhzinfo navCardList.forEach((card) => {
gridItems.forEach(item => { card.navs?.forEach((item) => {
if (item.to.params && item.to.params.data) { if (item.to.params && item.to.params.data) {
item.to.params.data = encodeURIComponent(JSON.stringify(yhzinfo.value)); item.to.params.data = encodeURIComponent(JSON.stringify(yhzinfo.value))
} }
}); })
})
} else { } else {
throw new Error(res.message); throw new Error(res.message)
} }
} catch (error) { } catch (error) {
showToast({ showToast({
message: error.message, message: error.message,
type: "fail", type: 'fail',
}); })
} }
}; }
const onYHZConfirmClose = () => { const onYHZConfirmClose = () => {
YHZConfirmpopup.value = false; YHZConfirmpopup.value = false
}; }
const getLocation = () => { const getLocation = () => {
// YHZConfirmpopup.value = false
YHZConfirmpopup.value = false; }
};
const toNav = (item) => {
if (!item?.to) {
return
}
router.push(item.to)
}
onMounted(async () => { onMounted(async () => {
if (token) { if (token) {
localStorage.setItem("token", token); localStorage.setItem('token', token)
router.replace({ path: route.path }).then(() => { router.replace({ path: route.path }).then(() => {
window.location.reload(); window.location.reload()
}); })
} }
await getYHZinfo();
if (
yhzinfo.value.isManager &&
(yhzinfo.value.jd === "" || yhzinfo.value.wd === "")
) {
YHZConfirmpopup.value = true;
}
});
const goToUser = () => { await getYHZinfo()
router.push("/user");
}; if (yhzinfo.value.isManager && (yhzinfo.value.jd === '' || yhzinfo.value.wd === '')) {
YHZConfirmpopup.value = true
}
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.banner-card {
overflow: hidden;
}
.banner-image {
display: block;
width: 100%;
height: auto;
}
.nav-card {
margin-top: 8px;
padding: 14px 0 16px;
border-radius: 4px;
background: #ffffff;
}
.nav-card-header {
display: flex;
align-items: center;
gap: 4px;
margin-bottom: 20px;
}
.card-icon {
width: 4px;
height: 11px;
background: #2E7AF4;
border-radius: 2px;
margin-left: 8px;
}
.card-title {
font-weight: 500;
font-size: 16px;
color: #333333;
line-height: 16px;
}
.nav-list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px 10px;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.nav-icon-wrap {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.nav-icon {
width: 40px;
height: 40px;
object-fit: contain;
}
.nav-text {
font-weight: 400;
font-size: 14px;
color: #333333;
line-height: 16px;
margin-top: 8px;
}
.btn-box { .btn-box {
width: 100%; width: 100%;
display: flex; display: flex;
gap: 16px; gap: 16px;
padding: 16px; padding: 16px;
} }
.btn { .btn {
width: 50%; width: 50%;
} }
@ -195,24 +282,4 @@ const goToUser = () => {
.confirmpopup__content { .confirmpopup__content {
padding: 20px; 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>

View File

@ -1,40 +1,47 @@
<template> <template>
<PageContainer title="恢复重建" @click-back="handleClickBack"> <PageContainer title="恢复重建" @click-back="handleClickBack">
<SearchInput v-model="searchValue" /> <SearchInput v-model="searchValue" />
<CurrentSite /> <CurrentSite />
<div class="list-panel"> <div class="list-panel">
<CardItem v-for="(item, index) in list" :key="index" :title="`${item.projectName}`" <van-list :loading="loading" :finished="finished" finished-text="没有更多了" @load="handleLoadMore">
@click="handleClickItem(item)"> <CardItem v-for="(item, index) in list" :key="index" :title="`${item.projectName}`" @click="handleClickItem(item)">
<template #headerExtra> <template #headerExtra>
<van-tag v-if="item.approvalStatus === 3 || item.approvalStatus === 1" type="success" plain size="medium">审批通过</van-tag> <van-tag v-if="item.approvalStatus === 3 || item.approvalStatus === 1" type="success" plain size="medium">审批通过</van-tag>
<van-tag v-else-if="item.approvalStatus === 2 || item.approvalStatus === 4" type="danger" plain size="medium">审批驳回</van-tag> <van-tag v-else-if="item.approvalStatus === 2 || item.approvalStatus === 4" type="danger" plain size="medium">审批驳回</van-tag>
<van-tag v-else type="warning" plain size="medium">待审批</van-tag> <van-tag v-else type="warning" plain size="medium">待审批</van-tag>
</template> </template>
<div class="content"> <div class="content">
<div class="left-info"> <div class="left-info">
<div><span class="label">起止桩号</span><span class="value">{{ `${item.startStakeNo} - <div>
${item.endStakeNo}`}}</span> <span class="label">起止桩号</span
</div> ><span class="value">{{
<div><span class="label">路况位置</span><span class="value">{{ item.roadLocation }}</span></div> `${item.startStakeNo} -
<div><span class="label">提交日期</span><span class="value">{{ item.submitTime }}</span></div> ${item.endStakeNo}`
</div> }}</span>
<div class="right-arrow" @click.stop="handleClickItem(item)"> </div>
<van-icon name="arrow" /> <div>
</div> <span class="label">路况位置</span><span class="value">{{ item.roadLocation }}</span>
</div> </div>
</CardItem> <div>
<span class="label">提交日期</span><span class="value">{{ item.submitTime }}</span>
</div>
</div>
<div class="right-arrow" @click.stop="handleClickItem(item)">
<van-icon name="arrow" />
</div>
</div>
</CardItem>
<!-- 空状态提示 --> <!-- 空状态提示 -->
<EmptyBox v-if="list.length === 0" placeholder="暂无相关预警信息" /> <!-- <EmptyBox v-if="list.length === 0" placeholder="暂无相关预警信息" /> -->
</div> </van-list>
</div>
<van-button type="primary" class="add-btn" icon="plus" @click="handleAddDevice"> <van-button type="primary" class="add-btn" icon="plus" @click="handleAddDevice"> 项目填报 </van-button>
项目填报 </PageContainer>
</van-button>
</PageContainer>
</template> </template>
<script setup> <script setup>
@ -45,30 +52,58 @@ import SearchInput from '@/components/SearchInput.vue'
import CurrentSite from '@/components/CurrentSite.vue' import CurrentSite from '@/components/CurrentSite.vue'
import CardItem from '@/components/CardItem.vue' import CardItem from '@/components/CardItem.vue'
import EmptyBox from '@/components/EmptyBox.vue' import EmptyBox from '@/components/EmptyBox.vue'
import { request } from "../../../../shared/utils/request"; import { request } from '../../../../shared/utils/request'
const router = useRouter() const router = useRouter()
const loading = ref(false)
const finished = ref(false)
const pageNum = ref(1)
const pageSize = 10
onMounted(() => { onMounted(() => {
getData() getData({ reset: true })
}) })
const getData = async () => { const getData = async ({ reset = false } = {}) => {
if (loading.value) return
if (reset) {
pageNum.value = 1
finished.value = false
list.value = []
}
if (finished.value) return
loading.value = true
try {
const params = { const params = {
pageNum: 1, pageNum: pageNum.value,
pageSize: 999, pageSize,
} }
if (searchValue.value) { if (searchValue.value) {
params.districtName = searchValue.value params.districtName = searchValue.value.trim()
} }
const res = await request({ const res = await request({
url: '/snow-ops-platform/recovery/list', url: '/snow-ops-platform/recovery/list',
method: 'GET', method: 'GET',
params params,
}) })
if (res.code === '00000') { if (res.code === '00000' && res.data?.records) {
list.value = res.data.records list.value = reset ? res.data.records : [...list.value, ...res.data.records]
const total = Number(res.data.total || 0)
finished.value = list.value.length >= total || res.data.records.length < pageSize
pageNum.value += 1
} }
} catch (error) {
console.error('获取列表失败:', error)
showToast('获取数据失败,请稍后重试')
finished.value = true
} finally {
loading.value = false
}
} }
// //
@ -77,83 +112,88 @@ const searchValue = ref('')
// //
const list = ref([]) const list = ref([])
const handleClickBack = () => { const handleClickBack = () => {
router.push('/') router.push('/')
} }
const handleClickItem = (item) => { const handleClickItem = (item) => {
router.push({ router.push({
name: 'RebuildDetails', name: 'RebuildDetails',
params: { params: {
data: encodeURIComponent(JSON.stringify(item.id)) data: encodeURIComponent(JSON.stringify(item.id)),
} },
}) })
} }
const handleAddDevice = () => { const handleAddDevice = () => {
router.push('/rebuild-add') router.push('/rebuild-add')
// router.push({ // router.push({
// name: "RebuildAdd", // name: "RebuildAdd",
// params: { // params: {
// data: encodeURIComponent(JSON.stringify(11)), // data: encodeURIComponent(JSON.stringify(11)),
// }, // },
// }); // });
} }
watch(() => searchValue.value, () => { const handleLoadMore = () => {
getData() if (loading.value) return
}) getData()
}
watch(
() => searchValue.value,
() => {
getData({ reset: true })
},
)
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.list-panel { .list-panel {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
} }
.content { .content {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
.left-info { .left-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
font-size: 14px; font-size: 14px;
.label { .label {
color: #666; color: #666;
} }
.value { .value {
color: #aaa; color: #aaa;
} }
} }
.right-arrow { .right-arrow {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100%; height: 100%;
cursor: pointer; cursor: pointer;
} }
.add-btn { .add-btn {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 16px; left: 16px;
right: 16px; right: 16px;
width: calc(100% - 32px); width: calc(100% - 32px);
margin: 0 auto; margin: 0 auto;
border-radius: 24px; border-radius: 24px;
font-size: 16px; font-size: 16px;
height: 44px; height: 44px;
z-index: 999; z-index: 999;
} }
</style> </style>

View File

@ -1,59 +1,109 @@
<template> <template>
<PageContainer title="项目填报" @click-back="handleClickBack"> <PageContainer title="项目填报" @click-back="handleClickBack">
<div class="content"> <div class="content">
<PanelItem> <PanelItem>
<van-form ref="formRef" label-align="left" colon> <van-form ref="formRef" label-align="left" colon>
<van-field v-model="form.project.districtName" label="区县名称" center placeholder="请填写" required <van-field
:rules="[{ required: true, message: '请填写区县名称' }]" /> v-model="form.project.districtName"
<RoadRoutesPicker v-model="form.project.routeNo" label="线路编号" center placeholder="请选择" required label="区县名称"
:rules="[{ required: true, message: '请选择线路编号' }]" @change="handleRouteNoChange" /> center
<van-field v-model="form.project.startStakeNo" label="起点桩号" disabled center placeholder="请选择线路编号" placeholder="请填写"
required :rules="[{ required: true, message: '请填写起点桩号' }]" /> :rules="[{ required: true, message: '请填写区县名称' }]"
<van-field v-model="form.project.endStakeNo" label="止点桩号" disabled center placeholder="请选择线路编号" />
required :rules="[{ required: true, message: '请填写止点桩号' }]" /> <RoadRoutesPicker
<van-field v-model="form.project.implementMileage" label="实施里程" center placeholder="单位:公里" required v-model="form.project.routeNo"
type="number" :rules="[{ required: true, message: '请填写实施里程' }]"> label="线路编号"
<template #extra> center
公里 placeholder="请选择"
</template> :rules="[{ required: true, message: '请选择线路编号' }]"
</van-field> @change="handleRouteNoChange"
<van-field v-model="form.project.earthworkLoss" label="塌方及损失" center placeholder="(方/万元)" required />
:rules="[{ required: true, message: '请填写塌方及损失' }]" /> <van-field
<van-field v-model="form.project.disasterType" label="灾害类型" center placeholder="请填写" required v-model="form.project.startStakeNo"
:rules="[{ required: true, message: '请填写灾害类型' }]" /> label="起点桩号"
<van-field v-model="form.project.locationRoute" label="地点路线" center placeholder="请填写" required disabled
:rules="[{ required: true, message: '请填写地点路线' }]" /> center
<van-field v-model="form.project.roadLocation" label="路况位置" center placeholder="请填写" required placeholder="请选择线路编号"
:rules="[{ required: true, message: '请填写路况位置' }]" /> :rules="[{ required: true, message: '请填写起点桩号' }]"
<van-field v-model="form.project.blockedPointName" label="阻断点小地名" center placeholder="请填写" required />
:rules="[{ required: true, message: '请填写阻断点小地名' }]" /> <van-field
<van-field v-model="form.project.estimatedCost" label="恢复重建预估费用" center placeholder="请填写" required v-model="form.project.endStakeNo"
:rules="[{ required: true, message: '请填写恢复重建预估费用' }]"> label="止点桩号"
<template #extra> disabled
万元 center
</template> placeholder="请选择线路编号"
</van-field> :rules="[{ required: true, message: '请填写止点桩号' }]"
<DisasterFileUpload label="附件上传" v-model="form.fileList"></DisasterFileUpload> />
</van-form> <van-field
v-model="form.project.implementMileage"
</PanelItem> label="实施里程"
</div> center
placeholder="单位:公里"
<van-button type="primary" class="add-btn" icon="plus" @click="handleAdd"> type="number"
提交 :rules="[{ required: true, message: '请填写实施里程' }]"
</van-button> >
</PageContainer> <template #extra> 公里 </template>
</van-field>
<van-field
v-model="form.project.earthworkLoss"
label="塌方及损失"
center
placeholder="(方/万元)"
:rules="[{ required: true, message: '请填写塌方及损失' }]"
/>
<van-field
v-model="form.project.disasterType"
label="灾害类型"
center
placeholder="请填写"
:rules="[{ required: true, message: '请填写灾害类型' }]"
/>
<van-field
v-model="form.project.locationRoute"
label="地点路线"
center
placeholder="请填写"
:rules="[{ required: true, message: '请填写地点路线' }]"
/>
<van-field
v-model="form.project.roadLocation"
label="路况位置"
center
placeholder="请填写"
:rules="[{ required: true, message: '请填写路况位置' }]"
/>
<van-field
v-model="form.project.blockedPointName"
label="阻断点小地名"
center
placeholder="请填写"
:rules="[{ required: true, message: '请填写阻断点小地名' }]"
/>
<van-field
v-model="form.project.estimatedCost"
label="恢复重建预估费用"
center
placeholder="请填写"
:rules="[{ required: true, message: '请填写恢复重建预估费用' }]"
>
<template #extra> 万元 </template>
</van-field>
<DisasterFileUpload label="附件上传" v-model="form.fileList"></DisasterFileUpload>
</van-form>
</PanelItem>
</div>
<van-button type="primary" class="add-btn" icon="plus" @click="handleAdd"> 提交 </van-button>
</PageContainer>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, watch, reactive, toRaw } from 'vue' import { ref, onMounted, watch, reactive, toRaw } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import PageContainer from '@/components/PageContainer.vue' import PageContainer from '@/components/PageContainer.vue'
import { showToast, showLoadingToast } from "vant"; import { showToast, showLoadingToast } from 'vant'
import PanelItem from '@/components/PanelItem.vue' import PanelItem from '@/components/PanelItem.vue'
import { request } from "../../../../shared/utils/request"; import { request } from '../../../../shared/utils/request'
import RoadRoutesPicker from '../DisasterManagement/components/RoadRoutesPicker.vue' import RoadRoutesPicker from '../DisasterManagement/components/RoadRoutesPicker.vue'
import DisasterFileUpload from '../DisasterManagement/components/DisasterFileUpload.vue' import DisasterFileUpload from '../DisasterManagement/components/DisasterFileUpload.vue'
@ -61,136 +111,132 @@ const router = useRouter()
const route = useRoute() const route = useRoute()
const form = reactive({ const form = reactive({
project: { project: {
districtName: null, districtName: null,
routeNo: null, routeNo: null,
startStakeNo: null, startStakeNo: null,
endStakeNo: null, endStakeNo: null,
implementMileage: null, implementMileage: null,
earthworkLoss: null, earthworkLoss: null,
disasterType: null, disasterType: null,
locationRoute: null, locationRoute: null,
roadLocation: null, roadLocation: null,
blockedPointName: null, blockedPointName: null,
estimatedCost: null, estimatedCost: null,
}, },
fileList: [] fileList: [],
}) })
const formRef = ref(); const formRef = ref()
// //
const getDetail = async (id) => { const getDetail = async (id) => {
try { try {
const res = await request({ const res = await request({
url: '/snow-ops-platform/water-damage/getById', url: '/snow-ops-platform/water-damage/getById',
method: 'GET', method: 'GET',
params: { params: {
id id,
} },
}) })
if (res.code === '00000') { if (res.code === '00000') {
form.project.districtName = res.data.event.district form.project.districtName = res.data.event.district
form.project.routeNo = res.data.routeNo form.project.routeNo = res.data.routeNo
form.project.startStakeNo = res.data.event.startStakeNo form.project.startStakeNo = res.data.event.startStakeNo
form.project.endStakeNo = res.data.event.endStakeNo form.project.endStakeNo = res.data.event.endStakeNo
form.project.implementMileage = res.data.event.blockedMileage form.project.implementMileage = res.data.event.blockedMileage
form.project.earthworkLoss = Array.isArray(res.data.lossList) ? res.data.lossList.reduce((sum, item) => sum + (item.totalAmount || 0), 0) : 0 form.project.earthworkLoss = Array.isArray(res.data.lossList) ? res.data.lossList.reduce((sum, item) => sum + (item.totalAmount || 0), 0) : 0
form.project.disasterType = res.data.roadConditionType form.project.disasterType = res.data.roadConditionType
form.project.locationRoute = res.data.occurLocation form.project.locationRoute = res.data.occurLocation
form.project.roadLocation = res.data.event.blockedPointName form.project.roadLocation = res.data.event.blockedPointName
form.project.blockedPointName = res.data.event.blockedPointName form.project.blockedPointName = res.data.event.blockedPointName
form.project.estimatedCost = res.data.event.estimatedRecoveryCost form.project.estimatedCost = res.data.event.estimatedRecoveryCost
form.fileList = res.data.fileList || [] form.fileList = res.data.fileList || []
} else { } else {
throw new Error(res.message) throw new Error(res.message)
}
} catch (error) {
showToast({
type: "fail",
message: error.message,
});
} }
} catch (error) {
showToast({
type: 'fail',
message: error.message,
})
}
} }
onMounted(() => { onMounted(() => {
if (route.params.data) { if (route.params.data) {
const data = JSON.parse(decodeURIComponent(route.params.data)); const data = JSON.parse(decodeURIComponent(route.params.data))
// console.log('@@@@data', data); // console.log('@@@@data', data);
// //
getDetail(data); getDetail(data)
} else { } else {
// console.log(''); // console.log('');
} }
}) })
const handleClickBack = () => { const handleClickBack = () => {
if (route.params.data) { if (route.params.data) {
router.push('/') router.push('/')
} else { } else {
router.push('/rebuild') router.push('/rebuild')
} }
} }
const handleAdd = async () => { const handleAdd = async () => {
// //
if (!formRef.value) { if (!formRef.value) {
showToast('表单初始化失败'); showToast('表单初始化失败')
return; return
} }
try { try {
const isValid = await formRef.value.validate(); const isValid = await formRef.value.validate()
// //
const toast = showLoadingToast({ const toast = showLoadingToast({
message: "上报中...", message: '上报中...',
forbidClick: true, forbidClick: true,
duration: 0, // 0 duration: 0, // 0
}); })
console.log('表单校验通过,提交数据:', form); console.log('表单校验通过,提交数据:', form)
const res = await request({ const res = await request({
url: '/snow-ops-platform/recovery/add', url: '/snow-ops-platform/recovery/add',
method: 'POST', method: 'POST',
data: form data: form,
}) })
toast.close(); toast.close()
if (res.code === '00000') { if (res.code === '00000') {
showToast('提交成功'); showToast('提交成功')
handleClickBack(); handleClickBack()
} else { } else {
showToast('提交失败, 请稍后重试或联系管理员'); showToast('提交失败, 请稍后重试或联系管理员')
}
} catch (error) {
// console.log(':', error);
showToast('请检查并完善表单信息');
} }
} catch (error) {
// console.log(':', error);
showToast('请检查并完善表单信息')
}
} }
const handleRouteNoChange = (item) => { const handleRouteNoChange = (item) => {
form.project.startStakeNo = item.startStakeNo form.project.startStakeNo = item.startStakeNo
form.project.endStakeNo = item.endStakeNo form.project.endStakeNo = item.endStakeNo
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.content { .content {
padding: 20px 0px 80px 0px; padding: 20px 0px 80px 0px;
} }
.add-btn { .add-btn {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
left: 16px; left: 16px;
right: 16px; right: 16px;
width: calc(100% - 32px); width: calc(100% - 32px);
margin: 0 auto; margin: 0 auto;
border-radius: 24px; border-radius: 24px;
font-size: 16px; font-size: 16px;
height: 44px; height: 44px;
z-index: 999; z-index: 999;
} }
</style> </style>

View File

@ -1,7 +1,7 @@
<template> <template>
<PageContainer title="项目填报" @click-back="handleClickBack"> <PageContainer title="项目填报" @click-back="handleClickBack">
<div class="content"> <div class="content">
<PanelItem> <PanelItem v-if="!loading">
<div class="detail"> <div class="detail">
<div class="header"> <div class="header">
<div class="header-title">{{ data.projectName }}</div> <div class="header-title">{{ data.projectName }}</div>
@ -26,7 +26,7 @@
<div class="item">恢复重建预估费用 {{ data.estimatedCost }}</div> <div class="item">恢复重建预估费用 {{ data.estimatedCost }}</div>
</div> </div>
</PanelItem> </PanelItem>
<PanelItem title="附件"> <PanelItem v-if="!loading" title="附件">
<div class="fileArea"> <div class="fileArea">
<van-image v-for="(item, index) in data?.fileList" :key="index" :src="item.fileUrl" fit="cover" <van-image v-for="(item, index) in data?.fileList" :key="index" :src="item.fileUrl" fit="cover"
width="100px" height="100px" style="margin: 10px" @click="showImage(item.fileUrl)"></van-image> width="100px" height="100px" style="margin: 10px" @click="showImage(item.fileUrl)"></van-image>
@ -56,6 +56,7 @@ const router = useRouter()
const route = useRoute() const route = useRoute()
const data = ref({}) const data = ref({})
const loading = ref(false)
onMounted(() => { onMounted(() => {
if (route.params.data) { if (route.params.data) {
@ -69,6 +70,7 @@ onMounted(() => {
const getDetaillData = async (id) => { const getDetaillData = async (id) => {
try { try {
loading.value = true
const res = await request({ const res = await request({
url: '/snow-ops-platform/recovery/getById', url: '/snow-ops-platform/recovery/getById',
method: 'GET', method: 'GET',
@ -82,6 +84,8 @@ const getDetaillData = async (id) => {
} catch (error) { } catch (error) {
showToast('获取详情失败,请稍后重试') showToast('获取详情失败,请稍后重试')
console.log('error', error); console.log('error', error);
} finally {
loading.value = false
} }
} }

View File

@ -100,7 +100,7 @@ const getData = async (keyword = '') => {
const markNoticeRead = async id => { const markNoticeRead = async id => {
await request({ await request({
url: `/snow-ops-platform/weather-warning/notice/${id}/_read`, url: `/snow-ops-platform/weather-warning/notice/${id}/_read`,
method: 'put', method: 'post',
}); });
}; };