| | |
| | | <!-- 搜索 --> |
| | | <div class="flex a-center gap--16 mt--24 mb--20"> |
| | | <div |
| | | class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox" |
| | | class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox cascader-box" |
| | | > |
| | | <el-select |
| | | filterable |
| | | v-model="projectId" |
| | | <el-cascader |
| | | v-model="cascaderValue" |
| | | :options="cityOptions" |
| | | :props="cascaderProps" |
| | | placeholder="选择城市" |
| | | class="flex1" |
| | | clearable |
| | | @change="handleCityChange" |
| | | filterable |
| | | > |
| | | <el-option |
| | | v-for="item in [1, 2]" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <img |
| | | src="../../assets/img/down-circle@2x.png" |
| | | class="w--15 h--16 shrink0" |
| | | /> |
| | | </el-cascader> |
| | | <div class="flex a-center gap--5"> |
| | | <i |
| | | @click.stop="handleClearCity" |
| | | class="el-icon-circle-close c-fff cursor-pointer" |
| | | v-show="cascaderValue && cascaderValue.length > 0" |
| | | /> |
| | | <img |
| | | src="../../assets/img/down-circle@2x.png" |
| | | class="w--15 h--16 shrink0" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div |
| | | class="flex a-center j-between pl--18 pr--15 h--40 relative w--300 bgcolor1 searchBox" |
| | | > |
| | | <el-select |
| | | filterable |
| | | v-model="projectId" |
| | | placeholder="选择工作类型" |
| | | v-model="classifyId" |
| | | placeholder="选择事故类型" |
| | | class="flex1" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in [1, 2]" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | v-for="item in classifyList" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <img |
| | | src="../../assets/img/down-circle@2x.png" |
| | | class="w--15 h--16 shrink0" |
| | | /> |
| | | <div class="flex a-center gap--5"> |
| | | <i |
| | | @click.stop="handleClearClassify" |
| | | class="el-icon-circle-close c-fff cursor-pointer" |
| | | v-show="classifyId" |
| | | /> |
| | | <img |
| | | src="../../assets/img/down-circle@2x.png" |
| | | class="w--15 h--16 shrink0" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div |
| | | @click="handleClick(1)" |
| | |
| | | ref="datetime1" |
| | | type="datetime" |
| | | placeholder="" |
| | | @change="handleDateChange" |
| | | > |
| | | </el-date-picker> |
| | | <div |
| | | class="absolute w100 h100 flex a-center c-fff fs--14 SHS" |
| | | style="width: calc(100% - 20px)" |
| | | v-if="dateTxt" |
| | | class="absolute w100 h100 flex a-center px--20" |
| | | style="pointer-events: none" |
| | | > |
| | | {{ dateTxt }} |
| | | <div |
| | | class="flex a-center c-fff fs--14 SHS" |
| | | style="width: calc(100% - 20px)" |
| | | > |
| | | {{ dateTxt || "请选择开始日期" }} |
| | | </div> |
| | | <div class="flex a-center gap--5" style="pointer-events: auto"> |
| | | <i |
| | | @click.stop="handleClearStartDate" |
| | | class="el-icon-circle-close c-fff cursor-pointer" |
| | | v-show="dateTxt" |
| | | /> |
| | | <img |
| | | src="../../assets/img/home/Shape@2x (6).png" |
| | | class="w--13 h--13 shrink0" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div |
| | | v-else |
| | | class="absolute w100 h100 flex a-center c-fff fs--14 SHSR" |
| | | > |
| | | 请选择日期 |
| | | </div> |
| | | <img |
| | | src="../../assets/img/home/Shape@2x (6).png" |
| | | class="w--13 h--13 shrink0" |
| | | /> |
| | | </div> |
| | | <div |
| | | @click="handleClick(2)" |
| | | class="flex a-center j-between px--20 w--300 h--40 relative bgcolor1 picker" |
| | | > |
| | | <el-date-picker |
| | | v-model="dateTime" |
| | | v-model="dateTime2" |
| | | ref="datetime2" |
| | | type="datetime" |
| | | placeholder="" |
| | | @change="handleDateChange" |
| | | > |
| | | </el-date-picker> |
| | | <div |
| | | class="absolute w100 h100 flex a-center c-fff fs--14 SHS" |
| | | style="width: calc(100% - 20px)" |
| | | v-if="dateTxt" |
| | | class="absolute w100 h100 flex a-center px--20" |
| | | style="pointer-events: none" |
| | | > |
| | | {{ dateTxt }} |
| | | <div |
| | | class="flex a-center c-fff fs--14 SHS" |
| | | style="width: calc(100% - 20px)" |
| | | > |
| | | {{ dateTxt2 || "请选择结束日期" }} |
| | | </div> |
| | | <div class="flex a-center gap--5" style="pointer-events: auto"> |
| | | <i |
| | | @click.stop="handleClearEndDate" |
| | | class="el-icon-circle-close c-fff cursor-pointer" |
| | | v-show="dateTxt2" |
| | | /> |
| | | <img |
| | | src="../../assets/img/home/Shape@2x (6).png" |
| | | class="w--13 h--13 shrink0" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div |
| | | v-else |
| | | class="absolute w100 h100 flex a-center c-fff fs--14 SHSR" |
| | | > |
| | | 请选择日期 |
| | | </div> |
| | | <img |
| | | src="../../assets/img/home/Shape@2x (6).png" |
| | | class="w--13 h--13 shrink0" |
| | | /> |
| | | </div> |
| | | <div |
| | | class="flex a-center j-between w--300 pl--20 h--40 relative bgcolor1 searchBox" |
| | | > |
| | | <el-select |
| | | filterable |
| | | v-model="projectId" |
| | | <el-input |
| | | v-model="content" |
| | | placeholder="请输入搜索内容" |
| | | class="flex1" |
| | | @keyup.enter.native="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in [1, 2]" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <div class="btn SHSR">搜索</div> |
| | | </el-input> |
| | | <div class="btn SHSR" @click="handleSearch">搜索</div> |
| | | </div> |
| | | </div> |
| | | <!-- 表格 --> |
| | | <div class="mt--20 border1 oa" style="height: 800px"> |
| | | <div class="mt--20 border1 oa" style="height: 800px" v-loading="loading"> |
| | | <div |
| | | v-for="(item, index) in 10" |
| | | :key="item" |
| | | v-for="(item, index) in storyList" |
| | | :key="item.id" |
| | | class="flex a-center j-between px--32 py--20 c-fff cursor-pointer tableItem" |
| | | :class="{ bgcolor2: (index + 1) % 2 != 0 }" |
| | | @click="toDetail(item)" |
| | | > |
| | | <div class="flex a-center"> |
| | | <div class="fs--29 lh--29 SHSN">31</div> |
| | | <div class="fs--29 lh--29 SHSN">{{ formatDay(item.time) }}</div> |
| | | <div class="border2 ml--15 mr--16"></div> |
| | | <div class="fs--12 lh--14 SHSN color1"> |
| | | <p>2025</p> |
| | | <p>12</p> |
| | | <p>{{ formatYearMonth(item.time).year }}</p> |
| | | <p>{{ formatYearMonth(item.time).month }}</p> |
| | | </div> |
| | | </div> |
| | | <div class="ml--79 flex1"> |
| | | <div class="fs--20 lh--20 SHSBold mt--2"> |
| | | 秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢 |
| | | {{ item.title }} |
| | | </div> |
| | | <div class="flex a-center j-between mt--6"> |
| | | <div class="flex a-center gap--7"> |
| | |
| | | src="../../assets/img/home/Shape@2x (2).png" |
| | | class="shrink0 w--8 h--9" |
| | | /> |
| | | <div class="fs--12 lh--12 c-fff SHSN">河北省秦皇岛市昌黎县</div> |
| | | <div class="fs--12 lh--12 c-fff SHSN"> |
| | | {{ item.province }}{{ item.city }}{{ item.area }} |
| | | </div> |
| | | </div> |
| | | <div class="typeBox">塔吊倒塌</div> |
| | | <div class="typeBox" v-if="item.classifyName"> |
| | | {{ item.classifyName }} |
| | | </div> |
| | | </div> |
| | | <div class="mt--5 fs--14 lh--20 SHSR c-fff"> |
| | | 秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故秦皇岛市钢铁厂发生塔吊倒塌事故 |
| | | <div class="mt--5 fs--14 lh--20 SHSR c-fff text-ellipsis-3"> |
| | | {{ item.content }} |
| | | </div> |
| | | </div> |
| | | <img |
| | | v-if="item.img" |
| | | :src="'http://47.108.113.190:8181/public/file/download' + item.img" |
| | | class="w--264 h--160 shrink0 ml--54 br--10" |
| | | @error="handleImageError" |
| | | /> |
| | | <img |
| | | v-else |
| | | src="../../assets/img/logo.png" |
| | | class="w--264 h--160 shrink0 ml--54 br--10" |
| | | /> |
| | | </div> |
| | | <div |
| | | v-if="!loading && storyList.length === 0" |
| | | class="flex a-center j-center c-fff fs--16" |
| | | style="height: 100%" |
| | | > |
| | | 暂无数据 |
| | | </div> |
| | | </div> |
| | | <CustomPagination |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | :current-page="currentPage" |
| | | :page-sizes="[100, 200, 300, 400]" |
| | | :page-size="10" |
| | | :total="400" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | :page-size="pageSize" |
| | | :total="total" |
| | | /> |
| | | </div> |
| | | </div> |
| | |
| | | <script> |
| | | import HeaderBox from "../header/index.vue"; |
| | | import moment from "moment"; |
| | | import { getAccidentClassify, getStoryPage } from "./service"; |
| | | |
| | | export default { |
| | | components: { HeaderBox }, |
| | | props: {}, |
| | | data() { |
| | | return { |
| | | dateTime: null, |
| | | projectId: null, |
| | | dateTime2: null, |
| | | city: null, |
| | | classifyId: null, |
| | | content: "", |
| | | dateTxt: "", |
| | | dateTxt2: "", |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | cityOptions: [], |
| | | cascaderValue: [], |
| | | cascaderProps: { |
| | | lazy: true, |
| | | lazyLoad: this.loadCityData, |
| | | checkStrictly: true, |
| | | }, |
| | | classifyList: [], |
| | | storyList: [], |
| | | loading: false, |
| | | }; |
| | | }, |
| | | computed: {}, |
| | |
| | | handler(newVal, oldVal) { |
| | | if (newVal) { |
| | | this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss"); |
| | | } else { |
| | | this.dateTxt = ""; |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | dateTime2: { |
| | | handler(newVal, oldVal) { |
| | | if (newVal) { |
| | | this.dateTxt2 = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss"); |
| | | } else { |
| | | this.dateTxt2 = ""; |
| | | } |
| | | }, |
| | | immediate: true, |
| | | }, |
| | | }, |
| | | created() {}, |
| | | created() { |
| | | this.initCityOptions(); |
| | | this.loadClassifyList(); |
| | | this.loadStoryList(); |
| | | }, |
| | | mounted() {}, |
| | | methods: { |
| | | // 初始化城市选项(加载省份) |
| | | async initCityOptions() { |
| | | try { |
| | | const provinces = await this.getDistrictData(); |
| | | this.cityOptions = provinces; |
| | | } catch (error) { |
| | | console.error("加载省份数据失败:", error); |
| | | } |
| | | }, |
| | | |
| | | // 获取高德地图区域数据 |
| | | getDistrictData(keyword = "", level = 0) { |
| | | const url = `https://restapi.amap.com/v3/config/district?keywords=${keyword}&subdistrict=1&key=aeec2a4b436322753dd2458fde89506b`; |
| | | return fetch(url) |
| | | .then((response) => response.json()) |
| | | .then((data) => { |
| | | if ( |
| | | data.status === "1" && |
| | | data.districts && |
| | | data.districts.length > 0 |
| | | ) { |
| | | const root = data.districts[0]; |
| | | const list = root.districts || []; |
| | | |
| | | return list.map((node) => ({ |
| | | value: node.name, |
| | | label: node.name, |
| | | leaf: node.level === "district", // 区县级为叶子节点 |
| | | level: node.level, |
| | | })); |
| | | } |
| | | return []; |
| | | }) |
| | | .catch((e) => { |
| | | console.error("加载城市数据失败", e); |
| | | return []; |
| | | }); |
| | | }, |
| | | |
| | | // 级联选择器懒加载 |
| | | async loadCityData(node, resolve) { |
| | | const { level, value } = node; |
| | | |
| | | if (level === 0) { |
| | | // 加载省份 |
| | | const provinces = await this.getDistrictData(); |
| | | resolve(provinces); |
| | | } else { |
| | | // 加载市或区 |
| | | const children = await this.getDistrictData(value); |
| | | resolve(children); |
| | | } |
| | | }, |
| | | |
| | | // 城市选择变化 |
| | | handleCityChange(value) { |
| | | if (value && value.length > 0) { |
| | | // 取最后一级作为城市 |
| | | this.city = value[value.length - 1]; |
| | | } else { |
| | | this.city = null; |
| | | } |
| | | this.handleSearch(); |
| | | }, |
| | | |
| | | // 加载事故分类列表 |
| | | async loadClassifyList() { |
| | | try { |
| | | const res = await getAccidentClassify(); |
| | | if (res && res) { |
| | | this.classifyList = res; |
| | | } |
| | | } catch (error) { |
| | | console.error("加载事故分类列表失败:", error); |
| | | } |
| | | }, |
| | | |
| | | // 加载简讯列表 |
| | | async loadStoryList() { |
| | | try { |
| | | this.loading = true; |
| | | const params = { |
| | | pageNum: this.currentPage, |
| | | pageSize: this.pageSize, |
| | | }; |
| | | |
| | | // 添加筛选条件 |
| | | if (this.city) { |
| | | params.city = this.city; |
| | | } |
| | | if (this.classifyId) { |
| | | params.classifyId = this.classifyId; |
| | | } |
| | | if (this.content) { |
| | | params.content = this.content; |
| | | } |
| | | |
| | | // 时间范围筛选:只有当开始时间和结束时间都选择时才添加 |
| | | // 格式:2022-02-02 - 2023-03-03 |
| | | if (this.dateTime && this.dateTime2) { |
| | | const startTime = moment(this.dateTime).format("YYYY-MM-DD"); |
| | | const endTime = moment(this.dateTime2).format("YYYY-MM-DD"); |
| | | params.time = `${startTime} - ${endTime}`; |
| | | } |
| | | |
| | | const res = await getStoryPage(params); |
| | | if (res && res) { |
| | | this.storyList = res.records || []; |
| | | this.total = res.total || 0; |
| | | } |
| | | } catch (error) { |
| | | console.error("加载简讯列表失败:", error); |
| | | this.$message.error("加载数据失败"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 时间选择变化处理 |
| | | handleDateChange() { |
| | | // 如果两个时间都选择了,进行验证 |
| | | if (this.dateTime && this.dateTime2) { |
| | | const startTime = moment(this.dateTime); |
| | | const endTime = moment(this.dateTime2); |
| | | |
| | | // 验证开始时间必须小于结束时间 |
| | | if (startTime.isAfter(endTime)) { |
| | | this.$message.warning("开始时间不能大于结束时间"); |
| | | return; |
| | | } |
| | | |
| | | // 验证通过,执行搜索 |
| | | this.handleSearch(); |
| | | } else if (!this.dateTime && !this.dateTime2) { |
| | | // 如果两个时间都清空了,也执行搜索 |
| | | this.handleSearch(); |
| | | } |
| | | // 如果只选择了一个时间,不执行搜索,等待用户选择另一个时间 |
| | | }, |
| | | |
| | | // 搜索 |
| | | handleSearch() { |
| | | this.currentPage = 1; |
| | | this.loadStoryList(); |
| | | }, |
| | | |
| | | toDetail(item) { |
| | | this.$router.push({ |
| | | path: "/accidentCase/detail", |
| | |
| | | }, |
| | | |
| | | handleSizeChange(val) { |
| | | console.log(`每页 ${val} 条`); |
| | | this.pageSize = val; |
| | | this.loadStoryList(); |
| | | }, |
| | | |
| | | handleCurrentChange(val) { |
| | | console.log(`当前页: ${val}`); |
| | | this.currentPage = val; |
| | | this.loadStoryList(); |
| | | }, |
| | | |
| | | handleClick(type) { |
| | |
| | | backFun() { |
| | | this.$router.go(-1); |
| | | }, |
| | | |
| | | // 格式化日期显示 |
| | | formatDate(dateStr) { |
| | | if (!dateStr) return ""; |
| | | return moment(dateStr).format("YYYY年MM月DD日"); |
| | | }, |
| | | |
| | | // 格式化日期的日 |
| | | formatDay(dateStr) { |
| | | if (!dateStr) return ""; |
| | | return moment(dateStr).format("DD"); |
| | | }, |
| | | |
| | | // 格式化日期的年月 |
| | | formatYearMonth(dateStr) { |
| | | if (!dateStr) return { year: "", month: "" }; |
| | | return { |
| | | year: moment(dateStr).format("YYYY"), |
| | | month: moment(dateStr).format("MM"), |
| | | }; |
| | | }, |
| | | |
| | | // 图片加载失败处理 |
| | | handleImageError(e) { |
| | | e.target.src = require("../../assets/img/logo.png"); |
| | | }, |
| | | |
| | | // 清除城市选择 |
| | | handleClearCity() { |
| | | this.cascaderValue = []; |
| | | this.city = null; |
| | | this.handleSearch(); |
| | | }, |
| | | |
| | | // 清除事故类型 |
| | | handleClearClassify() { |
| | | this.classifyId = null; |
| | | this.handleSearch(); |
| | | }, |
| | | |
| | | // 清除开始日期 |
| | | handleClearStartDate() { |
| | | this.dateTime = null; |
| | | // 如果结束日期也为空,触发搜索 |
| | | if (!this.dateTime2) { |
| | | this.handleSearch(); |
| | | } |
| | | }, |
| | | |
| | | // 清除结束日期 |
| | | handleClearEndDate() { |
| | | this.dateTime2 = null; |
| | | // 如果开始日期也为空,触发搜索 |
| | | if (!this.dateTime) { |
| | | this.handleSearch(); |
| | | } |
| | | } |
| | | }, |
| | | }; |
| | | </script> |
| | | <style scoped lang="less"> |
| | | .text-ellipsis-3 { |
| | | display: -webkit-box; |
| | | -webkit-box-orient: vertical; |
| | | -webkit-line-clamp: 3; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .tableItem:hover { |
| | | background-color: rgba(17, 40, 255, 0.2) !important; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | .cascader-box { |
| | | ::v-deep .el-cascader { |
| | | width: 100%; |
| | | |
| | | .el-input__inner { |
| | | background: transparent; |
| | | border: none; |
| | | color: #fff; |
| | | padding: 0; |
| | | } |
| | | |
| | | .el-input__suffix { |
| | | display: none; |
| | | } |
| | | |
| | | .el-input__icon { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btnColor { |
| | | color: #00ebfc; |
| | | } |