防火巡检
parent
74d46d4edd
commit
15697b12e8
|
|
@ -0,0 +1,98 @@
|
||||||
|
import { defHttp } from '@/utils/http/axios';
|
||||||
|
import {
|
||||||
|
AddCheckPointParams,
|
||||||
|
GetCheckPointListParams,
|
||||||
|
DeleteCheckPointParams,
|
||||||
|
GetClockOnListParams,
|
||||||
|
GetStatisticsCountParams,
|
||||||
|
GetStatisticsParams,
|
||||||
|
} from './model/index';
|
||||||
|
|
||||||
|
enum Api {
|
||||||
|
AddCheckPoint = '/api/FireGrid/AddCheckPoint',
|
||||||
|
GetCheckPointList = '/api/FireGrid/GetCheckPointList',
|
||||||
|
DeleteCheckPoint = '/api/FireGrid/DeleteCheckPoint',
|
||||||
|
EditCheckPoint = '/api/FireGrid/EditCheckPoint',
|
||||||
|
GetSingleCheckPoint = '/api/FireGrid/GetSingleCheckPoint',
|
||||||
|
GetCheckInfoByPointId = '/api/FireGrid/GetCheckInfoByPointId',
|
||||||
|
GetCheckInfoByUserId = '/api/FireGrid/GetCheckInfoByUserId',
|
||||||
|
GetClockOnList = '/api/FireGrid/GetClockOnList',
|
||||||
|
GetStatisticsCount = '/api/FireGrid/GetStatisticsCount',
|
||||||
|
GetStatistics = '/api/FireGrid/GetStatistics',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 添加打卡点
|
||||||
|
*/
|
||||||
|
export function addCheckPoint(params: AddCheckPointParams) {
|
||||||
|
return defHttp.post({
|
||||||
|
url: Api.AddCheckPoint,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取打卡点列表
|
||||||
|
*/
|
||||||
|
export function getCheckPointList(params: GetCheckPointListParams) {
|
||||||
|
return defHttp.get({ url: Api.GetCheckPointList, params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 删除打卡点
|
||||||
|
*/
|
||||||
|
export function deleteCheckPoint(params: DeleteCheckPointParams) {
|
||||||
|
return defHttp.post({
|
||||||
|
url: Api.DeleteCheckPoint,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 编辑打卡点
|
||||||
|
*/
|
||||||
|
export function editCheckPoint(params: AddCheckPointParams) {
|
||||||
|
return defHttp.post({
|
||||||
|
url: Api.EditCheckPoint,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取单个打卡点
|
||||||
|
*/
|
||||||
|
export function getSingleCheckPoint(params: DeleteCheckPointParams) {
|
||||||
|
return defHttp.get({ url: Api.GetSingleCheckPoint, params });
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 获取打卡记录
|
||||||
|
*/
|
||||||
|
export function getCheckInfoByPointId(params: GetCheckPointListParams) {
|
||||||
|
return defHttp.get({ url: Api.GetCheckInfoByPointId, params });
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 获取打卡信息
|
||||||
|
*/
|
||||||
|
export function getCheckInfoByUserId(params: GetCheckPointListParams) {
|
||||||
|
return defHttp.get({ url: Api.GetCheckInfoByUserId, params });
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 获取打卡记录列表
|
||||||
|
*/
|
||||||
|
export function getClockOnList(params: GetClockOnListParams) {
|
||||||
|
return defHttp.get({ url: Api.GetClockOnList, params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取数据总览
|
||||||
|
*/
|
||||||
|
export function getStatisticsCount(params: GetStatisticsCountParams) {
|
||||||
|
return defHttp.get({ url: Api.GetStatisticsCount, params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取数据列表
|
||||||
|
*/
|
||||||
|
export function getStatistics(params: GetStatisticsParams) {
|
||||||
|
return defHttp.get({ url: Api.GetStatistics, params });
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @description: Login interface parameters
|
||||||
|
*/
|
||||||
|
export interface AddCheckPointParams {
|
||||||
|
id?: number;
|
||||||
|
lng: string;
|
||||||
|
lat: string;
|
||||||
|
pointName: string;
|
||||||
|
userId: any;
|
||||||
|
areaId: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetCheckPointListParams {
|
||||||
|
pointName?: string;
|
||||||
|
id?: number;
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteCheckPointParams {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetClockOnListParams {
|
||||||
|
userId?: number;
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
beginTime?: string;
|
||||||
|
endTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetStatisticsCountParams {
|
||||||
|
areaid?: number;
|
||||||
|
begintime?: string;
|
||||||
|
endtime?: string;
|
||||||
|
}
|
||||||
|
export interface GetStatisticsParams {
|
||||||
|
areaid?: number;
|
||||||
|
begintime?: string;
|
||||||
|
endtime?: string;
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -1,39 +0,0 @@
|
||||||
import type { AppRouteModule } from '@/router/types';
|
|
||||||
|
|
||||||
import { LAYOUT } from '@/router/constant';
|
|
||||||
import { t } from '@/hooks/web/useI18n';
|
|
||||||
|
|
||||||
const datamaintenance: AppRouteModule = {
|
|
||||||
path: '/datamaintenance',
|
|
||||||
name: 'DataMaintenance',
|
|
||||||
component: LAYOUT,
|
|
||||||
redirect: '/datamaintenance/home',
|
|
||||||
meta: {
|
|
||||||
orderNo: 10,
|
|
||||||
icon: 'ion:grid-outline',
|
|
||||||
title: '数据维护',
|
|
||||||
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/datamaintenance/home',
|
|
||||||
name: 'dataMaintenancehome',
|
|
||||||
meta: {
|
|
||||||
title: '数据中心',
|
|
||||||
hideMenu: true,
|
|
||||||
},
|
|
||||||
component: () => import('@/views/demo/datamaintenance/index.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/datamaintenance/datamanagement',
|
|
||||||
name: 'datamanagement',
|
|
||||||
meta: {
|
|
||||||
title: '数据中心',
|
|
||||||
hideMenu: true,
|
|
||||||
},
|
|
||||||
component: () => import('@/views/demo/datamaintenance/datamanagement/index.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default datamaintenance;
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @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 #userId="{ 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>
|
||||||
|
</BasicForm>
|
||||||
|
</BasicModal>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, unref, reactive, onMounted } from 'vue';
|
||||||
|
import { BasicModal, useModalInner } from '@/components/Modal';
|
||||||
|
import { BasicForm, useForm } from '@/components/Form';
|
||||||
|
import { formSchema } from './data';
|
||||||
|
import { getDeptList } from '@/api/demo/system';
|
||||||
|
import { useMessage } from '@/hooks/web/useMessage';
|
||||||
|
import { addCheckPoint, editCheckPoint, getSingleCheckPoint } from '@/api/firegrid/index';
|
||||||
|
import { EventBus } from '@/utils/eventBus';
|
||||||
|
|
||||||
|
const { createMessage } = useMessage();
|
||||||
|
defineOptions({ name: 'DeptModal' });
|
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'register']);
|
||||||
|
|
||||||
|
const isUpdate = ref(true);
|
||||||
|
const treeData: any = ref([]);
|
||||||
|
onMounted(() => {
|
||||||
|
getTreeList();
|
||||||
|
});
|
||||||
|
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
|
||||||
|
labelWidth: 100,
|
||||||
|
baseColProps: { span: 24 },
|
||||||
|
schemas: formSchema,
|
||||||
|
showActionButtonGroup: false,
|
||||||
|
});
|
||||||
|
const position: any = reactive({});
|
||||||
|
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||||
|
resetFields();
|
||||||
|
setModalProps({ confirmLoading: false });
|
||||||
|
isUpdate.value = !!data?.isUpdate;
|
||||||
|
if (unref(isUpdate)) {
|
||||||
|
getDetail(data.id);
|
||||||
|
setFieldsValue({
|
||||||
|
...data.record,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
position.lat = data.lat;
|
||||||
|
position.lng = data.lng;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const getDetail = async (id) => {
|
||||||
|
getSingleCheckPoint({ id }).then((res) => {
|
||||||
|
setFieldsValue({
|
||||||
|
...res,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getTreeList = async () => {
|
||||||
|
getDeptList().then((res) => {
|
||||||
|
treeData.value = res;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTitle = computed(() => (!unref(isUpdate) ? '新增打卡点' : '编辑打卡点'));
|
||||||
|
async function handleSubmit() {
|
||||||
|
try {
|
||||||
|
const values = await validate();
|
||||||
|
let query: any = values;
|
||||||
|
// 调用接口
|
||||||
|
if (!unref(isUpdate)) {
|
||||||
|
query.lat = position.lat;
|
||||||
|
query.lng = position.lng;
|
||||||
|
const data = await addCheckPoint(query);
|
||||||
|
if (data) {
|
||||||
|
setModalProps({ confirmLoading: true });
|
||||||
|
closeModal();
|
||||||
|
EventBus.emit('addCheckPoint', '');
|
||||||
|
return createMessage.success('新增成功');
|
||||||
|
} else {
|
||||||
|
return createMessage.error('新增失败');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const data = await editCheckPoint(query);
|
||||||
|
if (data) {
|
||||||
|
setModalProps({ confirmLoading: true });
|
||||||
|
closeModal();
|
||||||
|
emit('success');
|
||||||
|
return createMessage.success('编辑成功');
|
||||||
|
} else {
|
||||||
|
return createMessage.error('编辑失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setModalProps({ confirmLoading: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4 flex">
|
||||||
|
<div class="w-1/2 xl:w-1/2">
|
||||||
|
<div class="search-container flex justify-end items-center form-data m-4">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="formState.areaId"
|
||||||
|
style="width: 30%; margin-right: 10px"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:tree-data="treeData"
|
||||||
|
placeholder="选择行政区划"
|
||||||
|
tree-default-expand-all
|
||||||
|
>
|
||||||
|
<template #title="{ key, value }">
|
||||||
|
<span style="color: #08c" v-if="key === '0-0-1'">Child Node1 {{ value }}</span>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
<!-- formState.isonline -->
|
||||||
|
<a-select ref="select" v-model:value="formState.isonline" style="width: 120px">
|
||||||
|
<a-select-option :value="item.value" v-for="item in stateOptions" :key="item.value">{{
|
||||||
|
item.label
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<div class="form-button">
|
||||||
|
<a-button type="primary">查询</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="all-count">
|
||||||
|
<div class="online-user-count">
|
||||||
|
在线人数
|
||||||
|
<span style="font-size: 24px; color: #108eff; margin-left: 12px">{{
|
||||||
|
onlineInfo.online
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="online-user-count">
|
||||||
|
离线人数
|
||||||
|
<span style="font-size: 24px; color: #108eff; margin-left: 12px">{{
|
||||||
|
onlineInfo.offline
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #toolbar>
|
||||||
|
<!-- <a-button type="primary" @click="handleCreate"> 新增角色 </a-button> -->
|
||||||
|
<!-- <a-button type="primary" @click="handleItem"> 获取选中行 </a-button> -->
|
||||||
|
<PermissionBtn @btn-event="onBtnClicked" />
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
// icon: 'ant-design:ellipsis-outlined',
|
||||||
|
label: '位置',
|
||||||
|
onClick: toPosition.bind(null, record),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// icon: 'ant-design:ellipsis-outlined',
|
||||||
|
label: '轨迹',
|
||||||
|
onClick: toTrajectory.bind(null, record),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Map :name="'InspectionModel'" class="w-1/2 xl:w-1/2" />
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="patrolTrackModelVisible"
|
||||||
|
title="巡查"
|
||||||
|
wrap-class-name="full-modal"
|
||||||
|
width="100%"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<PatrolTrackModel />
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||||
|
import { getAccountList } from '@/api/demo/system';
|
||||||
|
import { InspectionColumns } from './data';
|
||||||
|
import { PatrolTrackModel, Map } from './index';
|
||||||
|
|
||||||
|
defineOptions({ name: 'DeptModal' });
|
||||||
|
const patrolTrackModelVisible = ref(false);
|
||||||
|
const onlineInfo = ref({
|
||||||
|
online: 0,
|
||||||
|
offline: 0,
|
||||||
|
});
|
||||||
|
const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
|
||||||
|
// 表格名称
|
||||||
|
title: '角色列表',
|
||||||
|
// 获取数据的接口
|
||||||
|
api: getAccountList,
|
||||||
|
// 表单列信息 BasicColumn[]
|
||||||
|
columns: InspectionColumns,
|
||||||
|
rowKey: 'id',
|
||||||
|
// 使用搜索表单
|
||||||
|
useSearchForm: false,
|
||||||
|
// 显示表格设置工具
|
||||||
|
showTableSetting: true,
|
||||||
|
// 是否显示表格边框
|
||||||
|
bordered: true,
|
||||||
|
// 序号列
|
||||||
|
showIndexColumn: false,
|
||||||
|
// 勾选列
|
||||||
|
rowSelection: {
|
||||||
|
//多选框
|
||||||
|
// type: 'checkbox',
|
||||||
|
type: 'radio',
|
||||||
|
},
|
||||||
|
// 搜索
|
||||||
|
handleSearchInfoFn(info) {
|
||||||
|
return info;
|
||||||
|
},
|
||||||
|
actionColumn: {
|
||||||
|
width: 120,
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
// slots: { customRender: 'action' },
|
||||||
|
fixed: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const toPosition = () => {
|
||||||
|
console.log('位置');
|
||||||
|
};
|
||||||
|
const toTrajectory = () => {
|
||||||
|
console.log('轨迹');
|
||||||
|
};
|
||||||
|
const stateOptions = ref([
|
||||||
|
{
|
||||||
|
label: '全部',
|
||||||
|
value: '全部',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '在线',
|
||||||
|
value: '在线',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '离线',
|
||||||
|
value: '离线',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
// 查询
|
||||||
|
interface FormState {
|
||||||
|
isonline: string;
|
||||||
|
areaId: string;
|
||||||
|
}
|
||||||
|
const formState: FormState = reactive({
|
||||||
|
isonline: '全部',
|
||||||
|
areaId: '',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form-button {
|
||||||
|
button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .ant-modal {
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
.all-count {
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px 20px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
border-bottom: 1px solid @border-color-light;
|
||||||
|
border-top: 1px solid @border-color-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-count div {
|
||||||
|
width: 40%;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-left: 3px solid #409eff;
|
||||||
|
float: left;
|
||||||
|
margin-left: 20px;
|
||||||
|
text-indent: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4 mr-0 overflow-hidden bg-white" style="overflow: auto">
|
||||||
|
<div class="flex justify-around items-center form-data m-4">
|
||||||
|
<a-input v-model:value="formState.keyWord" placeholder="输入关键字" style="width: 30%" />
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="formState.orgId"
|
||||||
|
style="width: 30%"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:tree-data="treeData"
|
||||||
|
placeholder="选择行政区划"
|
||||||
|
tree-default-expand-all
|
||||||
|
>
|
||||||
|
<template #title="{ key, value }">
|
||||||
|
<span style="color: #08c" v-if="key === '0-0-1'">Child Node1 {{ value }}</span>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-data">
|
||||||
|
<div class="clock-item-container">
|
||||||
|
<div class="clock-item" v-for="(item, index) in tasklist" :key="index">
|
||||||
|
<div class="clock-item-icon">
|
||||||
|
<img src="@/assets/images/meshing/clockIn-bg.png" />
|
||||||
|
</div>
|
||||||
|
<div class="clock-item-info">
|
||||||
|
<p>打卡点名称:{{ item.PointName }}</p>
|
||||||
|
<p>创建时间:{{ item.CreateTime }}</p>
|
||||||
|
<p>负责人员:{{ item.CreateUserName }}</p>
|
||||||
|
<p style="text-align: right">
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定删除吗?"
|
||||||
|
ok-text="是"
|
||||||
|
cancel-text="否"
|
||||||
|
@confirm="deleteTask(item.Id)"
|
||||||
|
>
|
||||||
|
<a-button type="primary" danger size="mini">删除</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
<a-button type="primary" round size="mini" @click="editClockInfo(item)"
|
||||||
|
>编辑</a-button
|
||||||
|
>
|
||||||
|
<a-button type="primary" round size="mini" @click="lookClockInfo(item)"
|
||||||
|
>查看</a-button
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-data-pagination m-4">
|
||||||
|
<a-pagination
|
||||||
|
show-size-changer
|
||||||
|
show-quick-jumper
|
||||||
|
v-model:current="pageData.current"
|
||||||
|
:total="pageData.total"
|
||||||
|
@change="paginationOnChange"
|
||||||
|
@showSizeChange="onShowSizeChange"
|
||||||
|
:show-total="(total) => `共 ${total} 条`"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditModal @register="editModal" @success="editSuccess" />
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="statisticsModalVisible"
|
||||||
|
title="统计"
|
||||||
|
wrap-class-name="full-modal"
|
||||||
|
width="100%"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<StatisticsModel />
|
||||||
|
</a-modal>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="InspectionModelVisible"
|
||||||
|
title="巡检"
|
||||||
|
wrap-class-name="full-modal"
|
||||||
|
width="100%"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<InspectionModel />
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, UnwrapRef, ref, onMounted } from 'vue';
|
||||||
|
import { useModal } from '@/components/Modal';
|
||||||
|
import { EditModal, StatisticsModel, InspectionModel } from './index';
|
||||||
|
import { getCheckPointList, deleteCheckPoint } from '@/api/firegrid/index';
|
||||||
|
import { useMessage } from '@/hooks/web/useMessage';
|
||||||
|
import { EventBus } from '@/utils/eventBus';
|
||||||
|
|
||||||
|
const { createMessage } = useMessage();
|
||||||
|
const emits = defineEmits(['viewHandle']);
|
||||||
|
const [editModal, { openModal: openEidtModal }] = useModal();
|
||||||
|
const statisticsModalVisible = ref(false);
|
||||||
|
const InspectionModelVisible = ref(false);
|
||||||
|
onMounted(() => {
|
||||||
|
getTaskList();
|
||||||
|
EventBus.on('addCheckPoint', (data) => {
|
||||||
|
getTaskList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 查询
|
||||||
|
interface FormState {
|
||||||
|
keyWord: string;
|
||||||
|
orgId: string;
|
||||||
|
}
|
||||||
|
interface listObj {
|
||||||
|
Id: number;
|
||||||
|
PointName: string;
|
||||||
|
Lat: string;
|
||||||
|
Lng: string;
|
||||||
|
CreateTime: string;
|
||||||
|
CreateUserName: string;
|
||||||
|
}
|
||||||
|
const formState: UnwrapRef<FormState> = reactive({
|
||||||
|
keyWord: '',
|
||||||
|
orgId: '',
|
||||||
|
});
|
||||||
|
const treeData = ref([]);
|
||||||
|
// 分页
|
||||||
|
const pageData = reactive({
|
||||||
|
total: 100,
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const paginationOnChange = (page: number) => {
|
||||||
|
pageData.current = page;
|
||||||
|
getTaskList();
|
||||||
|
};
|
||||||
|
const onShowSizeChange = (current: number, pageSize: number) => {
|
||||||
|
pageData.current = current;
|
||||||
|
pageData.pageSize = pageSize;
|
||||||
|
getTaskList();
|
||||||
|
};
|
||||||
|
// 列表
|
||||||
|
const tasklist = ref<listObj[]>([]);
|
||||||
|
const getTaskList = () => {
|
||||||
|
const params = {
|
||||||
|
page: pageData.current,
|
||||||
|
limit: pageData.pageSize,
|
||||||
|
pointName: formState.orgId,
|
||||||
|
};
|
||||||
|
getCheckPointList(params).then((res) => {
|
||||||
|
tasklist.value = res.items;
|
||||||
|
pageData.total = res.total;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 删除
|
||||||
|
const deleteTask = (id) => {
|
||||||
|
deleteCheckPoint({ id }).then((res) => {
|
||||||
|
if (res) {
|
||||||
|
getTaskList();
|
||||||
|
return createMessage.success('删除成功');
|
||||||
|
} else {
|
||||||
|
return createMessage.error('删除成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 编辑
|
||||||
|
const editClockInfo = (row) => {
|
||||||
|
openEidtModal(true, {
|
||||||
|
isUpdate: true,
|
||||||
|
id: row.Id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 编辑成功
|
||||||
|
const editSuccess = () => {
|
||||||
|
getTaskList();
|
||||||
|
};
|
||||||
|
// 统计
|
||||||
|
const toStatic = () => {
|
||||||
|
statisticsModalVisible.value = true;
|
||||||
|
};
|
||||||
|
// 查看
|
||||||
|
const lookClockInfo = (row) => {
|
||||||
|
console.log(row);
|
||||||
|
emits('viewHandle', row);
|
||||||
|
};
|
||||||
|
// 巡检
|
||||||
|
const toInspection = () => {
|
||||||
|
InspectionModelVisible.value = true;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form-button {
|
||||||
|
button {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clock-item-container {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
height: calc(100% - 40px);
|
||||||
|
padding: 0px 15px;
|
||||||
|
margin: 15px 0px;
|
||||||
|
overflow: auto;
|
||||||
|
border-top: 1px solid @border-color-light;
|
||||||
|
|
||||||
|
.clock-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-bottom: 1px solid @border-color-light;
|
||||||
|
}
|
||||||
|
.clock-item-icon {
|
||||||
|
width: 100px;
|
||||||
|
height: 80px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.clock-item-icon img {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.clock-item-info {
|
||||||
|
float: left;
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
height: 100px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-size: 12px;
|
||||||
|
button {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clock-item-info p {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.table-data {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100% - 68px);
|
||||||
|
.table-data-pagination {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
background-color: @component-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less">
|
||||||
|
.full-modal {
|
||||||
|
.ant-modal {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-content {
|
||||||
|
height: calc(80vh);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-body {
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="item-container">
|
||||||
|
<div style="padding: 0px 0px 0px 0px">
|
||||||
|
<a-button size="mini" type="primary" round @click="emits('delView')">返回</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="item-container-left">
|
||||||
|
<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>
|
||||||
|
{{ currentClockInfo.pointname }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
|
||||||
|
<a-descriptions-item>
|
||||||
|
<template v-slot:label>
|
||||||
|
<HistoryOutlined />
|
||||||
|
创建时间
|
||||||
|
</template>
|
||||||
|
{{ currentClockInfo.createtime }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item>
|
||||||
|
<template v-slot:label>
|
||||||
|
<EnvironmentOutlined />
|
||||||
|
打卡点位置
|
||||||
|
</template>
|
||||||
|
{{ currentClockInfo.lng }},{{ currentClockInfo.lat }}
|
||||||
|
<!-- <el-button type="primary" size="mini" round icon="el-icon-location-outline" @click="lookClockInfo(currentClockInfo)">定位</el-button> -->
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</div>
|
||||||
|
<div class="item-container-right">
|
||||||
|
<div class="time-box" v-if="tabActive == 1">
|
||||||
|
<a-range-picker
|
||||||
|
:show-time="{ format: 'HH:mm' }"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
:placeholder="['开始时间', '结束时间']"
|
||||||
|
@change="timeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider content-position="left">
|
||||||
|
<span
|
||||||
|
:style="{ color: tabActive == 1 ? '#409eff' : '', cursor: 'pointer' }"
|
||||||
|
@click="tabActive = 1"
|
||||||
|
>巡查轨迹</span
|
||||||
|
>
|
||||||
|
|
||||||
|
<span
|
||||||
|
:style="{ color: tabActive == 2 ? '#409eff' : '', cursor: 'pointer' }"
|
||||||
|
@click="tabActive = 2"
|
||||||
|
>打卡记录</span
|
||||||
|
>
|
||||||
|
</el-divider>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style="width: 100%; text-align: center; padding: 100px 0px"
|
||||||
|
v-if="currentRouters.length <= 0 && tabActive == 1"
|
||||||
|
>
|
||||||
|
<!-- <img src="/img/no-data.png" style="width: 140px; margin-bottom: 20px" /> -->
|
||||||
|
<p style="color: #cfcfcf">暂无巡查轨迹</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="users-container" v-show="tabActive == 1">
|
||||||
|
<div class="history-line" v-for="(it, idx) in currentRouters" :key="idx">
|
||||||
|
<div class="user-item">
|
||||||
|
<div class="user-photo">
|
||||||
|
<img src="@/assets/images/meshing/rangers-number.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="user-name">{{ it.name }}</div>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
round
|
||||||
|
@click="getTrajectoryData(it)"
|
||||||
|
style="float: right; position: relative; top: 8px"
|
||||||
|
>轨迹</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
round
|
||||||
|
@click="getRange(it.phone)"
|
||||||
|
style="float: right; position: relative; top: 8px; left: -12px"
|
||||||
|
>范围</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{ it.startTime }}
|
||||||
|
<SwapRightOutlined style="font-size: 20px" />
|
||||||
|
|
||||||
|
{{ it.endTime }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="users-container" v-show="tabActive == 2">
|
||||||
|
<div class="clockIn-box" v-for="(item, idx) in clockInList" :key="idx">
|
||||||
|
<p>
|
||||||
|
<span><UserOutlined /> 打卡人员:</span>{{ item.Name }}
|
||||||
|
<span
|
||||||
|
> <HistoryOutlined />打卡时间:</span
|
||||||
|
>
|
||||||
|
{{ item.clockontime }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span><EnvironmentOutlined /> 打卡位置:</span>
|
||||||
|
{{ parseFloat(item.lng).toFixed(6) }},{{ parseFloat(item.lat).toFixed(6) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import {
|
||||||
|
SwapRightOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
HistoryOutlined,
|
||||||
|
EnvironmentOutlined,
|
||||||
|
BankOutlined,
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const emits = defineEmits(['delView']);
|
||||||
|
const currentClockInfo = ref({
|
||||||
|
pointname: '测试点',
|
||||||
|
createtime: '2022-11-10 10:00:00',
|
||||||
|
lng: '116.397128',
|
||||||
|
lat: '39.916527',
|
||||||
|
});
|
||||||
|
const tabActive = ref(1);
|
||||||
|
const currentRouters = ref([
|
||||||
|
{
|
||||||
|
name: '打卡记录',
|
||||||
|
phone: '13800138000',
|
||||||
|
startTime: '2022-11-10 10:00:00',
|
||||||
|
endTime: '2022-11-10 10:00:00',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const clockInList = ref([
|
||||||
|
{
|
||||||
|
Name: '测试点',
|
||||||
|
clockontime: '2022-11-10 10:00:00',
|
||||||
|
lng: '116.397128',
|
||||||
|
lat: '39.916527',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
// 查询
|
||||||
|
interface FormState {
|
||||||
|
begintime: string;
|
||||||
|
endtime: string;
|
||||||
|
}
|
||||||
|
const formState: FormState = reactive({
|
||||||
|
begintime: '',
|
||||||
|
endtime: '',
|
||||||
|
});
|
||||||
|
const timeChange = (value: any, dateString: string) => {
|
||||||
|
formState.begintime = dateString[0];
|
||||||
|
formState.endtime = dateString[1];
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.item-container {
|
||||||
|
width: inherit;
|
||||||
|
height: 100%;
|
||||||
|
float: left;
|
||||||
|
padding: 30px;
|
||||||
|
border-right: 1px solid #636262;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
background-color: @component-background;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-container-left {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-container-right {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.users-container {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 15px;
|
||||||
|
height: calc(100vh - 440px);
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
.clockIn-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 80px;
|
||||||
|
/* background:rgba(0,0,0,0.25); */
|
||||||
|
border-bottom: 1px solid #76838f;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 0px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.item-container-right div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.user-item {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
.history-line {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-indent: 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.history-line-button:hover {
|
||||||
|
color: #108eff;
|
||||||
|
}
|
||||||
|
.history-line-button {
|
||||||
|
}
|
||||||
|
.user-item::after {
|
||||||
|
content: '';
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-photo {
|
||||||
|
float: left;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
margin-top: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
line-height: 36px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.user-photo img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.user-name {
|
||||||
|
width: 70px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
width: 100px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.time-box {
|
||||||
|
padding: 0px 20px;
|
||||||
|
margin: 0px 0px 15px 0px;
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
background-color: @component-background;
|
||||||
|
z-index: 100000;
|
||||||
|
}
|
||||||
|
::v-deep .ant-descriptions-item-label {
|
||||||
|
margin-right: 20px;
|
||||||
|
.anticon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,444 @@
|
||||||
|
<template>
|
||||||
|
<div ref="vChartRef" :id="'mars3d-container-' + name"></div>
|
||||||
|
<EditModal @register="editModal" @success="editSuccess" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { isArray } from '@/utils';
|
||||||
|
import * as mars3d from 'mars3d';
|
||||||
|
import { EditModal } from './index';
|
||||||
|
import { useModal } from '@/components/Modal';
|
||||||
|
|
||||||
|
const [editModal, { openModal: openEidtModal }] = useModal();
|
||||||
|
|
||||||
|
let map: mars3d.Map; // 地图对象
|
||||||
|
|
||||||
|
let mapIns: any = null;
|
||||||
|
let markers: any = [];
|
||||||
|
let AMapIns: any = null;
|
||||||
|
|
||||||
|
const vChartRef = ref<HTMLElement>();
|
||||||
|
const props = defineProps({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
let options = {
|
||||||
|
scene: {
|
||||||
|
center: {
|
||||||
|
lat: 35.362625,
|
||||||
|
lng: 118.033886,
|
||||||
|
alt: 8306.3,
|
||||||
|
heading: 360,
|
||||||
|
pitch: -45,
|
||||||
|
},
|
||||||
|
scene3DOnly: false,
|
||||||
|
shadows: false,
|
||||||
|
removeDblClick: true,
|
||||||
|
sceneMode: 3,
|
||||||
|
showSun: true,
|
||||||
|
showMoon: true,
|
||||||
|
showSkyBox: true,
|
||||||
|
showSkyAtmosphere: true,
|
||||||
|
fog: true,
|
||||||
|
fxaa: true,
|
||||||
|
requestRenderMode: true,
|
||||||
|
contextOptions: {
|
||||||
|
requestWebgl1: false,
|
||||||
|
webgl: {
|
||||||
|
preserveDrawingBuffer: true,
|
||||||
|
alpha: false,
|
||||||
|
stencil: true,
|
||||||
|
powerPreference: 'high-performance',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globe: {
|
||||||
|
depthTestAgainstTerrain: false,
|
||||||
|
baseColor: '#546a53',
|
||||||
|
showGroundAtmosphere: true,
|
||||||
|
enableLighting: false,
|
||||||
|
},
|
||||||
|
cameraController: {
|
||||||
|
zoomFactor: 3,
|
||||||
|
minimumZoomDistance: 1,
|
||||||
|
maximumZoomDistance: 50000000,
|
||||||
|
enableRotate: true,
|
||||||
|
enableTranslate: true,
|
||||||
|
enableTilt: true,
|
||||||
|
enableZoom: true,
|
||||||
|
enableCollisionDetection: true,
|
||||||
|
minimumCollisionTerrainHeight: 15000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
control: {
|
||||||
|
homeButton: false,
|
||||||
|
baseLayerPicker: false,
|
||||||
|
sceneModePicker: false,
|
||||||
|
vrButton: false,
|
||||||
|
fullscreenButton: false,
|
||||||
|
navigationHelpButton: false,
|
||||||
|
animation: false,
|
||||||
|
timeline: false,
|
||||||
|
infoBox: false,
|
||||||
|
geocoder: false,
|
||||||
|
selectionIndicator: false,
|
||||||
|
showRenderLoopErrors: true,
|
||||||
|
contextmenu: {
|
||||||
|
hasDefault: true,
|
||||||
|
},
|
||||||
|
mouseDownView: true,
|
||||||
|
zoom: {
|
||||||
|
insertIndex: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
method: {
|
||||||
|
templateValues: {
|
||||||
|
dataServer: '//data.mars3d.cn',
|
||||||
|
gltfServerUrl: '//data.mars3d.cn/gltf',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terrain: {
|
||||||
|
url: '//data.mars3d.cn/terrain',
|
||||||
|
show: true,
|
||||||
|
clip: true,
|
||||||
|
},
|
||||||
|
basemaps: [
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: '地图底图',
|
||||||
|
type: 'group',
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2021,
|
||||||
|
pid: 10,
|
||||||
|
name: '天地图影像',
|
||||||
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
||||||
|
type: 'group',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
name: '底图',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_d',
|
||||||
|
eventParent: {
|
||||||
|
id: 2021,
|
||||||
|
pid: 10,
|
||||||
|
name: '天地图影像',
|
||||||
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
||||||
|
type: 'group',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
name: '底图',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_d',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '注记',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_z',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
private: false,
|
||||||
|
id: 'm-a57ecb7d-ba05-47a3-b1be-2e28411a5954',
|
||||||
|
opacity: 1,
|
||||||
|
pid: 2021,
|
||||||
|
parent: {
|
||||||
|
id: 2021,
|
||||||
|
pid: 10,
|
||||||
|
name: '天地图影像',
|
||||||
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
||||||
|
type: 'group',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
name: '底图',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_d',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '注记',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_z',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '注记',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_z',
|
||||||
|
eventParent: {
|
||||||
|
id: 2021,
|
||||||
|
pid: 10,
|
||||||
|
name: '天地图影像',
|
||||||
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
||||||
|
type: 'group',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
name: '底图',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_d',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '注记',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_z',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
private: false,
|
||||||
|
id: 'm-671f9d42-dda7-45ec-9d0f-4259c915b2cb',
|
||||||
|
opacity: 1,
|
||||||
|
pid: 2021,
|
||||||
|
parent: {
|
||||||
|
id: 2021,
|
||||||
|
pid: 10,
|
||||||
|
name: '天地图影像',
|
||||||
|
icon: 'https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png',
|
||||||
|
type: 'group',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
name: '底图',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_d',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '注记',
|
||||||
|
type: 'tdt',
|
||||||
|
layer: 'img_z',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
zIndex: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
show: true,
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
layers: [],
|
||||||
|
};
|
||||||
|
initMap(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
const isFirstLoad = ref(true);
|
||||||
|
const initMap = (newData: any) => {
|
||||||
|
// 第一次加载
|
||||||
|
if (isFirstLoad.value) {
|
||||||
|
map = new mars3d.Map(vChartRef.value, newData);
|
||||||
|
} else {
|
||||||
|
// 之后更新
|
||||||
|
// map.setOptions(newData);
|
||||||
|
map.setSceneOptions(newData.scene);
|
||||||
|
}
|
||||||
|
isFirstLoad.value = false;
|
||||||
|
// 初始化矢量图层
|
||||||
|
handlerInitEntityLayer();
|
||||||
|
const mapContextmenuItems = [
|
||||||
|
{
|
||||||
|
text: '在此处添加打卡点',
|
||||||
|
icon: `<svg class="iconsvg" aria-hidden="true">
|
||||||
|
<use xlink:href="#marsgis-qjsjdb"></use>
|
||||||
|
</svg>`, // 支持iconfont的symbol方式图标(svg)
|
||||||
|
callback: (e) => {
|
||||||
|
const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
|
||||||
|
openEidtModal(true, {
|
||||||
|
isUpdate: false,
|
||||||
|
lat: mpt.lat,
|
||||||
|
lng: mpt.lng,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
map.bindContextMenu(mapContextmenuItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataHandle = (newData: any) => {
|
||||||
|
if (!mapIns && !AMapIns) {
|
||||||
|
// initMap(props.chartConfig.option)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isArray(newData.markers)) {
|
||||||
|
// 先清除旧标记
|
||||||
|
mapIns.remove(markers);
|
||||||
|
markers = [];
|
||||||
|
// 记录新标记
|
||||||
|
if (mapMarkerType.value === 'Marker') {
|
||||||
|
newData.markers.forEach((markerItem: any) => {
|
||||||
|
const markerInstance = new AMapIns.Marker({
|
||||||
|
position: [markerItem.position[0], markerItem.position[1]],
|
||||||
|
offset: new AMapIns.Pixel(-13, -30),
|
||||||
|
});
|
||||||
|
markers.push(markerInstance);
|
||||||
|
markerInstance.setMap(mapIns);
|
||||||
|
});
|
||||||
|
} else if (mapMarkerType.value === 'CircleMarker') {
|
||||||
|
newData.markers.forEach((markerItem: any) => {
|
||||||
|
const markerInstance = new AMapIns.CircleMarker({
|
||||||
|
center: [markerItem.position[0], markerItem.position[1]],
|
||||||
|
radius: markerItem.value,
|
||||||
|
...marker.value,
|
||||||
|
});
|
||||||
|
markers.push(markerInstance);
|
||||||
|
markerInstance.setMap(mapIns);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let graphicLayer = null;
|
||||||
|
// 地球创建完成后默认加载矢量数据图层
|
||||||
|
const handlerInitEntityLayer = () => {
|
||||||
|
if (graphicLayer == null) {
|
||||||
|
graphicLayer = new mars3d.layer.GraphicLayer({ id: 999 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击获取点击位置点位信息 用于常见的下发火点、下发任务点等使用
|
||||||
|
|
||||||
|
const handlerDrawPoint = async () => {
|
||||||
|
const graphic = await graphicLayer.startDraw({
|
||||||
|
type: 'point',
|
||||||
|
});
|
||||||
|
|
||||||
|
let position = graphic.toJSON().position;
|
||||||
|
|
||||||
|
let res = {
|
||||||
|
lng: position[0],
|
||||||
|
lat: position[1],
|
||||||
|
alt: position[0],
|
||||||
|
};
|
||||||
|
|
||||||
|
graphicLayer.removeGraphic(graphic);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加Entity
|
||||||
|
const handlerAddEntity = (data) => {
|
||||||
|
let graphicOptions = {
|
||||||
|
id: data.id,
|
||||||
|
position: [parseFloat(data.position.lng), parseFloat(data.position.lat)],
|
||||||
|
style: {
|
||||||
|
image: data.image.generalIcon,
|
||||||
|
clampToGround: true,
|
||||||
|
scale: 0.5,
|
||||||
|
label: {
|
||||||
|
text: data.attribute.label,
|
||||||
|
font_size: 14,
|
||||||
|
color: '#ffffff',
|
||||||
|
pixelOffsetY: 10,
|
||||||
|
distanceDisplayCondition: true,
|
||||||
|
distanceDisplayCondition_far: 500000,
|
||||||
|
distanceDisplayCondition_near: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
popup: `<div class="marsTiltPanel marsTiltPanel-theme-red" style="font-size:12px;">
|
||||||
|
<div class="marsTiltPanel-wrap">
|
||||||
|
<div class="area">
|
||||||
|
<div class="arrow-lt"></div>
|
||||||
|
<div class="b-t"></div>
|
||||||
|
<div class="b-r"></div>
|
||||||
|
<div class="b-b"></div>
|
||||||
|
<div class="b-l"></div>
|
||||||
|
<div class="arrow-rb"></div>
|
||||||
|
<div class="label-wrap">
|
||||||
|
<div class="title">火点信息</div>
|
||||||
|
<div class="label-content">
|
||||||
|
<div class="data-li">
|
||||||
|
<div class="data-label">火点地址:${data.attribute.address}</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-li">
|
||||||
|
<div class="data-label">上报时间:</div>
|
||||||
|
<div class="data-value"><span id="lablYeWei" class="label-num">2025-2-11 12:00:00</span><span class="label-unit"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-li">
|
||||||
|
<div class="data-value">
|
||||||
|
<span id="lablCSFM3" onclick="aroundYuAn([${data.position.lng},${data.position.lat}])" class="label-tag data-value-status-2" >防灭火资源</span>
|
||||||
|
<span id="lablCSFM2" onclick="delFirePoint(${data.id})" class="label-tag data-value-status-3" title="删除火点">删除火点</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="b-t-l"></div>
|
||||||
|
<div class="b-b-r"></div>
|
||||||
|
</div>
|
||||||
|
<div class="arrow" ></div>
|
||||||
|
</div>`,
|
||||||
|
popupOptions: {
|
||||||
|
offsetY: -30,
|
||||||
|
template: '{content}',
|
||||||
|
horizontalOrigin: 'Cesium.HorizontalOrigin.LEFT',
|
||||||
|
verticalOrigin: 'Cesium.VerticalOrigin.CENTER',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let graphic = graphicLayer.getGraphicById(data.id);
|
||||||
|
|
||||||
|
if (graphic) {
|
||||||
|
graphic.setStyleOptions(graphicOptions);
|
||||||
|
} else {
|
||||||
|
graphic = new mars3d.graphic.BillboardEntity(graphicOptions);
|
||||||
|
graphicLayer.addGraphic(graphic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerHiddenEntity = (data) => {
|
||||||
|
let graphic = graphicLayer.getGraphicById(data.id);
|
||||||
|
if (graphic) {
|
||||||
|
graphic.show = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerRemoveEntity = (data) => {
|
||||||
|
let graphic = graphicLayer.getGraphicById(data.id);
|
||||||
|
if (graphic) {
|
||||||
|
graphicLayer.removeGraphic(graphic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerFlyToEntity = (data) => {
|
||||||
|
let graphic = graphicLayer.getGraphicById(data.id);
|
||||||
|
|
||||||
|
if (graphic) {
|
||||||
|
if (data.image.activeIcon) {
|
||||||
|
grasphic.setStyle({
|
||||||
|
image: data.image.activeIcon,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.globalMap.flyToGraphic(graphic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空所有适量图标
|
||||||
|
const handlerClearEntityLayer = () => {
|
||||||
|
graphicLayer.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 隐藏所有矢量图标
|
||||||
|
const handlerHiddenEntityLayer = () => {
|
||||||
|
graphicLayer.show = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// yi
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped></style>
|
||||||
|
|
@ -0,0 +1,187 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4 flex">
|
||||||
|
<div class="w-1/2 xl:w-1/2">
|
||||||
|
<div class="search-container flex justify-end items-center form-data m-4">
|
||||||
|
<a-range-picker
|
||||||
|
:show-time="{ format: 'HH:mm' }"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
:placeholder="['开始时间', '结束时间']"
|
||||||
|
@change="timeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<a-tabs v-model:activeKey="activeKey">
|
||||||
|
<a-tab-pane key="1" tab="巡查轨迹">
|
||||||
|
<div class="users-container">
|
||||||
|
<div class="history-line" v-for="(it, idx) in list" :key="idx">
|
||||||
|
<div class="user-item">
|
||||||
|
<div class="user-photo">
|
||||||
|
<img src="@/assets/images/meshing/rangers-number.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="user-name">{{ it.name }}</div>
|
||||||
|
<div class="user-phone">{{ it.phone }}</div>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
round
|
||||||
|
@click="getTrajectoryData(it)"
|
||||||
|
style="float: right"
|
||||||
|
>轨迹</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{ it.startAddress }}
|
||||||
|
<span style="font-size: 12px">({{ it.startTime }})</span>
|
||||||
|
<SwapRightOutlined style="font-size: 20px" />
|
||||||
|
{{ it.endAddress }}
|
||||||
|
<span style="font-size: 12px">({{ it.endTime }})</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" tab="打卡记录" force-render>
|
||||||
|
<div class="users-container">
|
||||||
|
<div class="clockIn-box" v-for="(item, idx) in clockInList" :key="idx">
|
||||||
|
<p>
|
||||||
|
<span><UserOutlined /> 打卡人员:</span>{{ item.Name }}
|
||||||
|
<span
|
||||||
|
> <HistoryOutlined />打卡时间:</span
|
||||||
|
>
|
||||||
|
{{ item.clockontime }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span><EnvironmentOutlined /> 打卡位置:</span>
|
||||||
|
{{ parseFloat(item.lng).toFixed(6) }},{{ parseFloat(item.lat).toFixed(6) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
<Map :name="'patrolTrackModel'" class="w-1/2 xl:w-1/2" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { Map } from './index';
|
||||||
|
import {
|
||||||
|
SwapRightOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
HistoryOutlined,
|
||||||
|
EnvironmentOutlined,
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'DeptModal' });
|
||||||
|
const activeKey = ref('1');
|
||||||
|
const list = ref([
|
||||||
|
{
|
||||||
|
name: '张三',
|
||||||
|
phone: '',
|
||||||
|
startAddress: '',
|
||||||
|
endAddress: '',
|
||||||
|
startTime: '2022-01-01 10:00:00',
|
||||||
|
endTime: '2022-01-01 12:00:00',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '张三',
|
||||||
|
phone: '',
|
||||||
|
startAddress: '',
|
||||||
|
endAddress: '',
|
||||||
|
startTime: '2022-01-01 10:00:00',
|
||||||
|
endTime: '2022-01-01 12:00:00',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const clockInList = ref([
|
||||||
|
{
|
||||||
|
Name: '张三',
|
||||||
|
clockontime: '2022-01-01 10:00:00',
|
||||||
|
lng: '116.404',
|
||||||
|
lat: '39.915',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: '张三',
|
||||||
|
clockontime: '2022-01-01 10:00:00',
|
||||||
|
lng: '116.404',
|
||||||
|
lat: '39.915',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const getTrajectoryData = (item) => {
|
||||||
|
console.log(item);
|
||||||
|
};
|
||||||
|
// 查询
|
||||||
|
interface FormState {
|
||||||
|
begintime: string;
|
||||||
|
endtime: string;
|
||||||
|
}
|
||||||
|
const formState: FormState = reactive({
|
||||||
|
begintime: '',
|
||||||
|
endtime: '',
|
||||||
|
});
|
||||||
|
const timeChange = (value: any, dateString: string) => {
|
||||||
|
formState.begintime = dateString[0];
|
||||||
|
formState.endtime = dateString[1];
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.users-container {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 15px;
|
||||||
|
height: calc(100vh - 280px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.item-container-right div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.user-item {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
.history-line {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-indent: 0px;
|
||||||
|
border-bottom: 1px solid @border-color-light;
|
||||||
|
cursor: pointer;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.user-item::after {
|
||||||
|
content: '';
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-photo {
|
||||||
|
float: left;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
margin-top: 6px;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
border-radius: 50%;
|
||||||
|
line-height: 36px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.user-photo img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.user-name {
|
||||||
|
width: 120px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
width: 100px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-operation {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.clockIn-box {
|
||||||
|
border-bottom: 1px solid @border-color-light;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,224 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4">
|
||||||
|
<div class="search-container flex justify-end items-center form-data m-4">
|
||||||
|
<a-tree-select
|
||||||
|
v-model:value="formState.areaId"
|
||||||
|
style="width: 30%; margin-right: 10px"
|
||||||
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:tree-data="treeData"
|
||||||
|
placeholder="选择行政区划"
|
||||||
|
tree-default-expand-all
|
||||||
|
>
|
||||||
|
<template #title="{ key, value }">
|
||||||
|
<span style="color: #08c" v-if="key === '0-0-1'">Child Node1 {{ value }}</span>
|
||||||
|
</template>
|
||||||
|
</a-tree-select>
|
||||||
|
<a-range-picker
|
||||||
|
:show-time="{ format: 'HH:mm' }"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
:placeholder="['开始时间', '结束时间']"
|
||||||
|
@change="timeChange"
|
||||||
|
/>
|
||||||
|
<div class="form-button">
|
||||||
|
<a-button type="primary">查询</a-button>
|
||||||
|
<a-button type="primary">导出</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cate-title">数据总览</div>
|
||||||
|
<div class="count-item-container">
|
||||||
|
<div class="count-item">
|
||||||
|
<div class="count-item-icon">
|
||||||
|
<img src="@/assets/images/meshing/rangers-number.png" />
|
||||||
|
</div>
|
||||||
|
<div class="count-item-title"> 护林员数量 </div>
|
||||||
|
<div class="count-item-value"> {{ allData.hulinyuan }} <span class="unit">人</span> </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="count-item">
|
||||||
|
<div class="count-item-icon">
|
||||||
|
<img src="@/assets/images/meshing/punch-track.png" />
|
||||||
|
</div>
|
||||||
|
<div class="count-item-title"> 全部巡查总数 </div>
|
||||||
|
<div class="count-item-value">
|
||||||
|
{{ allData.xunchazongshu }} <span class="unit">次</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="count-item">
|
||||||
|
<div class="count-item-icon">
|
||||||
|
<img src="@/assets/images/meshing/punch-times.png" />
|
||||||
|
</div>
|
||||||
|
<div class="count-item-title"> 全部打卡总数 </div>
|
||||||
|
<div class="count-item-value"> {{ allData.dakacishu }} <span class="unit">次</span> </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="count-item">
|
||||||
|
<div class="count-item-icon">
|
||||||
|
<img src="@/assets/images/meshing/significant-frequency.png" />
|
||||||
|
</div>
|
||||||
|
<div class="count-item-title"> 全部打卡点数 </div>
|
||||||
|
<div class="count-item-value"> {{ allData.dakadian }} <span class="unit">个</span> </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #toolbar>
|
||||||
|
<!-- <a-button type="primary" @click="handleCreate"> 新增角色 </a-button> -->
|
||||||
|
<!-- <a-button type="primary" @click="handleItem"> 获取选中行 </a-button> -->
|
||||||
|
<PermissionBtn @btn-event="onBtnClicked" />
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
// icon: 'ant-design:ellipsis-outlined',
|
||||||
|
label: '巡查轨迹',
|
||||||
|
onClick: getGuiji.bind(null, record),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="patrolTrackModelVisible"
|
||||||
|
title="巡查"
|
||||||
|
wrap-class-name="full-modal"
|
||||||
|
width="100%"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<PatrolTrackModel />
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||||
|
import { getAccountList } from '@/api/demo/system';
|
||||||
|
import { columns } from './data';
|
||||||
|
import { PatrolTrackModel } from './index';
|
||||||
|
|
||||||
|
defineOptions({ name: 'DeptModal' });
|
||||||
|
const patrolTrackModelVisible = ref(false);
|
||||||
|
const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
|
||||||
|
// 表格名称
|
||||||
|
title: '角色列表',
|
||||||
|
// 获取数据的接口
|
||||||
|
api: getAccountList,
|
||||||
|
// 表单列信息 BasicColumn[]
|
||||||
|
columns,
|
||||||
|
rowKey: 'id',
|
||||||
|
// 使用搜索表单
|
||||||
|
useSearchForm: false,
|
||||||
|
// 显示表格设置工具
|
||||||
|
showTableSetting: true,
|
||||||
|
// 是否显示表格边框
|
||||||
|
bordered: true,
|
||||||
|
// 序号列
|
||||||
|
showIndexColumn: false,
|
||||||
|
// 勾选列
|
||||||
|
rowSelection: {
|
||||||
|
//多选框
|
||||||
|
// type: 'checkbox',
|
||||||
|
type: 'radio',
|
||||||
|
},
|
||||||
|
// 搜索
|
||||||
|
handleSearchInfoFn(info) {
|
||||||
|
return info;
|
||||||
|
},
|
||||||
|
actionColumn: {
|
||||||
|
width: 80,
|
||||||
|
title: '查看账号',
|
||||||
|
dataIndex: 'action',
|
||||||
|
// slots: { customRender: 'action' },
|
||||||
|
fixed: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const getGuiji = () => {
|
||||||
|
console.log('查看轨迹');
|
||||||
|
patrolTrackModelVisible.value = true;
|
||||||
|
};
|
||||||
|
const allData = reactive({
|
||||||
|
hulinyuan: 0,
|
||||||
|
xunchazongshu: 0,
|
||||||
|
dakadian: 0,
|
||||||
|
dakacishu: 0,
|
||||||
|
});
|
||||||
|
// 查询
|
||||||
|
interface FormState {
|
||||||
|
begintime: string;
|
||||||
|
endtime: string;
|
||||||
|
areaId: string;
|
||||||
|
}
|
||||||
|
const formState: FormState = reactive({
|
||||||
|
begintime: '',
|
||||||
|
endtime: '',
|
||||||
|
areaId: '',
|
||||||
|
});
|
||||||
|
const timeChange = (value: any, dateString: string) => {
|
||||||
|
formState.begintime = dateString[0];
|
||||||
|
formState.endtime = dateString[1];
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form-button {
|
||||||
|
button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .ant-modal {
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
.cate-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-item-container {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100px;
|
||||||
|
padding: 15px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-item {
|
||||||
|
width: calc(25% - 20px);
|
||||||
|
padding: 5px 15px;
|
||||||
|
float: left;
|
||||||
|
margin-right: 20px;
|
||||||
|
border-radius: 0px;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-item .count-item-icon {
|
||||||
|
float: left;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-item-icon img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin-top: 4px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.count-item-title {
|
||||||
|
line-height: 50px;
|
||||||
|
margin-left: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
float: left;
|
||||||
|
color: #9da1bd;
|
||||||
|
}
|
||||||
|
.count-item-value {
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 50px;
|
||||||
|
margin-left: 30px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.count-item .unit {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '所属班组',
|
||||||
|
dataIndex: 'areaName',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '护林员',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '手机号码',
|
||||||
|
dataIndex: 'account',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打卡次数',
|
||||||
|
dataIndex: 'dakacishu',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '巡检次数',
|
||||||
|
dataIndex: 'xunjian',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打卡点数量',
|
||||||
|
dataIndex: 'dakadian',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const InspectionColumns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '乡镇/村庄',
|
||||||
|
dataIndex: 'townName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '护林员姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '在线状态',
|
||||||
|
dataIndex: 'state',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '离线时长',
|
||||||
|
dataIndex: 'onLineTime',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const formSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
field: 'id',
|
||||||
|
label: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
ifShow: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'pointName',
|
||||||
|
label: '打卡点名称',
|
||||||
|
component: 'Input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'areaId',
|
||||||
|
label: '行政区划',
|
||||||
|
required: true,
|
||||||
|
slot: 'areaId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'userId',
|
||||||
|
label: '责任人',
|
||||||
|
slot: 'userId',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
export { default as LeftTable } from './LeftTable.vue';
|
||||||
|
export { default as EditModal } from './EditModal.vue';
|
||||||
|
export { default as StatisticsModel } from './StatisticsModel.vue';
|
||||||
|
export { default as Map } from './Map.vue';
|
||||||
|
export { default as PatrolTrackModel } from './PatrolTrackModel.vue';
|
||||||
|
export { default as LeftView } from './LeftView.vue';
|
||||||
|
export { default as InspectionModel } from './InspectionModel.vue';
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
||||||
|
<LeftView class="w-1/2 xl:w-1/2" v-if="viewData" @delView="delViewData" />
|
||||||
|
<LeftTable class="w-1/2 xl:w-1/2" @viewHandle="viewHandle" v-else />
|
||||||
|
<Map class="w-1/2 xl:w-1/2" />
|
||||||
|
</PageWrapper>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { PageWrapper } from '@/components/Page';
|
||||||
|
import { LeftTable, Map, LeftView } from './index';
|
||||||
|
|
||||||
|
const viewData = ref(null);
|
||||||
|
const viewHandle = (data: any) => {
|
||||||
|
console.log(data);
|
||||||
|
viewData.value = data;
|
||||||
|
};
|
||||||
|
const delViewData = () => {
|
||||||
|
viewData.value = null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="m-5 result-error">
|
|
||||||
<Result status="error" title="提交失败" sub-title="请核对并修改以下信息后,再重新提交。">
|
|
||||||
<template #extra>
|
|
||||||
<a-button key="console" type="primary"> 返回修改 </a-button>
|
|
||||||
</template>
|
|
||||||
</Result>
|
|
||||||
<div class="result-error__content">
|
|
||||||
<div class="result-error__content-title">您提交的内容有如下错误:</div>
|
|
||||||
<div class="mb-4">
|
|
||||||
<CloseCircleOutlined class="mr-2 result-error__content-icon" />
|
|
||||||
您的账户已被冻结
|
|
||||||
<a class="ml-4">立即解冻 ></a>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4">
|
|
||||||
<CloseCircleOutlined class="mr-2 result-error__content-icon" />
|
|
||||||
您的账户还不具备申请资格
|
|
||||||
<a class="ml-4">立即解冻 ></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { Result } from 'ant-design-vue';
|
|
||||||
import { CloseCircleOutlined } from '@ant-design/icons-vue';
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.result-error {
|
|
||||||
padding: 48px 32px;
|
|
||||||
background-color: @component-background;
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
padding: 24px 40px;
|
|
||||||
background-color: @app-content-background;
|
|
||||||
|
|
||||||
&-title {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-icon {
|
|
||||||
color: #ff4d4f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="m-5 result-success">
|
|
||||||
<Result
|
|
||||||
status="success"
|
|
||||||
title="提交成功"
|
|
||||||
sub-title="提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。"
|
|
||||||
>
|
|
||||||
<template #extra>
|
|
||||||
<a-button key="console" type="primary"> 返回列表 </a-button>
|
|
||||||
<a-button key="buy"> 查看项目 </a-button>
|
|
||||||
<a-button key="buy"> 打印 </a-button>
|
|
||||||
</template>
|
|
||||||
</Result>
|
|
||||||
<div class="result-success__content">
|
|
||||||
<Descriptions title="项目名称">
|
|
||||||
<Descriptions.Item label="项目 ID"> 111222 </Descriptions.Item>
|
|
||||||
<Descriptions.Item label="负责人"> Vben </Descriptions.Item>
|
|
||||||
<Descriptions.Item label="生效时间"> 2016-12-12 ~ 2017-12-12 </Descriptions.Item>
|
|
||||||
</Descriptions>
|
|
||||||
<Steps :current="1" progress-dot size="small">
|
|
||||||
<Steps.Step title="创建项目">
|
|
||||||
<template #description>
|
|
||||||
<div>Vben</div>
|
|
||||||
<p>2016-12-12 12:32</p>
|
|
||||||
</template>
|
|
||||||
</Steps.Step>
|
|
||||||
<Steps.Step title="部门初审">
|
|
||||||
<template #description>
|
|
||||||
<p>Chad</p>
|
|
||||||
</template>
|
|
||||||
</Steps.Step>
|
|
||||||
<Steps.Step title="财务复核" />
|
|
||||||
<Steps.Step title="完成" />
|
|
||||||
</Steps>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { Result, Steps, Descriptions } from 'ant-design-vue';
|
|
||||||
</script>
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.result-success {
|
|
||||||
padding: 48px 32px;
|
|
||||||
background-color: @component-background;
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
padding: 24px 40px;
|
|
||||||
background-color: @app-content-background;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in New Issue