调度区县数接口调试完成,调度区县数详情接口调试完成,抽查人次接口调试完成,管控情况详情接口完成调试,

This commit is contained in:
fanjia 2026-05-07 15:59:49 +08:00
parent 0d0f2d3937
commit 4ab5bb0abd
13 changed files with 515 additions and 409 deletions

View File

@ -26,57 +26,47 @@
:popper-append-to-body="false" :popper-append-to-body="false"
class="filter-select" class="filter-select"
clearable clearable
@change="fetchData"
> >
<el-option <el-option v-for="item in regionOptions" :key="item.value" :label="item.label" :value="item.value" />
v-for="item in regionOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
<div class="filter-item"> <!-- <div class="filter-item">
<span class="filter-label">类型</span> <span class="filter-label">类型</span>
<el-select <el-select :teleported="false" v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable @change="fetchData">
:teleported="false" <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
v-model="filterForm.type"
placeholder="请选择"
class="filter-select"
clearable
>
<el-option
v-for="item in typeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div> -->
</div> </div>
</template> </template>
</base-dialog> </base-dialog>
</template> </template>
<script setup> <script setup>
import { ref, computed, watch } from 'vue'; import { ref, computed, watch } from 'vue'
import { Close } from '@element-plus/icons-vue'; import { Close } from '@element-plus/icons-vue'
import { regionOptions, typeOptions } from '../component/index.js'; import { regionOptions, typeOptions, formatDateTime } from '../component/index.js'
import BaseDialog from '../component/baseDialog.vue'; import BaseDialog from '../component/baseDialog.vue'
import { request } from '@/utils/request'
const props = defineProps({ const props = defineProps({
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}); dispatchDateRange: {
type: Array,
default: () => [],
},
})
const emit = defineEmits(['update:visible', 'close']); const emit = defineEmits(['update:visible', 'close'])
// //
const filterForm = ref({ const filterForm = ref({
region: '', region: '',
type: '', type: '',
}); })
// //
// index.js // index.js
@ -85,7 +75,7 @@ const filterForm = ref({
// index.js // index.js
// //
const tableHeight = ref(300); const tableHeight = ref(300)
// //
const tableColumns = ref([ const tableColumns = ref([
@ -96,104 +86,137 @@ const tableColumns = ref([
{ prop: 'type', label: '类型', width: '120px' }, { prop: 'type', label: '类型', width: '120px' },
{ prop: 'role', label: '角色', width: '120px' }, { prop: 'role', label: '角色', width: '120px' },
{ prop: 'dispatchTime', label: '调度时间', width: '160px' }, { prop: 'dispatchTime', label: '调度时间', width: '160px' },
]); ])
// //
const tableData = ref([ const tableData = ref([])
{
id: 1,
district: '柏梓镇',
name: '赵海浪',
phone: '18623520681',
type: '交通主管部门',
role: '一般人员(路长履职)',
dispatchTime: '2025-08-11 04:53:42',
},
{
id: 2,
district: '柏梓镇',
name: '赵海浪',
phone: '18623520681',
type: '公路机构',
role: '一般人员(路长履职)',
dispatchTime: '2025-08-11 04:53:42',
},
{
id: 3,
district: '万州区',
name: '王鑫',
phone: '18623520682',
type: '养护站',
role: '站长',
dispatchTime: '2025-08-10 14:30:00',
},
{
id: 4,
district: '沙坪坝区',
name: '李华',
phone: '18623520683',
type: '护路员',
role: '一般人员',
dispatchTime: '2025-08-09 09:15:30',
},
]);
// //
const currentPage = ref(1); const currentPage = ref(1)
const pageSize = ref(10); const pageSize = ref(10)
const total = ref(36); const total = ref(36)
const totalPages = computed(() => Math.ceil(total.value / pageSize.value)); const totalPages = computed(() => Math.ceil(total.value / pageSize.value))
const visiblePages = computed(() => { const visiblePages = computed(() => {
const pages = []; const pages = []
const maxVisible = 5; const maxVisible = 5
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2)); let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2))
let end = Math.min(totalPages.value, start + maxVisible - 1); let end = Math.min(totalPages.value, start + maxVisible - 1)
if (end - start + 1 < maxVisible) { if (end - start + 1 < maxVisible) {
start = Math.max(1, end - maxVisible + 1); start = Math.max(1, end - maxVisible + 1)
} }
for (let i = start; i <= end; i++) { for (let i = start; i <= end; i++) {
pages.push(i); pages.push(i)
} }
return pages; return pages
}); })
// //
const handleClose = () => { const handleClose = () => {
emit('update:visible', false); emit('update:visible', false)
emit('close'); emit('close')
}; }
// //
const handleSizeChange = val => { const handleSizeChange = (val) => {
pageSize.value = val; pageSize.value = val
fetchData(); fetchData()
}; }
const handleCurrentChange = val => { const handleCurrentChange = (val) => {
currentPage.value = val; currentPage.value = val
fetchData(); fetchData()
}; }
// //
const fetchData = () => { const fetchData = async () => {
console.log('获取第', currentPage.value, '页数据'); try {
// API const res = await request({
}; url: '/snow-ops-platform/weather-warning/scheduling-county-record',
method: 'GET',
params: {
offset: (currentPage.value - 1) * pageSize.value,
limit: pageSize.value,
start: formatDateTime(props.dispatchDateRange?.[0]),
end: formatDateTime(props.dispatchDateRange?.[1]),
countyId: filterForm.value.region,
},
})
if (res.total > 0 && res.data) {
const data = res.data
tableData.value = data.map((item, index) => {
// command JSON
let commandData = {}
try {
if (item.command) {
commandData = JSON.parse(item.command)
}
} catch (e) {
console.error('解析 command 字段失败:', e)
}
// type
const typeMap = {
'phone-based-confirmation': '电话确认',
'video-conference': '视频会议',
'scheduling-county': '调度区县',
}
const district = regionOptions.value.find((option) => option.value === item.countyId)?.label || '-'
return {
id: (currentPage.value - 1) * pageSize.value + index + 1,
district: district,
name: commandData.userName || '-',
phone: commandData.userPhone || '-',
type: commandData.type || '-',
role: commandData.role || '一般人员',
dispatchTime: item.createdAt || '-',
}
})
total.value = res.total
} else {
tableData.value = []
total.value = 0
}
} catch (error) {
console.error('获取调度区县详情数据失败:', error)
}
}
// visible // visible
watch( watch(
() => props.visible, () => props.visible,
newVal => { (newVal) => {
if (newVal) { if (newVal) {
currentPage.value = 1; filterForm.value.region = ''
fetchData(); filterForm.value.type = ''
tableData.value = []
total.value = 0
currentPage.value = 1
fetchData()
} }
},
)
// dispatchDateRange
watch(
() => props.dispatchDateRange,
() => {
if (props.visible) {
filterForm.value.region = ''
filterForm.value.type = ''
tableData.value = []
total.value = 0
currentPage.value = 1
fetchData()
} }
); },
{ deep: true },
)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -18,19 +18,8 @@
<div class="filter-row"> <div class="filter-row">
<div class="filter-item"> <div class="filter-item">
<span class="filter-label">影响区域</span> <span class="filter-label">影响区域</span>
<el-select <el-select :teleported="false" v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable @change="fetchData">
:teleported="false" <el-option v-for="item in regionOptions" :key="item.value" :label="item.label" :value="item.value" />
v-model="filterForm.region"
placeholder="请选择"
class="filter-select"
clearable
>
<el-option
v-for="item in regionOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
</div> </div>
@ -44,34 +33,47 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, watch } from 'vue'; import { ref, computed, watch } from 'vue'
import { Close } from '@element-plus/icons-vue'; import { Close } from '@element-plus/icons-vue'
import { regionOptions } from '../component/index.js'; import { regionOptions, formatDateTime } from '../component/index.js'
import BaseDialog from '../component/baseDialog.vue'; import BaseDialog from '../component/baseDialog.vue'
import { request } from '@/utils/request'
const props = defineProps({ const props = defineProps({
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}); dispatchDateRange: {
type: Array,
default: () => [],
},
})
watch(
() => props.dispatchDateRange,
(newVal) => {
console.log(newVal, '调度日期范围')
fetchData()
},
)
const emit = defineEmits({ const emit = defineEmits({
'update:visible': value => typeof value === 'boolean', 'update:visible': (value) => typeof value === 'boolean',
close: () => true, close: () => true,
dispatchClick: item => item !== undefined, dispatchClick: (item) => item !== undefined,
}); })
// //
const filterForm = ref({ const filterForm = ref({
region: '', region: '',
}); })
// //
// index.js // index.js
// //
const tableHeight = ref(300); const tableHeight = ref(300)
// //
const tableColumns = ref([ const tableColumns = ref([
@ -79,99 +81,106 @@ const tableColumns = ref([
{ prop: 'region', label: '影响区域', width: '' }, { prop: 'region', label: '影响区域', width: '' },
{ prop: 'dispatchCount', label: '调度数', width: '', slot: 'dispatchCount' }, { prop: 'dispatchCount', label: '调度数', width: '', slot: 'dispatchCount' },
{ prop: 'lastDispatchTime', label: '最近调度时间', width: '' }, { prop: 'lastDispatchTime', label: '最近调度时间', width: '' },
]); ])
// //
const tableData = ref([ const tableData = ref([])
{
id: 1,
region: '重庆市',
dispatchCount: 1,
lastDispatchTime: '2025-08-11 04:53:42',
},
{
id: 2,
region: '万州区',
dispatchCount: 1,
lastDispatchTime: '2025-08-11 04:53:42',
},
{
id: 3,
region: '沙坪坝区',
dispatchCount: 3,
lastDispatchTime: '2025-08-10 16:20:15',
},
{
id: 4,
region: '渝中区',
dispatchCount: 2,
lastDispatchTime: '2025-08-09 11:45:30',
},
]);
// //
const currentPage = ref(1); const currentPage = ref(1)
const pageSize = ref(10); const pageSize = ref(10)
const total = ref(36); const total = ref(36)
const totalPages = computed(() => Math.ceil(total.value / pageSize.value)); const totalPages = computed(() => Math.ceil(total.value / pageSize.value))
const visiblePages = computed(() => { const visiblePages = computed(() => {
const pages = []; const pages = []
const maxVisible = 5; const maxVisible = 5
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2)); let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2))
let end = Math.min(totalPages.value, start + maxVisible - 1); let end = Math.min(totalPages.value, start + maxVisible - 1)
if (end - start + 1 < maxVisible) { if (end - start + 1 < maxVisible) {
start = Math.max(1, end - maxVisible + 1); start = Math.max(1, end - maxVisible + 1)
} }
for (let i = start; i <= end; i++) { for (let i = start; i <= end; i++) {
pages.push(i); pages.push(i)
} }
return pages; return pages
}); })
// //
const handleClose = () => { const handleClose = () => {
emit('update:visible', false); emit('update:visible', false)
emit('close'); emit('close')
}; }
// //
const handleDispatchClick = item => { const handleDispatchClick = (item) => {
emit('dispatchClick', item); emit('dispatchClick', item)
}; }
// //
const handleSizeChange = val => { const handleSizeChange = (val) => {
pageSize.value = val; pageSize.value = val
fetchData(); fetchData()
}; }
const handleCurrentChange = val => { const handleCurrentChange = (val) => {
currentPage.value = val; currentPage.value = val
fetchData(); fetchData()
}; }
const handleFilterChange = () => {
currentPage.value = 1
fetchData()
}
// //
const fetchData = () => { const fetchData = async () => {
console.log('获取第', currentPage.value, '页数据'); try {
// API const res = await request({
}; url: '/snow-ops-platform/weather-warning/scheduling-county',
method: 'GET',
params: {
start: formatDateTime(props.dispatchDateRange?.[0]),
end: formatDateTime(props.dispatchDateRange?.[1]),
countyId: filterForm.value.region,
offset: (currentPage.value - 1) * pageSize.value,
limit: pageSize.value,
},
})
if (res.total > 0 && res.data) {
const data = res.data
tableData.value = data.map((item, index) => {
const region = item.qxmc || regionOptions.value.find((option) => option.value === item.countyId)?.label || '-'
return {
id: (currentPage.value - 1) * pageSize.value + index + 1,
region: region,
dispatchCount: item.count || 0,
lastDispatchTime: item.lastTime || '-',
}
})
total.value = res.total
} else {
tableData.value = []
total.value = 0
}
} catch (error) {
console.error('获取调度区县数据失败:', error)
}
}
// visible // visible
watch( watch(
() => props.visible, () => props.visible,
newVal => { (newVal) => {
if (newVal) { currentPage.value = 1
currentPage.value = 1;
// //
filterForm.value.region = ''; filterForm.value.region = ''
fetchData(); fetchData()
} },
} )
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -139,12 +139,7 @@
<span class="timeline-value highlight">{{ item.sceneDesc }}</span> <span class="timeline-value highlight">{{ item.sceneDesc }}</span>
</div> </div>
<div class="timeline-images" v-if="item.images && item.images.length > 0"> <div class="timeline-images" v-if="item.images && item.images.length > 0">
<div <div v-for="(img, imgIndex) in item.images" :key="imgIndex" class="timeline-image" @click="previewImage(img)">
v-for="(img, imgIndex) in item.images"
:key="imgIndex"
class="timeline-image"
@click="previewImage(img)"
>
<img :src="img" alt="现场图片" /> <img :src="img" alt="现场图片" />
</div> </div>
</div> </div>
@ -168,11 +163,11 @@
</template> </template>
<script setup> <script setup>
import { ref, watch, onMounted } from 'vue'; import { ref, watch, onMounted } from 'vue'
import { Close } from '@element-plus/icons-vue'; import { Close } from '@element-plus/icons-vue'
import baseDialog from '../component/baseDialog.vue'; import baseDialog from '../component/baseDialog.vue'
import { request } from '@/utils/request'; import { request } from '@/utils/request'
import { formatDateTime } from '../component/index.js'; import { formatDateTime } from '../component/index.js'
const props = defineProps({ const props = defineProps({
visible: { visible: {
@ -183,11 +178,11 @@ const props = defineProps({
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },
}); })
onMounted(() => { onMounted(() => {
console.log('props.eventData', props.eventData); console.log('props.eventData', props.eventData)
}); })
const emit = defineEmits(['update:visible', 'close']); const emit = defineEmits(['update:visible', 'close'])
// //
const eventInfo = ref({ const eventInfo = ref({
@ -201,55 +196,56 @@ const eventInfo = ref({
roadPosition: '', roadPosition: '',
stakeRange: '', stakeRange: '',
discoverTime: '', discoverTime: '',
}); })
// //
const feedbackList = ref([]); const feedbackList = ref([])
// //
const fetchEventDetail = async () => { const fetchEventDetail = async () => {
try { try {
const gl1SjId = props.eventData?.gl1SjId; const gl1SjId = props.eventData?.gl1SjId
if (!gl1SjId) { if (!gl1SjId) {
console.warn('gl1SjId 不存在'); console.warn('gl1SjId 不存在')
return; return
} }
const res = await request({ const res = await request({
url: '/snow-ops-platform/sm-event/detail-by-sjid', // url: '/snow-ops-platform/sm-event/detail-by-sjid',
url: '/snow-ops-platform/sm-event/detail',
method: 'GET', method: 'GET',
params: { params: {
sjid: gl1SjId + '', gl1SjId: gl1SjId + '',
// sjid: '00092c5f0c054c67b0ad00071dd94630', // gl1SjId: '2fd1225c892a4e9396f006fe8ebaac53',
}, },
}); })
if (res && res.code === '00000') { if (res && res.code === '00000') {
// - API // - API
const data = res.data || {}; const data = res.data || {}
eventInfo.value = { eventInfo.value = {
// eventType: // eventType:
eventType: data.eventType || '-', eventType: data.gl1Sjlx || '-',
// eventLevel: -> // eventLevel: ->
roadConditionType: data.eventLevel || '-', roadConditionType: data.gl1Lklx || '-',
// isBlocked: eventDesc // isBlocked: eventDesc
isBlocked: data.eventDesc?.includes('阻断') ? '是' : '否', isBlocked: data.eventDesc?.includes('阻断') ? '是' : '否',
// district: -> // district: ->
reportCounty: data.district || '-', reportCounty: data.qxmc || '-',
// detailAddress: -> // detailAddress: ->
blockLocation: data.detailAddress || '-', blockLocation: data.gl1Wz || '-',
// eventNo: -> 线 // eventNo: -> 线
routeCode: data.eventNo || '-', routeCode: data.gl1Lxbh || '-',
// eventDesc: -> // eventDesc: ->
handleMeasure: data.eventDesc || '-', handleMeasure: data.gl1Clcs || '-',
// detailAddress: -> // detailAddress: ->
roadPosition: data.detailAddress || '-', roadPosition: data.gl1Lxmc || '-',
// stakeRange // stakeRange
stakeRange: formatStakeRangeFromData(data), stakeRange: data.gl1Qdzh + '-' + data.gl1Zdzh || '-',
// occurTime: -> // occurTime: ->
discoverTime: formatDateTime(data.occurTime) || '-', discoverTime: data.gl1Fxsj || '-',
}; }
console.log('eventInfo', eventInfo.value); console.log('eventInfo', eventInfo.value)
// - API // - API
if (data.handleList && Array.isArray(data.handleList)) { if (data.handleList && Array.isArray(data.handleList)) {
feedbackList.value = data.handleList.map((item, index) => ({ feedbackList.value = data.handleList.map((item, index) => ({
@ -257,84 +253,84 @@ const fetchEventDetail = async () => {
isFirst: index === 0, isFirst: index === 0,
reportType: index === 0 ? '首报' : '续报', reportType: index === 0 ? '首报' : '续报',
// disposeTime: // disposeTime:
reportTime: formatDateTime(item.disposeTime) || '-', reportTime: formatDateTime(item.gl1Cjsj) || '-',
// handleMeasure: disposeDesc // handleMeasure: disposeDesc
handleMeasure: item.disposeDesc?.substring(0, 10) || '-', handleMeasure: item.gl1Clcs || '-',
// expectStartTime: // expectStartTime:
estimatedRecoverTime: formatDateTime(item.expectStartTime) || '-', estimatedRecoverTime: formatDateTime(item.gl1Yjhfsj) || '-',
// actualStartTime: // actualStartTime:
actualRecoverTime: formatDateTime(item.actualStartTime) || '-', actualRecoverTime: formatDateTime(item.gl1Sjhfsj) || '-',
// disposer: // disposer:
reporter: item.disposer || '-', reporter: item.gl1Lxrxm || '-',
// contactPhone: // contactPhone:
contactPhone: item.contactPhone || '-', contactPhone: item.gl1Lxdh || '-',
// disposeDesc: // disposeDesc:
sceneDesc: item.disposeDesc || '-', sceneDesc: item.gl1Xcqkms || '-',
})); }))
} else { } else {
feedbackList.value = []; feedbackList.value = []
} }
} }
} catch (error) { } catch (error) {
console.error('获取事件详情失败:', error); console.error('获取事件详情失败:', error)
}
} }
};
// //
const formatRoadPosition = data => { const formatRoadPosition = (data) => {
const parts = []; const parts = []
if (data.gl1Qxmc) parts.push(data.gl1Qxmc); if (data.gl1Qxmc) parts.push(data.gl1Qxmc)
if (data.gl1Zddxdm) parts.push(data.gl1Zddxdm); if (data.gl1Zddxdm) parts.push(data.gl1Zddxdm)
if (data.gl1Lxbh) parts.push(data.gl1Lxbh); if (data.gl1Lxbh) parts.push(data.gl1Lxbh)
return parts.length > 0 ? parts.join('') : '-'; return parts.length > 0 ? parts.join('') : '-'
}; }
// //
const formatStakeRange = data => { const formatStakeRange = (data) => {
const start = data.gl1Qdzh || ''; const start = data.gl1Qdzh || ''
const end = data.gl1Zdzh || ''; const end = data.gl1Zdzh || ''
if (start && end) return `${start}-${end}`; if (start && end) return `${start}-${end}`
if (start) return start; if (start) return start
if (end) return end; if (end) return end
return '-'; return '-'
}; }
// API- APIdetailAddress'-' // API- APIdetailAddress'-'
const formatStakeRangeFromData = data => { const formatStakeRangeFromData = (data) => {
// APIdetailAddress'-' // APIdetailAddress'-'
// API // API
return '-'; return '-'
}; }
// //
const previewVisible = ref(false); const previewVisible = ref(false)
const previewImageUrl = ref(''); const previewImageUrl = ref('')
const previewImage = url => { const previewImage = (url) => {
previewImageUrl.value = url; previewImageUrl.value = url
previewVisible.value = true; previewVisible.value = true
}; }
const closePreview = () => { const closePreview = () => {
previewVisible.value = false; previewVisible.value = false
previewImageUrl.value = ''; previewImageUrl.value = ''
}; }
// //
const handleClose = () => { const handleClose = () => {
emit('update:visible', false); emit('update:visible', false)
emit('close'); emit('close')
}; }
// eventData // eventData
watch( watch(
() => props.visible, () => props.visible,
newVal => { (newVal) => {
if (newVal) { if (newVal) {
fetchEventDetail(); fetchEventDetail()
} }
} },
); )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -62,12 +62,7 @@
</div> </div>
<!-- 图片预览组件 --> <!-- 图片预览组件 -->
<el-image-viewer <el-image-viewer v-if="previewVisible" :url-list="hazardData.photos" :initial-index="previewIndex" @close="previewVisible = false" />
v-if="previewVisible"
:url-list="hazardData.photos"
:initial-index="previewIndex"
@close="previewVisible = false"
/>
<!-- 风险描述 --> <!-- 风险描述 -->
<div class="info-block"> <div class="info-block">
@ -97,13 +92,13 @@
<span class="responsibility-phone">{{ hazardData.trafficDept.phone }}</span> <span class="responsibility-phone">{{ hazardData.trafficDept.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.trafficDept.frequency }}</span> <span class="responsibility-frequency">{{ hazardData.trafficDept.frequency }}</span>
<div class="action-btns"> <div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.trafficDept)" title="视频"> <div class="action-btn" @click="handleVideo(hazardData.trafficDept, '交通主管部门责任人')" title="视频">
<el-icon><VideoCamera /></el-icon> <el-icon><VideoCamera /></el-icon>
</div> </div>
<div class="action-btn" @click="handleVoice(hazardData.trafficDept)" title="语音"> <div class="action-btn" @click="handleVoice(hazardData.trafficDept, '交通主管部门责任人')" title="语音">
<el-icon><Microphone /></el-icon> <el-icon><Microphone /></el-icon>
</div> </div>
<div class="action-btn" @click="handleCall(hazardData.trafficDept)" title="电话"> <div class="action-btn" @click="handleCall(hazardData.trafficDept, '交通主管部门责任人')" title="电话">
<el-icon><Phone /></el-icon> <el-icon><Phone /></el-icon>
</div> </div>
</div> </div>
@ -115,13 +110,13 @@
<span class="responsibility-phone">{{ hazardData.roadOrg.phone }}</span> <span class="responsibility-phone">{{ hazardData.roadOrg.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.roadOrg.frequency }}</span> <span class="responsibility-frequency">{{ hazardData.roadOrg.frequency }}</span>
<div class="action-btns"> <div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.roadOrg)" title="视频"> <div class="action-btn" @click="handleVideo(hazardData.roadOrg, '公路机构责任人')" title="视频">
<el-icon><VideoCamera /></el-icon> <el-icon><VideoCamera /></el-icon>
</div> </div>
<div class="action-btn" @click="handleVoice(hazardData.roadOrg)" title="语音"> <div class="action-btn" @click="handleVoice(hazardData.roadOrg, '公路机构责任人')" title="语音">
<el-icon><Microphone /></el-icon> <el-icon><Microphone /></el-icon>
</div> </div>
<div class="action-btn" @click="handleCall(hazardData.roadOrg)" title="电话"> <div class="action-btn" @click="handleCall(hazardData.roadOrg, '公路机构责任人')" title="电话">
<el-icon><Phone /></el-icon> <el-icon><Phone /></el-icon>
</div> </div>
</div> </div>
@ -133,13 +128,13 @@
<span class="responsibility-phone">{{ hazardData.maintenance.phone }}</span> <span class="responsibility-phone">{{ hazardData.maintenance.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.maintenance.frequency }}</span> <span class="responsibility-frequency">{{ hazardData.maintenance.frequency }}</span>
<div class="action-btns"> <div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.maintenance)" title="视频"> <div class="action-btn" @click="handleVideo(hazardData.maintenance, '养护站责任人')" title="视频">
<el-icon><VideoCamera /></el-icon> <el-icon><VideoCamera /></el-icon>
</div> </div>
<div class="action-btn" @click="handleVoice(hazardData.maintenance)" title="语音"> <div class="action-btn" @click="handleVoice(hazardData.maintenance, '养护站责任人')" title="语音">
<el-icon><Microphone /></el-icon> <el-icon><Microphone /></el-icon>
</div> </div>
<div class="action-btn" @click="handleCall(hazardData.maintenance)" title="电话"> <div class="action-btn" @click="handleCall(hazardData.maintenance, '养护站责任人')" title="电话">
<el-icon><Phone /></el-icon> <el-icon><Phone /></el-icon>
</div> </div>
</div> </div>
@ -156,13 +151,13 @@
<span class="responsibility-name" style="width: 100px">{{ hazardData.roadKeeper.phone }}</span> <span class="responsibility-name" style="width: 100px">{{ hazardData.roadKeeper.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.roadKeeper.frequency }}</span> <span class="responsibility-frequency">{{ hazardData.roadKeeper.frequency }}</span>
<div class="action-btns"> <div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.roadKeeper)" title="视频"> <div class="action-btn" @click="handleVideo(hazardData.roadKeeper, '护路员')" title="视频">
<el-icon><VideoCamera /></el-icon> <el-icon><VideoCamera /></el-icon>
</div> </div>
<div class="action-btn" @click="handleVoice(hazardData.roadKeeper)" title="语音"> <div class="action-btn" @click="handleVoice(hazardData.roadKeeper, '护路员')" title="语音">
<el-icon><Microphone /></el-icon> <el-icon><Microphone /></el-icon>
</div> </div>
<div class="action-btn" @click="handleCall(hazardData.roadKeeper)" title="电话"> <div class="action-btn" @click="handleCall(hazardData.roadKeeper, '护路员')" title="电话">
<el-icon><Phone /></el-icon> <el-icon><Phone /></el-icon>
</div> </div>
</div> </div>
@ -332,11 +327,13 @@ const previewPhoto = (index) => {
} }
// //
const handleVideo = (item) => { const handleVideo = (item, type) => {
console.log('视频通话:', item) console.log('视频通话:', item)
let videoParams = { let videoParams = {
...item, ...item,
id: hazardData.value.id, id: hazardData.value.id,
type: type,
role: getRolefn(type),
} }
openVideoConference(videoParams) openVideoConference(videoParams)
// emit('video', { // emit('video', {
@ -346,11 +343,13 @@ const handleVideo = (item) => {
} }
// //
const handleVoice = (item) => { const handleVoice = (item, type) => {
console.log('语音通话:', item) console.log('语音通话:', item)
let voiceParams = { let voiceParams = {
...item, ...item,
id: hazardData.value.id, id: hazardData.value.id,
type: type,
role: getRolefn(type),
} }
openVoiceConference(voiceParams) openVoiceConference(voiceParams)
// emit('voice', { // emit('voice', {
@ -360,14 +359,28 @@ const handleVoice = (item) => {
} }
// //
const handleCall = (item) => { const handleCall = (item, type) => {
console.log('拨打电话:', item) console.log('拨打电话:', item)
emit('call', { emit('call', {
...item, ...item,
id: hazardData.value.id, id: hazardData.value.id,
type: type,
role: getRolefn(type),
}) })
} }
const getRolefn = (item) => {
if (item == '交通主管部门责任人') {
return '责任人'
} else if (item == '公路机构责任人') {
return '责任人'
} else if (item == '养护站责任人') {
return '站长'
} else if (item == '护路员') {
return '一般人员'
} else {
return '-'
}
}
// visible // visible
watch( watch(
() => props.visible, () => props.visible,

View File

@ -26,12 +26,7 @@
clearable clearable
@change="handleFilterChange" @change="handleFilterChange"
> >
<el-option <el-option v-for="item in regionOptions" :key="item.value" :label="item.label" :value="item.value" />
v-for="item in districtOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</div> </div>
</div> </div>
@ -40,56 +35,32 @@
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch, inject } from 'vue'
import BaseDialog from '../component/baseDialog.vue'; import BaseDialog from '../component/baseDialog.vue'
import { request } from '@/utils/request'; import { request } from '@/utils/request'
import { formatDateTime, regionOptions } from '../component/index'
//
const getdateRange = inject('getdateRange', ref([]))
const props = defineProps({ const props = defineProps({
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}); dispatchDateRange: {
type: Array,
default: () => [],
},
})
const emit = defineEmits(['update:visible', 'close']); const emit = defineEmits(['update:visible', 'close'])
// //
const filterForm = ref({ const filterForm = ref({
district: '', district: '',
}); })
//
const districtOptions = ref([
{ label: '万州区', value: 'wanzhou' },
{ label: '黔江区', value: 'qianjiang' },
{ label: '涪陵区', value: 'fuling' },
{ label: '渝中区', value: 'yuzhong' },
{ label: '大渡口区', value: 'dadukou' },
{ label: '江北区', value: 'jiangbei' },
{ label: '沙坪坝区', value: 'shapingba' },
{ label: '九龙坡区', value: 'jiulongpo' },
{ label: '南岸区', value: 'nanan' },
{ label: '北碚区', value: 'beibei' },
{ label: '渝北区', value: 'yubei' },
{ label: '巴南区', value: 'banan' },
{ label: '长寿区', value: 'changshou' },
{ label: '江津区', value: 'jiangjin' },
{ label: '合川区', value: 'hechuan' },
{ label: '永川区', value: 'yongchuan' },
{ label: '南川区', value: 'nanchuan' },
{ label: '綦江区', value: 'qijiang' },
{ label: '大足区', value: 'dazu' },
{ label: '璧山区', value: 'bishan' },
{ label: '铜梁区', value: 'tongliang' },
{ label: '潼南区', value: 'tongnan' },
{ label: '荣昌区', value: 'rongchang' },
{ label: '开州区', value: 'kaizhou' },
{ label: '梁平区', value: 'liangping' },
{ label: '武隆区', value: 'wulong' },
]);
// //
const tableHeight = ref(300); const tableHeight = ref(300)
// - // -
const tableColumns = ref([ const tableColumns = ref([
@ -98,80 +69,97 @@ const tableColumns = ref([
{ prop: 'inspectTime', label: '抽查时间' }, { prop: 'inspectTime', label: '抽查时间' },
{ prop: 'inspectedPerson', label: '被抽查人' }, { prop: 'inspectedPerson', label: '被抽查人' },
{ prop: 'contactPhone', label: '联系电话' }, { prop: 'contactPhone', label: '联系电话' },
]); ])
// //
const tableData = ref([]); const tableData = ref([])
// //
const currentPage = ref(1); const currentPage = ref(1)
const pageSize = ref(10); const pageSize = ref(10)
const total = ref(0); const total = ref(0)
// //
const handleClose = () => { const handleClose = () => {
emit('update:visible', false); emit('update:visible', false)
emit('close'); emit('close')
}; }
// //
const handleSizeChange = val => { const handleSizeChange = (val) => {
pageSize.value = val; pageSize.value = val
fetchData(); fetchData()
}; }
const handleCurrentChange = val => { const handleCurrentChange = (val) => {
currentPage.value = val; currentPage.value = val
fetchData(); fetchData()
}; }
// //
const handleFilterChange = () => { const handleFilterChange = () => {
currentPage.value = 1; currentPage.value = 1
fetchData(); fetchData()
}; }
// //
const fetchData = async () => { const fetchData = async () => {
try { try {
const res = await request({ const res = await request({
url: '/snow-ops-platform/inspection/personnel-list', url: '/snow-ops-platform/weather-warning/spot-check',
method: 'GET', method: 'GET',
params: { params: {
pageNum: currentPage.value, offset: (currentPage.value - 1) * pageSize.value,
pageSize: pageSize.value, limit: pageSize.value,
districtCode: filterForm.value.district, start: formatDateTime(props.dispatchDateRange?.[0]),
end: formatDateTime(props.dispatchDateRange?.[1]),
countyId: filterForm.value.district,
}, },
}); })
console.log(res, '抽查人次数据')
if (res.total > 0 && res.data) {
const data = res.data
tableData.value = data.map((item, index) => {
// command JSON
let commandData = {}
try {
if (item.command) {
commandData = JSON.parse(item.command)
}
} catch (e) {
console.error('解析 command 字段失败:', e)
}
const district = regionOptions.value.find((option) => option.value === item.countyId)?.label || '-'
if (res.code === '00000' && res.data) {
const data = res.data;
tableData.value = data.records.map((item, index) => {
return { return {
id: currentPage.value * pageSize.value - (pageSize.value - index - 1), id: currentPage.value * pageSize.value - (pageSize.value - index - 1),
district: item.districtName || '-', district: district,
inspectTime: item.inspectTime || '-', inspectTime: formatDateTime(item.createdAt) || '-',
inspectedPerson: item.inspectedPerson || '-', inspectedPerson: commandData.userName || '-',
contactPhone: item.contactPhone || '-', contactPhone: commandData.userPhone || '-',
}; }
}); })
total.value = data.total; total.value = data.total
} else {
tableData.value = []
total.value = 0
} }
} catch (error) { } catch (error) {
console.error('获取抽查人次数据失败:', error); console.error('获取抽查人次数据失败:', error)
}
} }
};
// visible // visible
watch( watch(
() => props.visible, () => props.visible,
newVal => { (newVal) => {
if (newVal) { if (newVal) {
currentPage.value = 1; currentPage.value = 1
fetchData(); fetchData()
} }
} },
); )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -332,7 +332,7 @@ const impactData = ref([
{ name: '影响桥梁', count: 0, icon: Icon0, type: '桥梁' }, { name: '影响桥梁', count: 0, icon: Icon0, type: '桥梁' },
{ name: '影响隧道', count: 0, icon: Icon2, type: '隧道' }, { name: '影响隧道', count: 0, icon: Icon2, type: '隧道' },
{ name: '影响边坡', count: 0, icon: Icon1, type: '边坡' }, { name: '影响边坡', count: 0, icon: Icon1, type: '边坡' },
{ name: '影响项目', count: 0, icon: Icon3, type: '驻地' }, { name: '影响驻地', count: 0, icon: Icon3, type: '驻地' },
]) ])
// //
const loadBarChartData = async () => { const loadBarChartData = async () => {
@ -396,11 +396,6 @@ const getColumnsByType = (type) => {
边坡: roadColumns, 边坡: roadColumns,
驻地: projectColumns, 驻地: projectColumns,
} }
// { name: '', count: 0, icon: Icon4, type: '' },
// { name: '', count: 0, icon: Icon0, type: '' },
// { name: '', count: 0, icon: Icon2, type: '' },
// { name: '', count: 0, icon: Icon1, type: '' },
// { name: '', count: 0, icon: Icon3, type: '' },
return typeMap[type] || bridgeColumns return typeMap[type] || bridgeColumns
} }

View File

@ -84,13 +84,11 @@ const props = defineProps({
const emit = defineEmits(['update:visible', 'close']) const emit = defineEmits(['update:visible', 'close'])
// //
const nationalRoadMileage = ref(345)
const ruralRoadMileage = ref(4333)
// //
const mileageData = ref([ const mileageData = ref([
{ name: '国省道', value: 345, icon: IconNational, type: 'national' }, { name: '国省道', value: 0, icon: IconNational, type: 'national' },
{ name: '农村公路', value: 4333, icon: IconRuralRoad, type: 'rural' }, { name: '农村公路', value: 0, icon: IconRuralRoad, type: 'rural' },
]) ])
// //
@ -183,7 +181,36 @@ const fetchData = async () => {
console.error('获取巡查里程列表数据失败:', error) console.error('获取巡查里程列表数据失败:', error)
} }
} }
//
const getInspectionStats = async () => {
try {
let params = {
start: '',
end: '',
}
if (props.getdateRange && props.getdateRange.length === 2) {
params.start = formatDateTime(props.getdateRange[0])
params.end = formatDateTime(props.getdateRange[1])
}
const res = await request({
url: '/snow-ops-platform/yhWgxc/weather-warning/inspection-stats',
method: 'GET',
params: params,
})
console.log('巡查统计数据:', res)
if (res.code == '00000' && res.data) {
const data = res.data
//
mileageData.value[0].value = data.nationalProvincialRoadMileage || '0'
mileageData.value[1].value = data.ruralRoadMileage || '0'
} else {
mileageData.value[0].value = '0'
mileageData.value[1].value = '0'
}
} catch (error) {
console.error('获取巡查统计数据失败:', error)
}
}
// visible // visible
watch( watch(
() => props.visible, () => props.visible,
@ -193,6 +220,7 @@ watch(
currentPage.value = 1 currentPage.value = 1
// fetchStatsData() // fetchStatsData()
fetchData() fetchData()
getInspectionStats()
}, },
) )
</script> </script>

View File

@ -43,13 +43,27 @@
<div class="filter-row"> <div class="filter-row">
<div class="filter-item"> <div class="filter-item">
<span class="filter-label">影响点等级</span> <span class="filter-label">影响点等级</span>
<el-select :teleported="false" v-model="filterForm.pointLevel" placeholder="影响点等级" class="filter-select"> <el-select
:teleported="false"
v-model="filterForm.pointLevel"
placeholder="影响点等级"
clearable
class="filter-select"
@change="handleFilterChange"
>
<el-option v-for="option in pointLevelOptions" :key="option.value" :label="option.label" :value="option.value" /> <el-option v-for="option in pointLevelOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select> </el-select>
</div> </div>
<div class="filter-item"> <div class="filter-item">
<span class="filter-label">是否回应</span> <span class="filter-label">是否回应</span>
<el-select :teleported="false" v-model="filterForm.isResponded" placeholder="是否回应" class="filter-select"> <el-select
:teleported="false"
v-model="filterForm.isResponded"
placeholder="是否回应"
clearable
class="filter-select"
@change="handleFilterChange"
>
<el-option v-for="option in isRespondedOptions" :key="option.value" :label="option.label" :value="option.value" /> <el-option v-for="option in isRespondedOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select> </el-select>
</div> </div>
@ -286,7 +300,9 @@ const fetchData = async () => {
end: '', end: '',
offset: (currentPage.value - 1) * pageSize.value, offset: (currentPage.value - 1) * pageSize.value,
limit: pageSize.value, limit: pageSize.value,
warningId: props.responseStatusData.warningId, warningId: props.responseStatusData.warningId || '',
riskLevel: filterForm.value.pointLevel || '',
isResponded: filterForm.value.isResponded,
} }
if (props.dispatchDateRange && props.dispatchDateRange.length > 0) { if (props.dispatchDateRange && props.dispatchDateRange.length > 0) {
params.start = formatDateTime(props.dispatchDateRange[0]) || '' params.start = formatDateTime(props.dispatchDateRange[0]) || ''
@ -386,6 +402,14 @@ const handleSearch = () => {
fetchData() fetchData()
loadBarChartData() loadBarChartData()
} }
const handleFilterChange = () => {
console.log(filterForm.value)
filterForm.value.pointLevel = filterForm.value.pointLevel || ''
filterForm.value.isResponded = filterForm.value.isResponded
currentPage.value = 1
fetchData()
}
// visible // visible
watch( watch(

View File

@ -248,10 +248,16 @@ const getLevelClass = (riskLevel) => {
watch( watch(
() => props.visible, () => props.visible,
(newVal) => { (newVal) => {
if (newVal) {
currentPage.value = 1 currentPage.value = 1
filterForm.value.warningLevel = ''
filterForm.value.region = ''
filterForm.value.isEnded = ''
filterForm.value.isResponded = ''
filterForm.value.district = ''
filterForm.value.countyId = ''
tableData.value = []
total.value = 0
fetchData() fetchData()
}
}, },
) )
@ -261,6 +267,14 @@ watch(
() => { () => {
if (props.visible) { if (props.visible) {
currentPage.value = 1 currentPage.value = 1
filterForm.value.warningLevel = ''
filterForm.value.region = ''
filterForm.value.isEnded = ''
filterForm.value.isResponded = ''
filterForm.value.district = ''
filterForm.value.countyId = ''
tableData.value = []
total.value = 0
fetchData() fetchData()
} }
}, },

View File

@ -2078,7 +2078,7 @@ defineExpose({
// } // }
.center-info-card { .center-info-card {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); // box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;

View File

@ -201,7 +201,6 @@ export const logUserOperation = (type, command) => {
} }
} }
// 打开视频会议 // 打开视频会议
export const openVideoConference = async (item) => { export const openVideoConference = async (item) => {
console.log('打开视频会议:', item) console.log('打开视频会议:', item)
@ -229,6 +228,8 @@ export const openVideoConference = async (item) => {
userName: item.name, userName: item.name,
userPhone: item.phone, userPhone: item.phone,
id: item.id, id: item.id,
type: item.type,
role: item.role,
userId: userId, userId: userId,
text: '打开视频会议', text: '打开视频会议',
} }
@ -270,6 +271,8 @@ export const openVoiceConference = async (item) => {
userName: item.name, userName: item.name,
userPhone: item.phone, userPhone: item.phone,
id: item.id, id: item.id,
role: item.role,
type: item.type,
userId: userId, userId: userId,
text: '打开语音通话', text: '打开语音通话',
} }
@ -297,6 +300,8 @@ export const opencallConference = async (item) => {
userName: item.name, userName: item.name,
userPhone: item.phone, userPhone: item.phone,
id: item.id, id: item.id,
role: item.role,
type: item.type,
userId: '', userId: '',
text: '拨打电话', text: '拨打电话',
} }

View File

@ -199,10 +199,15 @@
<controlSituationDialog v-model:visible="dialogVisible.controlSituation" @close="closeDialog('controlSituation')" /> <controlSituationDialog v-model:visible="dialogVisible.controlSituation" @close="closeDialog('controlSituation')" />
<!-- 调度详情对话框 --> <!-- 调度详情对话框 -->
<dispatchDetailDialog v-model:visible="dialogVisible.dispatchDetail" @close="closeDialog('dispatchDetail')" /> <dispatchDetailDialog
:dispatchDateRange="dispatchDateRange"
v-model:visible="dialogVisible.dispatchDetail"
@close="closeDialog('dispatchDetail')"
/>
<!-- 调度区县情况对话框 --> <!-- 调度区县情况对话框 -->
<dispatchDistrictDialog <dispatchDistrictDialog
:dispatchDateRange="dispatchDateRange"
v-model:visible="dialogVisible.dispatchDistrict" v-model:visible="dialogVisible.dispatchDistrict"
@close="closeDialog('dispatchDistrict')" @close="closeDialog('dispatchDistrict')"
@dispatchClick="openDialog('dispatchDetail')" @dispatchClick="openDialog('dispatchDetail')"
@ -240,7 +245,11 @@
<offlineHelpDialog v-model:visible="dialogVisible.offlineHelp" @close="closeDialog('offlineHelp')" /> <offlineHelpDialog v-model:visible="dialogVisible.offlineHelp" @close="closeDialog('offlineHelp')" />
<!-- 抽查人次对话框 --> <!-- 抽查人次对话框 -->
<imageInspectionDialog v-model:visible="dialogVisible.imageInspection" @close="closeDialog('imageInspection')" /> <imageInspectionDialog
v-model:visible="dialogVisible.imageInspection"
:dispatchDateRange="dispatchDateRange"
@close="closeDialog('imageInspection')"
/>
<!-- 巡查里程对话框 --> <!-- 巡查里程对话框 -->
<patrolMileageDialog v-model:visible="dialogVisible.patrolMileage" :getdateRange="getdateRange" @close="closeDialog('patrolMileage')" /> <patrolMileageDialog v-model:visible="dialogVisible.patrolMileage" :getdateRange="getdateRange" @close="closeDialog('patrolMileage')" />
@ -574,15 +583,15 @@ const allCountyData = ref({})
const handleDistrictClick = (item) => { const handleDistrictClick = (item) => {
console.log('区县点击:', item) console.log('区县点击:', item)
allCountyData.value = item allCountyData.value = item
if (item.data.roadType == 'national') { // if (item.data.roadType == 'national') {
// // //
openDialog('tongnanTeam') // openDialog('tongnanTeam')
} else if (item.data.roadType == 'rural') { // } else if (item.data.roadType == 'rural') {
openDialog('responseSituation') // openDialog('responseSituation')
} else if (item.data.type == 'project' && item.data.roadType == '-') { // } else if (item.data.type == 'project' && item.data.roadType == '-') {
// // //
openDialog('tongnanResponsible') // openDialog('tongnanResponsible')
} // }
} }
// //

View File

@ -200,11 +200,13 @@ const handleStatClick = (item) => {
emit('openResponseStatus') emit('openResponseStatus')
emit('dispatchDateRange', dateRange.value) emit('dispatchDateRange', dateRange.value)
} else if (item.label === '调度区县数') { } else if (item.label === '调度区县数') {
emit('dispatchDateRange', dateRange.value)
emit('openDispatchDistrict') emit('openDispatchDistrict')
} else if (item.label === '线下帮扶数') { } else if (item.label === '线下帮扶数') {
emit('openOfflineHelp') emit('openOfflineHelp')
} else if (item.label === '抽查人次') { } else if (item.label === '抽查人次') {
emit('openImageInspection') emit('openImageInspection')
emit('dispatchDateRange', dateRange.value)
} }
} }