main
徐景良 2026-02-28 09:46:14 +08:00
commit 433d1efab7
22 changed files with 355 additions and 180 deletions

View File

@ -30,3 +30,10 @@ VITE_GLOB_APP_MANAGEMENT_UNIT = 管理单位:临沂市自然资源和规划局
VITE_GLOB_APP_TECHINICAL_SUPPORT = 技术⽀持:山东慧创信息科技有限公司
VITE_GLOB_APP_VERSIONS = 系统版本V1.0
VITE_GLOB_MQTT_URL = wrj.wisestcity.com
VITE_GLOB_MQTT_PORT = 6010
VITE_GLOB_APP_RTMP_URL = rtmp://123.132.248.154:1935
VITE_GLOB_APP_FLV_URL = http://123.132.248.154:1986
VITE_GLOB_SRS_API_URL = http://123.132.248.154:1985

View File

@ -167,7 +167,8 @@
"vuedraggable": "^4.1.0",
"vuex": "^4.1.0",
"xe-utils": "^3.5.14",
"xlsx": "^0.18.5"
"xlsx": "^0.18.5",
"@turf/helpers": "^7.2.0"
},
"devDependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",

View File

@ -8,6 +8,8 @@ enum Api {
AddPreventionplan = '/api/FmPreventionPlan/AddPreventionplan',
// 删除预案
DeletePreventionplan = '/api/FmPreventionPlan/DeletePreventionplan',
// 根据坐标点获取预案
LoadClueInfoByLngLat = '/api/FmPreventionPlan/LoadClueInfoByLngLat',
}
export function GetPreventionplanPageList(params) {
return defHttp.get({
@ -31,4 +33,10 @@ export function DeletePreventionplan(id) {
return defHttp.post({
url: `${Api.DeletePreventionplan}?id=${id}`,
});
}
export function LoadClueInfoByLngLat(params) {
return defHttp.get({
url: Api.LoadClueInfoByLngLat,
params
});
}

View File

@ -0,0 +1,8 @@
import { defHttp } from '@/utils/http/axios';
enum Api {
LoadTimeSoltByUserId = '/api/FireManagement/LoadTimeSoltByUserId',
AddOrUpdateTimeSolt = '/api/FireManagement/AddOrUpdateTimeSolt',
}
export const LoadTimeSoltByUserId = (params: { id:number }) => defHttp.get({ url: Api.LoadTimeSoltByUserId, params });
export const AddOrUpdateTimeSolt = (params) => defHttp.post({ url: Api.AddOrUpdateTimeSolt, params });

View File

@ -50,19 +50,20 @@
<div class="add-plan-item">
<div class="plan-label">预案名称</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['planName']" placeholder="请输入预案名称" />
<a-input ref="planName" class="add-plan-input" v-model:value="addPlanData['planName']" placeholder="请输入预案名称" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">预案编号</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['planCode']" placeholder="请输入预案编号" />
<a-input ref="planCode" class="add-plan-input" v-model:value="addPlanData['planCode']" placeholder="请输入预案编号" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">预案类别</div>
<div class="plan-content">
<a-select
ref="planCategory"
class="add-plan-select"
popupClassName="add-plan-popup-select"
v-model:value="addPlanData['planCategory']"
@ -75,25 +76,26 @@
<div class="add-plan-item">
<div class="plan-label">管理级别</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['admLevel']" placeholder="请输入管理级别" />
<a-input ref="admLevel" class="add-plan-input" v-model:value="addPlanData['admLevel']" placeholder="请输入管理级别" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">描述</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['description']" placeholder="请输入描述" />
<a-input ref="description" class="add-plan-input" v-model:value="addPlanData['description']" placeholder="请输入描述" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">内容</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['content']" placeholder="请输入内容" />
<a-input ref="content" class="add-plan-input" v-model:value="addPlanData['content']" placeholder="请输入内容" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">状态</div>
<div class="plan-content">
<a-select
ref="status"
class="add-plan-select"
popupClassName="add-plan-popup-select"
v-model:value="addPlanData['status']"
@ -106,13 +108,14 @@
<div class="add-plan-item">
<div class="plan-label">写入单元</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['writeUnit']" placeholder="请输入写入单元" />
<a-input ref="writeUnit" class="add-plan-input" v-model:value="addPlanData['writeUnit']" placeholder="请输入写入单元" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">生效日期</div>
<div class="plan-content">
<a-date-picker
ref="effectiveDate"
v-model:value="addPlanData['effectiveDate']"
class="add-plan-date-picker"
popupClassName="add-plan-date-picker-popup"
@ -125,6 +128,7 @@
<div class="plan-label">到期日期</div>
<div class="plan-content">
<a-date-picker
ref="expiry_date"
v-model:value="addPlanData['expiry_date']"
class="add-plan-date-picker"
popupClassName="add-plan-date-picker-popup"
@ -136,13 +140,13 @@
<div class="add-plan-item">
<div class="plan-label">负责人</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['responsiblePerson']" placeholder="请输入负责人" />
<a-input ref="responsiblePerson" class="add-plan-input" v-model:value="addPlanData['responsiblePerson']" placeholder="请输入负责人" />
</div>
</div>
<div class="add-plan-item">
<div class="plan-label">联系方式</div>
<div class="plan-content">
<a-input class="add-plan-input" v-model:value="addPlanData['contact']" placeholder="联系方式" />
<a-input ref="contact" class="add-plan-input" v-model:value="addPlanData['contact']" placeholder="联系方式" />
</div>
</div>
<div class="add-plan-item">
@ -156,6 +160,9 @@
<a-button class="add-plan-button">上传附件</a-button>
</a-upload>
</div>
<div class="add-plan-item">
<a-button ref="geom" class="add-plan-button" @click="getGeom()"></a-button>
</div>
</div>
<div class="add-plan-footer">
<div class="save-button" @click="save"></div>
@ -178,6 +185,11 @@
import { message } from 'ant-design-vue';
import { uploadFile } from '@/api/demo/files'
import { getAppEnvConfig } from '@/utils/env'
import { point, polygon as trfPolygon } from '@turf/helpers';
import { WktToGeojson, GeojsonToWkt } from '@/views/demo/layer/geometryHandler';
import { contingencyPlanStore } from '@/store/modules/contingencyplan';
const contingencyPlanStoreVal = contingencyPlanStore();
const chartEditStore = useChartEditStore();
let { VITE_GLOB_API_URL } = getAppEnvConfig();
const props = defineProps({
@ -210,21 +222,38 @@
{ label: '负责人', key: 'responsiblePerson' },
{ label: '联系方式', key: 'contact' },
]
const planName = ref(null)
const planCode = ref(null)
const planCategory = ref(null)
const admLevel = ref(null)
const description = ref(null)
const content = ref(null)
const status = ref(null)
const writeUnit = ref(null)
const effectiveDate = ref(null)
const expiry_date = ref(null)
const responsiblePerson = ref(null)
const contact = ref(null)
const geom = ref(null)
const addPlanItemList = [
{ label: '预案名称', key: 'planName' },
{ label: '预案编号', key: 'planCode' },
{ label: '预案类别', key: 'planCategory' },
{ label: '管理级别', key: 'admLevel' },
{ label: '描述', key: 'description' },
{ label: '内容', key: 'content' },
{ label: '状态', key: 'status' },
{ label: '写入单元', key: 'writeUnit' },
{ label: '生效日期', key: 'effectiveDate' },
{ label: '到期日期', key: 'expiry_date' },
{ label: '负责人', key: 'responsiblePerson' },
{ label: '联系方式', key: 'contact' },
{ label: '预案名称', key: 'planName', dom: planName },
{ label: '预案编号', key: 'planCode', dom: planCode },
{ label: '预案类别', key: 'planCategory', dom: planCategory },
{ label: '管理级别', key: 'admLevel', dom: admLevel },
{ label: '描述', key: 'description', dom: description },
{ label: '内容', key: 'content', dom: content },
{ label: '状态', key: 'status', dom: status },
{ label: '写入单元', key: 'writeUnit', dom: writeUnit },
{ label: '生效日期', key: 'effectiveDate', dom: effectiveDate },
{ label: '到期日期', key: 'expiry_date', dom: expiry_date },
{ label: '负责人', key: 'responsiblePerson', dom: responsiblePerson },
{ label: '联系方式', key: 'contact', dom: contact },
{ label: '预案范围', key: 'geom', dom: geom },
]
let geojsonLayer: mars3d.layer.GeoJsonLayer
let drawLayer;
let graphic;
const lastGraphics = ref<any>([])
const { w, h } = toRefs(props.chartConfig.attr);
const {
dataset,
@ -264,14 +293,10 @@
})
});
const showInfo = async (item) => {
if(!geojsonLayer){
geojsonLayer = new mars3d.layer.GeoJsonLayer({
name: 'fire-plan-layer',
clampToGround: true
})
window.globalMap.addLayer(geojsonLayer);
if(!contingencyPlanStoreVal.getLayer()){
contingencyPlanStoreVal.setLayer()
}else{
geojsonLayer.clear()
contingencyPlanStoreVal.clearData()
}
if(item.attachment){
const res = await fetch(`${VITE_GLOB_API_URL}/${item.attachment}`)
@ -280,12 +305,7 @@
return
}
const data = await res.json()
geojsonLayer.load({
data: data
})
geojsonLayer.flyTo({
scale: 1.5
})
contingencyPlanStoreVal.reloadData(data)
}
EventBus.emit('ContingencyPlanListToContingencyPlanInfo',item)
}
@ -299,6 +319,10 @@
}
const closeAddPlan = () => {
addPlanDiv.value = false
lastGraphics.value.forEach(item => {
drawLayer && drawLayer.removeGraphic(item)
})
drawLayer && drawLayer.stopDraw()
}
const query = () => {
let params = {
@ -312,11 +336,33 @@
}
const save = () => {
let isCheck = true
addPlanData.value.geom = addAndUpdateWorkArea()
addPlanItemList.forEach(item => {
if(!(addPlanData.value[item.key])){
isCheck = false
message.warning(`${item.label}为空!`)
return
if(['planCategory', 'status'].includes(item.key)){
const el = item.dom?.value?.$el
const selector = el.querySelector('.ant-select-selector')
selector.style.borderColor = '#ff3939'
}else if(item.key == 'geom'){
const el = item.dom?.value?.$el
el.style.background = '#ff3939'
}else{
const el = item.dom?.value?.$el
el.style.borderColor = '#ff3939'
}
}else{
if(['planCategory', 'status'].includes(item.key)){
const el = item.dom?.value?.$el
const selector = el.querySelector('.ant-select-selector')
selector.style.borderColor = '#00611A'
}else if(item.key == 'geom'){
const el = item.dom?.value?.$el
el.style.background = '#00611A'
}else{
const el = item.dom?.value?.$el
el.style.borderColor = '#00611A'
}
}
})
if(isCheck){
@ -328,6 +374,10 @@
message.success('预案添加成功')
query()
addPlanDiv.value = false
lastGraphics.value.forEach(item => {
drawLayer && drawLayer.removeGraphic(item)
})
drawLayer && drawLayer.stopDraw()
})
}
}
@ -358,6 +408,46 @@
fileList.value = resFileList;
})
}
const getGeom = async () => {
lastGraphics.value.forEach(item => {
drawLayer && drawLayer.removeGraphic(item)
})
if(!drawLayer){
drawLayer = new mars3d.layer.GraphicLayer({
isAutoEditing: true,
});
window.globalMap.addLayer(drawLayer)
}
graphic = await drawLayer.startDraw({
type: 'polygon',
style: {
color: "#00B569",
opacity: 0.2,
outline: true,
outlineColor: "#00B569",
outlineWidth: 2,
},
});
lastGraphics.value.push(graphic)
console.log('draw',graphic)
}
function addAndUpdateWorkArea(addOrUpdate = 'add') {
if(!graphic){
return ''
}
let graphicJson = graphic.toJSON();
let coordinates = graphicJson.position || graphicJson.positions;
let polygonData: any = [];
let geom = '';
coordinates.push(coordinates[0]);
if (addOrUpdate == 'add') {
polygonData.push(coordinates);
} else {
polygonData = coordinates;
}
geom = GeojsonToWkt(trfPolygon(polygonData).geometry);
return geom
}
</script>
<style lang="scss" scoped>

View File

@ -12,6 +12,8 @@
/>
<span class="text">{{ Weather }} °C</span>
</div>
<div class="wind-speed">
<span style="margin-right: 25px;">{{`风速:${windPower}m/s`}}</span>{{`风向: ${winddirection}`}}</div>
</div>
</template>
@ -38,6 +40,8 @@
const currentTime = ref(dayjs().locale('zh-cn').format('YYYY年M月D日 dddd HH:mm:ss'));
const Weather = ref('');
const windPower = ref()
const winddirection = ref()
async function getWeather() {
try {
//
@ -46,6 +50,8 @@
url: `https://restapi.amap.com/v3/weather/weatherInfo?city=371300&key=ae4fb485fa25f5884b9cd7c1101687c4`,
}).then((res) => {
Weather.value = res.data.lives[0].temperature;
windPower.value = res.data.lives[0].windpower;
winddirection.value = res.data.lives[0].winddirection;
if(res.data.lives[0].weather == '阴'){
weatherIcon.value = "wi:cloud"
}else if(res.data.lives[0].weather == '晴'){
@ -116,5 +122,15 @@
font-size: v-bind('textSize+"px"');
}
}
.wind-speed{
position: absolute;
top: 45px;
left: 30px;
width: 400px;
height: 42px;
margin-left: 10px;
color: v-bind('textColor');
font-size: v-bind('textSize+"px"');
}
</style>

View File

@ -113,7 +113,7 @@
}, 5000);
});
// <<<<<<< HEAD
//
// const navsClick = function(item,index){
// navsIndex.value = index
// props.chartConfig.request.requestSQLContent.sql = item.sql

View File

@ -20,6 +20,9 @@
import { option as configOption } from './config';
import { eventHandlerHook } from '@/hooks/eventHandler.hook';
import { EventBus } from '@/utils/eventBus';
import { contingencyPlanStore } from '@/store/modules/contingencyplan';
const contingencyPlanStoreVal = contingencyPlanStore();
const chartEditStore = useChartEditStore();
const props = defineProps({
@ -58,6 +61,7 @@
'click',
val,
);
contingencyPlanStoreVal.clearData()
};
const dblclickBtn = (val) => {
eventHandlerHook(

View File

@ -425,6 +425,10 @@
import {drcDownTopicReize,eventsTopicSubscribeReize,servicesTopicReize,services_replyTopicReize,} from '@/utils/debugging/events';
import {getRedisUser,addOrUpdateRedisUser,getLockedClients,getTsgzProjectId,applyDroneControl} from '@/api/demo/airportMaintenance';
import { airPortStore } from '@/store/modules/airport';
import { LoadClueInfoByLngLat } from '@/api/demo/contingencyplan'
import { contingencyPlanStore } from '@/store/modules/contingencyplan';
const contingencyPlanStoreVal = contingencyPlanStore();
const airPortStoreVal = airPortStore();
@ -1682,6 +1686,24 @@
hikversionShow.value = false;
changeButton("应急响应")
let params = {
lng: clueInfo.value.lng,
lat: clueInfo.value.lat,
}
LoadClueInfoByLngLat(params).then(async res => {
if(res.length > 0){
let resultData = res[0]
if(resultData.Attachment){
const res = await fetch(`${VITE_GLOB_API_URL}/${resultData.Attachment}`)
if (!res.ok) {
console.error('下载失败', res.status)
return
}
const data = await res.json()
contingencyPlanStoreVal.reloadData(data)
}
}
})
}
const changeButton = (type) => {

View File

@ -68,6 +68,11 @@ const goflyaddress=(e)=>{
})
entityArr.value = []
}
if(e.state == '离线'){
return message.warning('当前人员离线')
}else if(e.lng == null || e.lat == null || e.lng == 0 || e.lat == 0){
return message.warning('人员位置异常')
}
handlerAddEntity(e)
}
// Entity

View File

@ -1,4 +1,6 @@
import { defineStore } from 'pinia';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_APP_RTMP_URL, VITE_GLOB_APP_FLV_URL, VITE_GLOB_SRS_API_URL } = getAppEnvConfig();
export const airPortStore = defineStore({
id: 'airport',
@ -17,8 +19,11 @@ export const airPortStore = defineStore({
video_id: null,
},
liveInfo: {
rtmp: 'rtmp://wrj.wisestcity.com:6019/live/',
url: 'https://wrj.wisestcity.com:6012/live/',
rtmp: `${VITE_GLOB_APP_RTMP_URL}/live/`,
url: `${VITE_GLOB_APP_FLV_URL}/live/`,
getUrl: `${VITE_GLOB_SRS_API_URL}/`,
// rtmp: 'rtmp://175.27.168.120:6019/live/',
// url: 'http://175.27.168.120:6012/live/',
// rtmp: 'rtmp://box.wisestcity.com:1935/live/',
// url: 'http://box.wisestcity.com:8081/live/',
// rtmp: 'http://wrj.wisestcity.com:5005/rtc/v1/whip/?app=live&stream=',

View File

@ -0,0 +1,35 @@
import { defineStore } from 'pinia';
import * as mars3d from 'mars3d';
interface ContingencyPlanState {
contingencyPlanLayer: mars3d.layer.GeoJsonLayer | null
}
export const contingencyPlanStore = defineStore({
id: 'contingencyPlan',
state: ():ContingencyPlanState => ({
contingencyPlanLayer: null,
}),
actions: {
setLayer() {
this.contingencyPlanLayer = new mars3d.layer.GeoJsonLayer({
name: 'fire-plan-layer',
clampToGround: true
})
window.globalMap.addLayer(this.contingencyPlanLayer);
},
clearData(){
this.contingencyPlanLayer?.clear()
},
reloadData(data){
this.contingencyPlanLayer?.load({
data: data
})
this.contingencyPlanLayer?.flyTo({
scale: 1.5
})
},
getLayer(){
return this.contingencyPlanLayer
}
}
})

View File

@ -40,6 +40,11 @@ export function getAppEnvConfig() {
VITE_GLOB_APP_TECHINICAL_SUPPORT,
VITE_GLOB_APP_VERSIONS,
VITE_GLOB_API_URL_SITUATION,
VITE_GLOB_MQTT_URL,
VITE_GLOB_MQTT_PORT,
VITE_GLOB_APP_RTMP_URL,
VITE_GLOB_APP_FLV_URL,
VITE_GLOB_SRS_API_URL,
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_GEOSERVER_BASE_URL,
VITE_GLOB_COFFEE_API_URL,
@ -63,6 +68,11 @@ export function getAppEnvConfig() {
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_GEOSERVER_BASE_URL,
VITE_GLOB_COFFEE_API_URL,
VITE_GLOB_MQTT_URL,
VITE_GLOB_MQTT_PORT,
VITE_GLOB_APP_RTMP_URL,
VITE_GLOB_APP_FLV_URL,
VITE_GLOB_SRS_API_URL,
};
}

View File

@ -3,6 +3,8 @@ import { useMessage } from '@/hooks/web/useMessage';
import { getRedisUser, addOrUpdateRedisUser } from '@/api/demo/airportMaintenance';
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_MQTT_URL, VITE_GLOB_MQTT_PORT } = getAppEnvConfig();
const userStore = useUserStore();
const userInfo = userStore.getUserInfo;
@ -12,9 +14,9 @@ const { createMessage } = useMessage();
const seizeClientId = 'mqtt_client_1581F8HGX254V00A0BUY_seize';
const connection = {
protocol: 'ws',
host: 'wrj.wisestcity.com',
host: VITE_GLOB_MQTT_URL,
// server less服务器只有两种协议mqtts: 8883; wss: 8084
port: 6010,
port: VITE_GLOB_MQTT_PORT,
endpoint: '/mqtt',
// for more options, please refer to https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
clean: true,

View File

@ -15,7 +15,7 @@ export const columns: BasicColumn[] = [
{
title: '审核状态',
dataIndex: 'state',
width: 80,
width: 90,
customRender: ({ record }) => {
const status = record.state;
let color = '';
@ -36,10 +36,12 @@ export const columns: BasicColumn[] = [
{
title: '负责人',
dataIndex: 'director',
width: 150,
},
{
title: '负责人电话',
dataIndex: 'phone',
width: 130,
},
];

View File

@ -1,35 +1,17 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicModal v-bind="$attrs" @register="registerModal" title='编辑' @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #areaId="{ model, field }">
<a-tree-select
show-search
style="width: 100%"
v-model:value="model[field]"
:tree-data="treeData"
:field-names="{ label: 'name', value: 'id' }"
placeholder="请选择"
allow-clear
multiple
/>
</template>
<template #time="{ model, field }">
<div>
<div class="flex mt-1" v-for="(item, index) in timeslot" :key="index">
<a-time-picker
placeholder="开始时间"
@change="(time, timeString) => beginTimeChange(time, timeString, index)"
v-model:value="item.beginTime"
v-model:value="timeSlot.beginTime"
/>
~
<a-time-picker
placeholder="结束时间"
@change="(time, timeString) => endTimeChange(time, timeString, index)"
v-model:value="item.endTime"
v-model:value="timeSlot.endTime"
/>
<CloseCircleOutlined style="margin-left: 10px" @click="delTime(index)" />
</div>
<a-button type="primary" style="margin-top: 10px" @click="addTime"></a-button>
</div>
</template>
</BasicForm>
@ -43,16 +25,19 @@
import { CloseCircleOutlined } from '@ant-design/icons-vue';
import { addRole, updateRole, getDeptList } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
import moment from 'moment';
import dayjs from 'dayjs';
import { AddOrUpdateTimeSolt } from '@/api/demo/forestranger'
import { message } from 'ant-design-vue';
const { createMessage } = useMessage();
const treeData: any = ref([]);
const timeslot: any = ref([]);
const timeList: any = ref([]);
const timeSlot: any = ref({
beginTime: '',
endTime: '',
});
const updateData = ref({})
defineOptions({ name: 'DeptModal' });
onMounted(() => {
getTreeList();
});
const emit = defineEmits(['success', 'register']);
@ -66,74 +51,53 @@
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
isUpdate.value = data.isUpdate
updateData.value = data.data
resetFields();
setModalProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
setFieldsValue({
...data.record,
});
setFieldsValue({
...data.data,
});
if(data.data.timeSlotData){
let timeSlotList = data.data.timeSlotData.timeSlot.split('-')
timeSlot.value.beginTime = dayjs(timeSlotList[0], 'HH:mm:ss')
timeSlot.value.endTime = dayjs(timeSlotList[1], 'HH:mm:ss')
}else{
timeSlot.value.beginTime = null
timeSlot.value.endTime = null
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
async function handleSubmit() {
try {
const values = await validate();
let query = values;
//
if (!unref(isUpdate)) {
const data = await addRole(query);
if (data) {
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
console.log('values',values)
console.log('updateData.value',updateData.value)
let query
if(isUpdate.value){
query = {
id: updateData.value.timeSlotData.id,
createId: updateData.value.id,
timeSlot: `${dayjs(timeSlot.value.beginTime).format('HH:mm:ss')}-${dayjs(timeSlot.value.endTime).format('HH:mm:ss')}`
}
}else{
query = {
createId: updateData.value.id,
timeSlot: `${dayjs(timeSlot.value.beginTime).format('HH:mm:ss')}-${dayjs(timeSlot.value.endTime).format('HH:mm:ss')}`
}
}
const data = await AddOrUpdateTimeSolt(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('编辑成功');
} else {
const data = await updateRole(query);
if (data) {
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
return createMessage.error('编辑失败');
}
} finally {
setModalProps({ confirmLoading: false });
}
}
const getTreeList = async () => {
getDeptList().then((res) => {
treeData.value = res;
});
};
const delTime = (index) => {
timeslot.value.splice(index, 1);
timeList.value.splice(index, 1);
};
const addTime = () => {
timeslot.value.push({
beginTime: '',
endTime: '',
});
timeList.value.push({
beginTime: '',
endTime: '',
});
};
const beginTimeChange = (time, timeString, index) => {
timeList.value[index].beginTime = timeString;
};
const endTimeChange = (time, timeString, index) => {
timeList.value[index].endTime = timeString;
};
</script>

View File

@ -41,40 +41,19 @@ export const formSchema: FormSchema[] = [
{
field: 'name',
label: '人员姓名',
required: true,
component: 'Input',
componentProps: {
disabled: true,
},
},
{
field: 'account',
label: '账号/手机号',
required: true,
component: 'Input',
},
{
field: 'sex',
component: 'RadioGroup',
label: '人员性别',
colProps: {
span: 8,
},
componentProps: {
options: [
{
label: '男',
value: 0,
},
{
label: '女',
value: 1,
},
],
disabled: true,
},
},
{
field: 'areaId',
label: '所属机构',
slot: 'areaId',
},
{
field: 'time',
label: '打卡时间',

View File

@ -13,6 +13,7 @@
import { BasicTable, useTable } from '@/components/Table';
import { getRoleListByPage, deleteRole } from '@/api/demo/system';
import { LoadTimeSoltByUserId } from '@/api/demo/forestranger'
import { useMessage } from '@/hooks/web/useMessage';
import { useModal } from '@/components/Modal';
@ -72,15 +73,23 @@
});
}
function handleEdit() {
async function handleEdit() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请勾选一个角色进行编辑');
}
const record = rows[0];
let params = {
id: record.id
}
let result = await LoadTimeSoltByUserId(params)
let data = {
...record,
timeSlotData: result
}
openRoleModal(true, {
record,
isUpdate: true,
data,
isUpdate: result? true: false,
});
}

View File

@ -13,8 +13,8 @@
/>
<div class="form-button">
<a-button type="primary" @click="getTaskList"></a-button>
<a-button type="primary" @click="toStatic"></a-button>
<a-button type="primary" @click="toInspection"></a-button>
<!-- <a-button type="primary" @click="toStatic"></a-button>
<a-button type="primary" @click="toInspection"></a-button> -->
</div>
</div>
<div class="table-data">

View File

@ -11,26 +11,17 @@
<a-divider orientation="left">打卡点信息</a-divider>
<a-descriptions class="margin-top" :column="1" :size="'mini'" border>
<a-descriptions-item>
<template v-slot:label>
<BankOutlined />
打卡点名称
</template>
{{ itemData.pointname }}
<BankOutlined style="margin-right: 20px;"/>
<span style="color: rgba(0,0,0,0.6);">{{ itemData.pointname }}</span>
</a-descriptions-item>
<a-descriptions-item>
<template v-slot:label>
<HistoryOutlined />
创建时间
</template>
{{ itemData.createtime }}
<HistoryOutlined style="margin-right: 20px;"/>
<span style="color: rgba(0,0,0,0.6);">{{ itemData.createtime }}</span>
</a-descriptions-item>
<a-descriptions-item>
<template v-slot:label>
<EnvironmentOutlined />
打卡点位置
</template>
{{ itemData.lng }},{{ itemData.lat }}&nbsp;&nbsp;
<EnvironmentOutlined style="margin-right: 20px;"/>
<span style="color: rgba(0,0,0,0.6);">{{ itemData.lng }},&nbsp;&nbsp;{{ itemData.lat }}</span>
<!-- <el-button type="primary" size="mini" round icon="el-icon-location-outline" @click="lookClockInfo(currentClockInfo)"></el-button> -->
</a-descriptions-item>
</a-descriptions>

View File

@ -74,6 +74,7 @@
import { useMessage } from '@/hooks/web/useMessage';
import { getPatrolPointByTimeSubsection } from '@/api/firegrid/patrol';
import { getDeptList } from '@/api/demo/system';
import { message } from 'ant-design-vue';
const { createMessage } = useMessage();
defineOptions({ name: 'DeptModal' });
@ -92,7 +93,8 @@
//
title: '巡检列表',
//
dataSource: [],
api: getPointUserOnLine,
// dataSource: [],
// BasicColumn[]
columns: InspectionColumns,
rowKey: 'id',
@ -108,6 +110,17 @@
handleSearchInfoFn(info) {
return info;
},
beforeFetch: (params) => {
return {
...params,
...formState
}
},
afterFetch: (data) => {
onlineInfo.online = data.online;
onlineInfo.offline = data.offline;
return data.userinfo
},
actionColumn: {
width: 120,
title: '操作',
@ -117,6 +130,11 @@
},
});
const toPosition = (row) => {
if(row.state == '离线'){
return message.warning('当前人员离线')
}else if(row.lng == null || row.lat == null || row.lng == 0 || row.lat == 0){
return message.warning('人员位置异常')
}
const lnglat = [row.lng, row.lat];
EventBus.emit('inspectionMoldeMap', lnglat);
};
@ -185,18 +203,17 @@
}
const formState: FormState = reactive({
isonline: '全部',
page: 1,
limit: 10,
});
const getLine = () => {
getPointUserOnLine(formState).then((res) => {
res.items.userinfo.forEach((item) => {
item.onLineTime = friendlyDate(item.onLineTime);
});
onlineInfo.online = res.items.online;
onlineInfo.offline = res.items.offline;
setTableData(res.items.userinfo);
});
reload()
// getPointUserOnLine(formState).then((res) => {
// res.items.userinfo.forEach((item) => {
// item.onLineTime = friendlyDate(item.onLineTime);
// });
// onlineInfo.online = res.items.online;
// onlineInfo.offline = res.items.offline;
// setTableData(res.items.userinfo);
// });
};
const friendlyDate = (time) => {
if (time > 60) {
@ -206,7 +223,7 @@
}
};
onMounted(() => {
getLine();
// getLine();
getTree();
});
</script>

View File

@ -37,7 +37,7 @@
</div>
<div class="count-item-title"> 全部巡查总数 </div>
<div class="count-item-value">
{{ allData.xunchazongshu? allData.xunchazongshu.toFixed(4): 0 }} <span class="unit">千米</span>
{{ allData.xunchazongshu? allData.xunchazongshu.toFixed(2): 0 }} <span class="unit">千米</span>
</div>
</div>