This commit is contained in:
2026-04-27 10:39:31 +08:00
parent 78291628ea
commit e88f8b921c
6 changed files with 55 additions and 781 deletions

View File

@ -25,7 +25,7 @@
import router from "../router/index.js"; import router from "../router/index.js";
import { getBase64 } from "../utils/tools.js"; import { getBase64 } from "../utils/tools.js";
import { defineProps, ref, watch } from "vue"; import { defineProps, ref, watch } from "vue";
import { getDictList, setDict } from "../utils/dict"; import { getDictList, setDict } from "../utils/dict.js";
import { ImagePreview } from "vant"; import { ImagePreview } from "vant";
import { qcckGet } from "@/api/qcckApi.js"; import { qcckGet } from "@/api/qcckApi.js";
const props = defineProps({ const props = defineProps({

View File

@ -1,393 +0,0 @@
<template>
<div class="detail-page">
<!-- 顶部导航栏 -->
<div class="nav-bar">
<van-icon name="arrow-left" class="nav-back" @click="goBack" />
<div class="nav-title">紧急任务详情</div>
<div class="nav-placeholder"></div>
</div>
<!-- 任务信息卡片 -->
<div class="task-card">
<div class="card-header">
<div class="task-type" :class="task.typeClass">
{{ task.type }}
</div>
<div class="task-level" :class="task.levelClass">
{{ task.level }}
</div>
</div>
<div class="card-body">
<div class="info-row">
<van-icon name="location-o" class="row-icon" />
<span class="label">任务地点</span>
<span class="value">{{ task.location }}</span>
</div>
<div class="info-row">
<van-icon name="clock-o" class="row-icon" />
<span class="label">下发时间</span>
<span class="value">{{ task.issueTime }}</span>
</div>
<div class="info-row">
<van-icon name="user-o" class="row-icon" />
<span class="label">下发人</span>
<span class="value">{{ task.issuer }}</span>
</div>
<div class="info-row">
<van-icon name="phone-o" class="row-icon" />
<span class="label">联系电话</span>
<span class="value link">{{ task.contact }}</span>
</div>
</div>
<div class="task-desc">
<div class="desc-title">任务描述</div>
<div class="desc-content">{{ task.description }}</div>
</div>
</div>
<!-- 执行记录 -->
<div class="detail-card" v-if="task.records && task.records.length > 0">
<div class="card-title">执行记录</div>
<div class="record-list">
<div v-for="(record, index) in task.records" :key="index" class="record-item">
<div class="record-dot" :class="record.status"></div>
<div class="record-content">
<div class="record-time">{{ record.time }}</div>
<div class="record-text">{{ record.content }}</div>
</div>
</div>
</div>
</div>
<!-- 附件 -->
<div class="detail-card">
<div class="card-title">附件</div>
<div class="attachment-list">
<div v-for="(item, index) in task.attachments" :key="index" class="attachment-item">
<van-icon name="description" class="attachment-icon" />
<span class="attachment-name">{{ item.name }}</span>
<van-icon name="down" class="download-icon" />
</div>
</div>
</div>
<!-- 底部操作按钮 -->
<div class="action-bar">
<van-button block round type="primary" class="action-btn" @click="handleExecute">
{{ task.status === 'completed' ? '查看完成' : '立即执行' }}
</van-button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import { Toast } from "vant";
const router = useRouter();
const route = useRoute();
// 任务详情数据
const task = ref({
id: "",
type: "紧急疏散",
typeClass: "type-emergency",
level: "一级",
levelClass: "level-high",
location: "光谷广场地铁站",
issueTime: "03/28 14:30",
issuer: "应急指挥中心",
contact: "027-88888888",
description: "光谷广场地铁站周边出现紧急情况,需立即组织人员疏散。请相关人员迅速到位,协助维持秩序。",
status: "pending",
records: [
{ time: "03/28 14:35", content: "任务已接收,正在前往现场", status: "success" },
{ time: "03/28 14:40", content: "已到达现场,开始执行疏散任务", status: "success" }
],
attachments: [
{ name: "紧急疏散方案.pdf" },
{ name: "现场平面图.jpg" }
]
});
// 返回
function goBack() {
router.back();
}
// 执行任务
function handleExecute() {
if (task.value.status === "completed") {
Toast("该任务已完成");
} else {
router.push("/dataReport");
}
}
onMounted(() => {
const taskData = route.query;
if (taskData.id) {
task.value.id = taskData.id;
}
});
</script>
<style lang="scss" scoped>
.detail-page {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 100px;
}
.nav-bar {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
background: white;
border-bottom: 1px solid #e5e5e5;
padding: 12px 16px;
.nav-back {
font-size: 20px;
color: #333;
}
.nav-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.nav-placeholder {
width: 20px;
}
}
.task-card {
background: white;
margin: 16px;
border-radius: 16px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
}
.task-type {
padding: 6px 12px;
border-radius: 8px;
font-size: 15px;
font-weight: 600;
&.type-emergency {
background: #fee2e2;
color: #dc2626;
}
}
.task-level {
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
&.level-high {
background: #fef3c7;
color: #d97706;
}
&.level-medium {
background: #e0e7ff;
color: #4f46e5;
}
&.level-low {
background: #ecfdf5;
color: #16a34a;
}
}
.card-body {
.info-row {
display: flex;
align-items: center;
margin-bottom: 12px;
font-size: 14px;
&:last-child {
margin-bottom: 0;
}
.row-icon {
font-size: 16px;
color: #999;
margin-right: 8px;
}
.label {
color: #999;
}
.value {
color: #333;
flex: 1;
&.link {
color: #2563eb;
}
}
}
}
.task-desc {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #f0f0f0;
.desc-title {
font-size: 14px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.desc-content {
font-size: 14px;
color: #666;
line-height: 1.6;
}
}
.detail-card {
background: white;
margin: 16px;
margin-top: 0;
border-radius: 16px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.card-title {
font-size: 15px;
font-weight: 600;
color: #333;
margin-bottom: 16px;
}
.record-list {
position: relative;
padding-left: 20px;
&::before {
content: "";
position: absolute;
left: 5px;
top: 8px;
bottom: 8px;
width: 2px;
background: #e5e5e5;
}
.record-item {
position: relative;
padding-bottom: 16px;
&:last-child {
padding-bottom: 0;
}
.record-dot {
position: absolute;
left: -17px;
top: 4px;
width: 10px;
height: 10px;
border-radius: 50%;
&.success {
background: #16a34a;
}
&.pending {
background: #ea580c;
}
}
.record-content {
.record-time {
font-size: 12px;
color: #999;
margin-bottom: 4px;
}
.record-text {
font-size: 14px;
color: #333;
}
}
}
}
.attachment-list {
.attachment-item {
display: flex;
align-items: center;
padding: 12px;
background: #f9fafb;
border-radius: 12px;
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.attachment-icon {
font-size: 24px;
color: #666;
margin-right: 12px;
}
.attachment-name {
flex: 1;
font-size: 14px;
color: #333;
}
.download-icon {
font-size: 18px;
color: #2563eb;
}
}
}
.action-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
border-top: 1px solid #e5e5e5;
padding: 12px 16px;
padding-bottom: calc(12px + env(safe-area-inset-bottom));
}
.action-btn {
height: 44px;
font-size: 16px;
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
border: none;
}
</style>

View File

@ -1,322 +0,0 @@
<template>
<div class="emergency-tasks-page">
<!-- 顶部导航栏 -->
<div class="nav-bar">
<van-icon name="arrow-left" class="nav-back" @click="goBack" />
<div class="nav-title">紧急任务</div>
<div class="nav-placeholder"></div>
</div>
<!-- 标签栏 -->
<div class="tabs-wrapper">
<div class="tabs-container">
<div
v-for="tab in tabs"
:key="tab.id"
class="tab-item"
:class="{ active: activeTab === tab.id }"
@click="activeTab = tab.id"
>
{{ tab.label }}
</div>
</div>
</div>
<!-- 任务列表 -->
<div class="tasks-container">
<div
v-for="task in filteredTasks"
:key="task.id"
class="task-card"
@click="goToDetail(task)"
>
<div class="task-header">
<div class="task-info">
<h3 class="task-type">{{ task.type }}</h3>
<span class="task-level" :class="task.levelClass">{{ task.level }}</span>
</div>
<span class="task-status" :class="task.statusClass">{{ task.statusText }}</span>
</div>
<div class="task-details">
<div class="detail-item">
<van-icon name="location-o" />
<span>{{ task.location }}</span>
</div>
<div class="detail-item">
<van-icon name="clock-o" />
<span>{{ task.time }}</span>
</div>
<div class="detail-item">
<van-icon name="user-o" />
<span>{{ task.issuer }}</span>
</div>
</div>
<van-button
v-if="task.status !== 'completed'"
block
round
type="primary"
class="execute-btn"
>
立即执行
</van-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
// 当前激活的标签
const activeTab = ref("all");
// 标签配置
const tabs = [
{ id: "all", label: "全部" },
{ id: "not-executed", label: "未执行" },
{ id: "processing", label: "执行中" },
{ id: "completed", label: "已完成" },
];
// 任务数据
const tasks = ref([
{
id: 1,
type: "紧急疏散",
level: "一级",
levelClass: "level-danger",
location: "光谷广场地铁站",
time: "03/28 14:30",
issuer: "应急指挥中心",
status: "pending",
statusClass: "status-pending",
statusText: "待处理",
},
{
id: 2,
type: "火灾救援",
level: "一级",
levelClass: "level-danger",
location: "科技大厦A座",
time: "03/28 15:20",
issuer: "安全管理部门",
status: "processing",
statusClass: "status-processing",
statusText: "执行中",
},
{
id: 3,
type: "医疗救护",
level: "二级",
levelClass: "level-warning",
location: "人民公园东门",
time: "03/28 10:00",
issuer: "急救中心",
status: "completed",
statusClass: "status-completed",
statusText: "已完成",
},
]);
// 根据标签过滤任务
const filteredTasks = computed(() => {
if (activeTab.value === "all") {
return tasks.value;
}
if (activeTab.value === "not-executed") {
return tasks.value.filter((task) => task.status === "pending");
}
if (activeTab.value === "processing") {
return tasks.value.filter((task) => task.status === "processing");
}
if (activeTab.value === "completed") {
return tasks.value.filter((task) => task.status === "completed");
}
return tasks.value;
});
// 返回上一页
function goBack() {
router.back();
}
// 跳转到详情页
function goToDetail(task) {
router.push({
path: "/emergency-task-detail",
query: { id: task.id },
});
}
</script>
<style lang="scss" scoped>
.emergency-tasks-page {
min-height: 100vh;
background: #f5f5f5;
}
.nav-bar {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
background: white;
border-bottom: 1px solid #e5e5e5;
padding: 12px 16px;
.nav-back {
font-size: 20px;
color: #333;
}
.nav-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.nav-placeholder {
width: 20px;
}
}
.tabs-wrapper {
background: white;
padding: 12px 16px;
}
.tabs-container {
display: flex;
gap: 12px;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.tab-item {
flex-shrink: 0;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
white-space: nowrap;
background: white;
color: #666;
border: 1px solid #e5e5e5;
transition: all 0.2s;
&.active {
background: #ee0a24;
color: white;
border-color: #ee0a24;
}
}
.tasks-container {
padding: 16px;
}
.task-card {
background: white;
border-radius: 16px;
padding: 16px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.task-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 16px;
}
.task-info {
.task-type {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
}
.task-level {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
&.level-danger {
background: #fef2f2;
color: #dc2626;
}
&.level-warning {
background: #fffbeb;
color: #d97706;
}
}
.task-status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
border: 1px solid;
&.status-pending {
background: #fff7ed;
color: #ea580c;
border-color: #fed7aa;
}
&.status-processing {
background: #eff6ff;
color: #2563eb;
border-color: #bfdbfe;
}
&.status-completed {
background: #f0fdf4;
color: #16a34a;
border-color: #bbf7d0;
}
}
.task-details {
.detail-item {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
font-size: 14px;
color: #666;
&:last-child {
margin-bottom: 0;
}
.van-icon {
font-size: 16px;
color: #999;
}
}
}
.execute-btn {
margin-top: 16px;
height: 40px;
font-size: 14px;
background: linear-gradient(135deg, #ee0a24 0%, #bd2a2a 100%);
border: none;
}
</style>

View File

@ -217,7 +217,6 @@ async function onLoad() {
finished.value = true; finished.value = true;
} }
} catch (error) { } catch (error) {
console.error("获取拦截预警列表失败:", error);
alertList.value = []; alertList.value = [];
finished.value = true; finished.value = true;
} finally { } finally {
@ -278,7 +277,6 @@ async function fetchTaskStats() {
}); });
} }
} catch (error) { } catch (error) {
console.error("获取任务统计数据失败:", error);
} }
} }

View File

@ -421,46 +421,46 @@ const routes = [
name: "yyzx/jqxx/mryq", name: "yyzx/jqxx/mryq",
component: () => import("../pages/yyzx/jqxx/mryq"), component: () => import("../pages/yyzx/jqxx/mryq"),
}, },
{ // {
path: "/newTwoHome", // path: "/newTwoHome",
name: "newTwoHome", // name: "newTwoHome",
component: () => import("../pages/newTwoHome/index"), // component: () => import("../pages/newTwoHome/index"),
}, // },
{ // {
path: "/newTwoHome/ldjsc", // path: "/newTwoHome/ldjsc",
name: "newTwoHome/ldjsc", // name: "newTwoHome/ldjsc",
component: () => import("../pages/newTwoHome/ldjsc"), // component: () => import("../pages/newTwoHome/ldjsc"),
}, // },
{ // {
path: "/newTwoHome/xd", // path: "/newTwoHome/xd",
name: "newTwoHome/xd", // name: "newTwoHome/xd",
component: () => import("../pages/newTwoHome/xd"), // component: () => import("../pages/newTwoHome/xd"),
}, // },
{ // {
path: "/newTwoHome/zjq", // path: "/newTwoHome/zjq",
name: "newTwoHome/zjq", // name: "newTwoHome/zjq",
component: () => import("../pages/newTwoHome/zjq"), // component: () => import("../pages/newTwoHome/zjq"),
}, // },
{ // {
path: "/newTwoHome/zbbbList", // path: "/newTwoHome/zbbbList",
name: "newTwoHome/zbbbList", // name: "newTwoHome/zbbbList",
component: () => import("../pages/newTwoHome/zbbbList"), // component: () => import("../pages/newTwoHome/zbbbList"),
}, // },
{ // {
path: "/newTwoHome/yclList", // path: "/newTwoHome/yclList",
name: "newTwoHome/yclList", // name: "newTwoHome/yclList",
component: () => import("../pages/newTwoHome/yclList"), // component: () => import("../pages/newTwoHome/yclList"),
}, // },
{ // {
path: "/newTwoHome/addZl", // path: "/newTwoHome/addZl",
name: "newTwoHome/addZl", // name: "newTwoHome/addZl",
component: () => import("../pages/newTwoHome/addZl"), // component: () => import("../pages/newTwoHome/addZl"),
}, // },
{ // {
path: "/newTwoHome/myZl", // path: "/newTwoHome/myZl",
name: "newTwoHome/myZl", // name: "newTwoHome/myZl",
component: () => import("../pages/newTwoHome/myZl"), // component: () => import("../pages/newTwoHome/myZl"),
}, // },
{ {
path: "/my/views/wdgjMapPoint", path: "/my/views/wdgjMapPoint",
name: "my/views/wdgjMapPoint", name: "my/views/wdgjMapPoint",
@ -583,16 +583,7 @@ const routes = [
name: "keyVehicle-detail", name: "keyVehicle-detail",
component: () => import("../pages/keyVehicle/detail.vue"), component: () => import("../pages/keyVehicle/detail.vue"),
}, },
{
path: "/emergencyTasks",
name: "emergencyTasks",
component: () => import("../pages/emergencyTasks/index.vue"),
},
{
path: "/emergencyTask/detail",
name: "emergencyTask-detail",
component: () => import("../pages/emergencyTasks/detail.vue"),
},
{ {
path: "/dataReport", path: "/dataReport",
name: "dataReport", name: "dataReport",

View File

@ -1,6 +1,7 @@
import axios from 'axios'; import axios from 'axios';
import { hintToast } from "./tools"; import { hintToast } from "./tools";
import router from '@/router';
let baseUrl2 = ''; //二类区地址 let baseUrl2 = ''; //二类区地址
let baseUrlZddwUrl = ''; //重点单位地址 let baseUrlZddwUrl = ''; //重点单位地址
let gjURL = '/api'; let gjURL = '/api';
@ -38,24 +39,18 @@ service.interceptors.request.use(
); );
// 2.响应拦截器 // 2.响应拦截器
service.interceptors.response.use( service.interceptors.response.use((response) => {
// 请求成功的处理 // 请求成功的处理
(response) => { const {success,code,msg,message,data,status } = response.data;
const { console.log(response.data,'=======sssss==');
success,
code,
msg,
message,
data,
status
} = response.data;
// 需要判断当前请求是否成功 // 需要判断当前请求是否成功
if (success && code === 10000) { if (success && code === 10000) {
return data; // 成功后返回解析后的数据 return data; // 成功后返回解析后的数据
} else if (code === 200 || code == "00000") { } else if (code === 200 || code == "00000") {
return data; // 成功后返回解析后的数据 return data; // 成功后返回解析后的数据
} else if (code === 401) { } else if (code === 401) {
// store.dispatch('user/logout'); // 401未授权跳转到登录页
// ElMessage.error(message); // 提示错误信息 // ElMessage.error(message); // 提示错误信息
// hintToast(message) // hintToast(message)
} else { } else {
@ -67,7 +62,12 @@ service.interceptors.response.use(
// 请求失败处理 // 请求失败处理
(error) => { (error) => {
//token过期 //token过期
// hintToast(error.message) if(error.response && error.response.status === 401) {
// hintToast('登录过期,请重新登录');
localStorage.clear();
router.push('/');
return Promise.reject(new Error('登录过期,请重新登录'));
}
return Promise.reject(error); return Promise.reject(error);
} }
); );