update
init
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
@register="registerModal"
|
||||
title="监测数据"
|
||||
width="80%"
|
||||
destoryOnClose
|
||||
@cancel="closeModal"
|
||||
:bodyStyle="{ height: 'calc(100vh * 0.7)', overflow: 'hidden auto' }"
|
||||
>
|
||||
<indoor-page style="height: calc(80vh - 160px)" v-if="typeId == 0 && meterCode" :meter-code="meterCode" />
|
||||
<outer-page style="height: calc(80vh - 160px)" v-if="typeId == 1 && meterCode" :meterCode="meterCode" />
|
||||
<water-page style="height: calc(80vh - 160px)" v-if="typeId == 3 && meterCode" :meterCode="meterCode" />
|
||||
<pollen-page style="height: calc(80vh - 160px)" v-if="typeId == 2 && meterCode" :meterCode="meterCode" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import indoorPage from '/@/views/interveneNew/environment/inner/dataAnalysis/indexSon.vue';
|
||||
import outerPage from '/@/views/interveneNew/environment/outer/dataAnalysis/indexSon.vue';
|
||||
import waterPage from '/@/views/interveneNew/environment/water/dataAnalysis/indexSon.vue';
|
||||
import pollenPage from '/@/views/interveneNew/environment/pollen/dataAnalysis/indexSon.vue';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const typeId = ref(0);
|
||||
const meterCode = ref('');
|
||||
const emit = defineEmits(['closeModal']);
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
setModalProps({ showOkBtn: false, showCancelBtn: false });
|
||||
typeId.value = data.typeId;
|
||||
meterCode.value = data.meterCode;
|
||||
});
|
||||
|
||||
function closeModal() {
|
||||
typeId.value = -1;
|
||||
emit('closeModal');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
:deep(.ant-modal-header) {
|
||||
background-color: red;
|
||||
}
|
||||
:deep(.container) {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<div id="container" style="position: relative"> </div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import mapKey from '/@/utils/mapKey';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
const emit = defineEmits(['getMarkerInfo', 'getDetail']);
|
||||
|
||||
const record = ref({});
|
||||
|
||||
let BasicMap = null;
|
||||
let SelfMap = null;
|
||||
let marker = null;
|
||||
const props = defineProps({
|
||||
mapList: {
|
||||
type: Array<any>,
|
||||
default: () => [],
|
||||
},
|
||||
centerPosition: {
|
||||
type: Array<any>,
|
||||
default: () => [108.95, 34.33],
|
||||
},
|
||||
markerContent: {
|
||||
type: String,
|
||||
default: () =>
|
||||
'<div><img style="width: 20px;height: 20px" src="//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png" alt=""></div>',
|
||||
},
|
||||
labelContent: {
|
||||
type: String,
|
||||
default: () => '<div></div>',
|
||||
},
|
||||
field: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: () => 'id',
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.mapList,
|
||||
(nV) => {
|
||||
if (SelfMap) {
|
||||
addMarker(nV);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function initMap(mapList) {
|
||||
AMapLoader.load({
|
||||
key: mapKey, // 申请好的Web端开发者Key,首次调用 load 时必填
|
||||
// version: '1.4.15', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
plugins: ['AMap.Geocoder'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
||||
})
|
||||
.then((AMap) => {
|
||||
SelfMap = AMap;
|
||||
|
||||
//设置地图容器id
|
||||
BasicMap = new AMap.Map('container', {
|
||||
viewMode: '3D', //是否为3D地图模式
|
||||
zoom: 8, //初始化地图级别
|
||||
center: getCenterP(mapList), //初始化地图中心点位置
|
||||
resizeEnable: true,
|
||||
});
|
||||
addMarker(mapList);
|
||||
|
||||
let logo1 = document.getElementsByClassName('amap-logo')[0];
|
||||
if (logo1) {
|
||||
// 将logo位置设置在视野之外
|
||||
logo1.style.position = 'absolute';
|
||||
logo1.style.left = '-1000px';
|
||||
}
|
||||
let logo2 = document.getElementsByClassName('amap-copyright')[0];
|
||||
if (logo2) {
|
||||
// 将logo位置设置在视野之外
|
||||
logo2.style.position = 'absolute';
|
||||
logo2.style.left = '-1000px';
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
function getCenterP(mapList) {
|
||||
let lng = [];
|
||||
let lat = [];
|
||||
mapList.map((item: any) => {
|
||||
lng.push(item.longitude * 1);
|
||||
lat.push(item.latitude * 1);
|
||||
});
|
||||
if (mapList.length === 1) {
|
||||
return [lng[0], lat[0]];
|
||||
}
|
||||
if (mapList.length > 1) {
|
||||
return getCenter(
|
||||
lng.sort((a, b) => {
|
||||
return a - b;
|
||||
}),
|
||||
lat.sort((a, b) => {
|
||||
return a - b;
|
||||
})
|
||||
);
|
||||
}
|
||||
return props.centerPosition;
|
||||
}
|
||||
|
||||
function selectInfo(v) {
|
||||
try {
|
||||
if (v && Object.keys(JSON.parse(v)).length > 0) {
|
||||
const { longitude, latitude } = JSON.parse(v);
|
||||
record.value = JSON.parse(v);
|
||||
if (latitude && latitude) {
|
||||
let lngLat = new SelfMap.LngLat(longitude, latitude);
|
||||
BasicMap.setCenter(lngLat);
|
||||
BasicMap.setZoom(12);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
let markerList = [];
|
||||
function addMarker(list) {
|
||||
removeMarker();
|
||||
if (list.length === 0) return;
|
||||
BasicMap.setCenter(getCenterP(list));
|
||||
let marker = null;
|
||||
markerList = list.map((item: any) => {
|
||||
marker = new SelfMap.Marker({
|
||||
position: new SelfMap.LngLat(item.longitude * 1, item.latitude * 1),
|
||||
content: props.markerContent ? props.markerContent.replace('^&', item[props.field]) : item?.markerContent,
|
||||
// icon: medicalResource,
|
||||
maxZoom: 8,
|
||||
});
|
||||
marker.info = item;
|
||||
marker.on('click', markerClick);
|
||||
return marker;
|
||||
});
|
||||
BasicMap.add(markerList);
|
||||
}
|
||||
|
||||
window.getDetail = () => {
|
||||
event?.stopPropagation();
|
||||
emit('getDetail', record.value);
|
||||
};
|
||||
function getCenter(lng, lat) {
|
||||
let lngCenter = (lng[0] + lng[lng.length - 1]) / 2;
|
||||
let latCenter = (lat[0] + lat[lat.length - 1]) / 2;
|
||||
return [lngCenter, latCenter];
|
||||
// let centerLngLat = new SelfMap.LngLat(lngCenter, latCenter);
|
||||
// BasicMap.setCenter(centerLngLat); // 设置地图中心点坐标
|
||||
}
|
||||
function markerClick(e) {
|
||||
if (marker?.info[props.id] !== e.target?.info[props.id]) {
|
||||
if (marker) {
|
||||
marker.setLabel({ content: ``, direction: 'right' });
|
||||
|
||||
marker.setzIndex(1);
|
||||
}
|
||||
marker = e.target;
|
||||
emit('getMarkerInfo', e.target.info);
|
||||
|
||||
record.value = e.target.info;
|
||||
}
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
function setLabel(labelContent) {
|
||||
marker.setzIndex(999);
|
||||
marker.setLabel({
|
||||
content: labelContent,
|
||||
direction: 'right',
|
||||
});
|
||||
|
||||
let logo1 = document.getElementsByClassName('amap-marker-label')[0];
|
||||
if (logo1) {
|
||||
logo1.style.left = marker._style.width;
|
||||
}
|
||||
}
|
||||
|
||||
function removeMarker() {
|
||||
for (let i = 0; i < markerList.length; i++) {
|
||||
markerList[i].setMap(null);
|
||||
}
|
||||
markerList = []; // 清空数组
|
||||
marker = null;
|
||||
}
|
||||
|
||||
function destroyMap() {
|
||||
BasicMap.destroy();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
selectInfo,
|
||||
initMap,
|
||||
setLabel,
|
||||
destroyMap,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
#container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
:deep(.ant-drawer) {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
:deep(.ant-drawer-header) {
|
||||
background-color: #b4c7e7;
|
||||
}
|
||||
:deep(.jeecg-basic-title) {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:deep(.amap-marker-label) {
|
||||
background-color: transparent !important;
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
cursor: pointer;
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.ant-drawer-content-wrapper) {
|
||||
height: 90%;
|
||||
margin-top: 2.5%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" title="咨询数据" width="80%">
|
||||
<div class="top-d-outer">
|
||||
<div class="top-d">
|
||||
<div>医院名称:{{ hospitalInfo?.resourceName || '-' }}</div>
|
||||
<div>医院级别:{{ hospitalInfo?.level || '-' }}</div>
|
||||
<div>专家人数:{{ hospitalInfo?.specialistSum }}</div>
|
||||
<div>当年咨询人次:{{ hospitalInfo?.thisYearSessionSum }}</div>
|
||||
<div>累计咨询人次:{{ hospitalInfo?.allSessionSum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; padding-right: 5px">
|
||||
<a-radio-group v-model:value="radioValue" button-style="solid" class="radio-group-d" @change="changeRadio">
|
||||
<a-radio-button value="0">专家数据</a-radio-button>
|
||||
<a-radio-button value="1">员工咨询数据</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<BasicTable @register="registerTable" table-type="1" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { userPageApi, yearPageApi } from '/@/views/archivesManage/institution/timeService/consult/consult.api';
|
||||
import dayjs from 'dayjs';
|
||||
import { columns1, columns2 } from '/@/views/archivesManage/institution/timeService/consult/consult.data';
|
||||
|
||||
const radioValue = ref('0');
|
||||
const hospitalInfo = ref({});
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
radioValue.value = '0';
|
||||
setModalProps({ showCancelBtn: false, showOkBtn: false });
|
||||
hospitalInfo.value = data.record;
|
||||
|
||||
setProps({ api: yearPageApi, columns: columns1, searchInfo: { hospitalId: hospitalInfo.value.id, year: dayjs().format('YYYY') } });
|
||||
await reload({ page: 1 });
|
||||
});
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
canResize: false,
|
||||
orderFlag: false,
|
||||
immediate: false,
|
||||
showIndexColumn: true,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
},
|
||||
});
|
||||
const [registerTable, { setProps, reload }] = tableContext;
|
||||
|
||||
async function changeRadio(v) {
|
||||
if (v.target.value === '0') {
|
||||
setProps({ api: yearPageApi, columns: columns1 });
|
||||
await reload({ page: 1 });
|
||||
} else {
|
||||
setProps({ api: userPageApi, columns: columns2 });
|
||||
await reload({ page: 1 });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.top-d-outer {
|
||||
padding: 10px;
|
||||
.top-d {
|
||||
border-bottom: 1px dashed #cecece;
|
||||
display: flex;
|
||||
padding: 0 0 10px;
|
||||
> div {
|
||||
margin-right: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.ant-radio-button-wrapper) {
|
||||
color: #1684fc !important;
|
||||
border-color: #1684fc !important;
|
||||
&:before {
|
||||
background-color: #1684fc !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper-checked) {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/health-consultation/archives/hospital/geo',
|
||||
statistics = '/health-consultation/archives/consultation/statistics',
|
||||
userPage = '/health-consultation/archives/consultation/user-page',
|
||||
yearPage = '/health-consultation/archives/specialist/page',
|
||||
}
|
||||
|
||||
export const listApi = (params: any) => defHttp.get({ url: Api.list, params });
|
||||
export const statisticsApi = (params: any) => defHttp.get({ url: Api.statistics, params });
|
||||
export const userPageApi = (params: any) => defHttp.get({ url: Api.userPage, params });
|
||||
export const yearPageApi = (params: any) => defHttp.get({ url: Api.yearPage, params });
|
||||
@@ -0,0 +1,78 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import dayjs from 'dayjs';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
|
||||
export const columns1: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'doctorName',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
customRender: ({ text }) => {
|
||||
return render.renderDict(text, 'sex2');
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
},
|
||||
{
|
||||
title: '科室',
|
||||
dataIndex: 'departmentName',
|
||||
},
|
||||
{
|
||||
title: '职称',
|
||||
dataIndex: 'doctorJob_dictText',
|
||||
},
|
||||
{
|
||||
title: `当年服务人次(${dayjs().format('YYYY')})`,
|
||||
dataIndex: 'thisYearSessionSum',
|
||||
},
|
||||
{
|
||||
title: '累计服务人次',
|
||||
dataIndex: 'allSessionSum',
|
||||
},
|
||||
];
|
||||
export const columns2: BasicColumn[] = [
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'secondDeptName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'thirdDeptName',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'realName',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '工号',
|
||||
dataIndex: 'workNo',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
customRender: ({ text }) => {
|
||||
return render.renderDict(text, 'sex2');
|
||||
},
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '最近咨询时间',
|
||||
dataIndex: 'lastSessionDate',
|
||||
},
|
||||
{
|
||||
title: '累计咨询次数',
|
||||
dataIndex: 'sessionCount',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-title"> 长庆油田咨询医院 </div>
|
||||
<div class="map-d">
|
||||
<template v-if="!loading">
|
||||
<service-map
|
||||
ref="serviceMap"
|
||||
:marker-content="markerContent"
|
||||
:label-content="labelContent"
|
||||
field="resourceName"
|
||||
@get-marker-info="getMarkerInfo"
|
||||
@get-detail="getDetail"
|
||||
/>
|
||||
<div class="bottom-d">
|
||||
<div
|
||||
class="bottom-d-item"
|
||||
v-for="(item, index) in statisticsInfo"
|
||||
:key="`bottom-d-item-${index}`"
|
||||
:style="{ margin: index === 1 ? '0 25px 0 50px' : index === 2 ? '0 50px 0 25px' : 0 }"
|
||||
>
|
||||
<div>{{ item.value }}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<consult-modal @register="registerModal" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { listApi, statisticsApi } from '/@/views/archivesManage/institution/timeService/consult/consult.api';
|
||||
import ConsultModal from '/@/views/archivesManage/institution/timeService/consult/components/consultModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import consult from '/@/assets/images/consult/consult.png';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
const loading = ref(true);
|
||||
const serviceMap = ref();
|
||||
const statisticsInfo = ref();
|
||||
const mapList = ref();
|
||||
const orgCode = ref();
|
||||
const markerContent = ref(`<div style="white-space: nowrap;display: flex;background-color: #58a55c;padding: 5px 10px;border-radius: 10px;
|
||||
align-items: center;">
|
||||
<img src="${consult}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
|
||||
<span style="color: #ffffff">^&</span>
|
||||
</div>`);
|
||||
const labelContent = ref('');
|
||||
|
||||
onMounted(async () => {
|
||||
await initList();
|
||||
await statistics();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
serviceMap.value.destroyMap();
|
||||
});
|
||||
|
||||
async function statistics() {
|
||||
const info = await statisticsApi({});
|
||||
statisticsInfo.value = [
|
||||
{ value: info?.hospitalSum, name: '医院数量' },
|
||||
{ value: info?.specialistSum, name: '专家人数' },
|
||||
{ value: info?.thisYearSessionSum, name: `${dayjs().format('YYYY')}年咨询人次` },
|
||||
{ value: info?.allSessionSum, name: `2023年至今累计咨询人次` },
|
||||
];
|
||||
}
|
||||
|
||||
async function initList() {
|
||||
try {
|
||||
mapList.value = await listApi({ orgCode: orgCode.value === '1' ? '' : orgCode.value });
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap(mapList.value);
|
||||
});
|
||||
} catch (e) {
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap([]);
|
||||
});
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkerInfo(e) {
|
||||
let r = JSON.stringify(e);
|
||||
console.log(r);
|
||||
labelContent.value = `
|
||||
<div style="padding: 10px;background-color: #ffffff;border-radius: 10px">
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">专家人数:${e.specialistSum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">当年咨询人次:${e.thisYearSessionSum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">累计咨询人次:${e.allSessionSum} </div>
|
||||
<div style="padding-top: 8px;text-align: center;color: #5087ec" onclick="getDetail()">查看咨询数据></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
serviceMap.value.setLabel(labelContent.value);
|
||||
}
|
||||
|
||||
function getDetail(e) {
|
||||
console.log(e);
|
||||
openModal(true, {
|
||||
record: e,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-d {
|
||||
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.bottom-d {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bottom-d-item {
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
|
||||
background-color: #ffffff;
|
||||
font-weight: bold;
|
||||
padding: 0 50px;
|
||||
> div {
|
||||
text-align: center;
|
||||
&:nth-child(1) {
|
||||
font-size: 18px;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
padding: 5px 0 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map-d {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 70px);
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
}
|
||||
</style>
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" title="服务数据" width="80%">
|
||||
<div class="top-d-outer">
|
||||
<div class="top-d">
|
||||
<div>应急中心名称:{{ hospitalInfo?.centerName || '-' }}</div>
|
||||
<div>专业人员数量:{{ hospitalInfo?.majNum }}</div>
|
||||
<div>操作人员数量:{{ hospitalInfo?.opNum }}</div>
|
||||
<div>当年服务人次:{{ hospitalInfo?.thisYearNum }}</div>
|
||||
<div>累计服务人次:{{ hospitalInfo?.totalYearNum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BasicTable @register="registerTable" table-type="1" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import dayjs from 'dayjs';
|
||||
import { listInfoApi } from '/@/views/archivesManage/institution/timeService/emergency/emergency.api';
|
||||
import { columns } from '/@/views/archivesManage/institution/timeService/emergency/emergency.data';
|
||||
|
||||
const hospitalInfo = ref({});
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
setModalProps({ showCancelBtn: false, showOkBtn: false });
|
||||
hospitalInfo.value = data.record;
|
||||
|
||||
setProps({ searchInfo: { centerId: hospitalInfo.value.centerId } });
|
||||
await reload({ page: 1 });
|
||||
});
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: listInfoApi,
|
||||
columns,
|
||||
canResize: false,
|
||||
orderFlag: false,
|
||||
immediate: false,
|
||||
showIndexColumn: true,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
},
|
||||
});
|
||||
const [registerTable, { setProps, reload }] = tableContext;
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.top-d-outer {
|
||||
padding: 10px;
|
||||
.top-d {
|
||||
border-bottom: 1px dashed #cecece;
|
||||
display: flex;
|
||||
padding: 0 0 10px;
|
||||
> div {
|
||||
margin-right: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/health-emergency/archives/emergency/centers',
|
||||
listInfo = '/health-emergency/emergency/order/list',
|
||||
}
|
||||
|
||||
export const listApi = (params: any) => defHttp.get({ url: Api.list, params });
|
||||
export const listInfoApi = (params: any) => defHttp.get({ url: Api.listInfo, params });
|
||||
@@ -0,0 +1,170 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '被救助人',
|
||||
align: 'center',
|
||||
dataIndex: 'salvageUserName',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '单位',
|
||||
align: 'center',
|
||||
dataIndex: 'salvageUserSecondDepart',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
align: 'center',
|
||||
dataIndex: 'salvageUserDepart',
|
||||
},
|
||||
{
|
||||
title: '所属应急中心',
|
||||
dataIndex: 'centerName',
|
||||
},
|
||||
{
|
||||
title: '求助方式',
|
||||
align: 'center',
|
||||
dataIndex: 'initiatorType',
|
||||
customRender: ({ text }) => {
|
||||
return text == '0' ? '120' : text == '1' ? '应急就医' : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '求助时间',
|
||||
align: 'center',
|
||||
dataIndex: 'createTime',
|
||||
},
|
||||
{
|
||||
title: '员工位置',
|
||||
align: 'center',
|
||||
dataIndex: 'initiatorLongitude',
|
||||
customRender: ({ record }) => {
|
||||
// @ts-ignore
|
||||
const { initiatorLongitude, initiatorLatitude } = record;
|
||||
if (!initiatorLongitude || !initiatorLatitude) {
|
||||
return '';
|
||||
}
|
||||
return `${initiatorLongitude.toFixed(4)},${initiatorLatitude.toFixed(4)}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '专业人员',
|
||||
align: 'center',
|
||||
dataIndex: 'majorUserName',
|
||||
},
|
||||
{
|
||||
title: '操作人员',
|
||||
align: 'center',
|
||||
dataIndex: 'operationUserName',
|
||||
},
|
||||
{
|
||||
title: '驻场人员',
|
||||
align: 'center',
|
||||
dataIndex: 'stationUserName',
|
||||
},
|
||||
{
|
||||
title: '工单状态',
|
||||
align: 'center',
|
||||
dataIndex: 'orderStatus',
|
||||
customRender: ({ text }) => render.renderDict(text, 'emergency_order_status'),
|
||||
},
|
||||
// {
|
||||
// title: '派单状态',
|
||||
// align: 'center',
|
||||
// dataIndex: 'isDispatch',
|
||||
// customRender: ({ text }) => render.renderDict(text, 'emergency_order_send_status').children,
|
||||
// },
|
||||
// {
|
||||
// title: '操作人员电话',
|
||||
// align:"center",
|
||||
// dataIndex: 'operationUserMobile'
|
||||
// },
|
||||
|
||||
// {
|
||||
// title: '专业人员电话',
|
||||
// align:"center",
|
||||
// dataIndex: 'majorUserMobile'
|
||||
// },
|
||||
// {
|
||||
// title: '驻场人员',
|
||||
// align: 'center',
|
||||
// dataIndex: 'stationUserName',
|
||||
// },
|
||||
// {
|
||||
// title: '驻场人员部门',
|
||||
// align:"center",
|
||||
// dataIndex: 'stationUserDepart'
|
||||
// },
|
||||
// {
|
||||
// title: '驻场人员派单业务',
|
||||
// align:"center",
|
||||
// dataIndex: 'stationBusiness'
|
||||
// },
|
||||
// {
|
||||
// title: '操作人员响应时间',
|
||||
// align:"center",
|
||||
// dataIndex: 'operationResponseTime',
|
||||
// customRender:({text}) =>{
|
||||
// return !text?"":(text.length>10?text.substr(0,10):text)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '操作人员派单时间',
|
||||
// align:"center",
|
||||
// dataIndex: 'operationSendOrderTime',
|
||||
// customRender:({text}) =>{
|
||||
// return !text?"":(text.length>10?text.substr(0,10):text)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '专业人员响应时间',
|
||||
// align:"center",
|
||||
// dataIndex: 'majorResponseTime',
|
||||
// customRender:({text}) =>{
|
||||
// return !text?"":(text.length>10?text.substr(0,10):text)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '驻场人员响应时间',
|
||||
// align:"center",
|
||||
// dataIndex: 'stationResponseTime',
|
||||
// customRender:({text}) =>{
|
||||
// return !text?"":(text.length>10?text.substr(0,10):text)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '驻场人员拒单时间',
|
||||
// align:"center",
|
||||
// dataIndex: 'stationRejectionTime',
|
||||
// customRender:({text}) =>{
|
||||
// return !text?"":(text.length>10?text.substr(0,10):text)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '专业人员救助意见',
|
||||
// align:"center",
|
||||
// dataIndex: 'majorSalvageOpinion'
|
||||
// },
|
||||
// {
|
||||
// title: '派单医院',
|
||||
// align:"center",
|
||||
// dataIndex: 'sendOrderHospital'
|
||||
// },
|
||||
// {
|
||||
// title: '应急单状态',
|
||||
// align:"center",
|
||||
// dataIndex: 'orderStatus',
|
||||
// customRender: ({ text }) => {
|
||||
// return render.renderDict(text, 'emergency_order_status');
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '是否派单',
|
||||
// align:"center",
|
||||
// dataIndex: 'isDispatch',
|
||||
// customRender: ({ text }) => {
|
||||
// return text == false ? '否' : text == true ? '是' : '';
|
||||
// },
|
||||
// },
|
||||
];
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-title"> 长庆油田应急中心 </div>
|
||||
<div class="map-d">
|
||||
<template v-if="!loading">
|
||||
<service-map
|
||||
ref="serviceMap"
|
||||
:marker-content="markerContent"
|
||||
:label-content="labelContent"
|
||||
field="centerName"
|
||||
@get-marker-info="getMarkerInfo"
|
||||
@get-detail="getDetail"
|
||||
id="centerId"
|
||||
/>
|
||||
|
||||
<div class="bottom-d">
|
||||
<div class="bottom-d-item" v-for="(item, index) in statisticsInfo" :key="`bottom-d-item-${index}`">
|
||||
<div>{{ item.value }}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<consult-modal @register="registerModal" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
|
||||
import { onMounted, ref, nextTick, onBeforeUnmount } from 'vue';
|
||||
import { listApi } from '/@/views/archivesManage/institution/timeService/emergency/emergency.api';
|
||||
import ConsultModal from '/@/views/archivesManage/institution/timeService/emergency/components/emergencyModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import emergency from '/@/assets/images/emergency.png';
|
||||
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
const loading = ref(true);
|
||||
const serviceMap = ref();
|
||||
const statisticsInfo = ref<any[]>([]);
|
||||
const mapList = ref();
|
||||
const markerContent = ref(`<div style="white-space: nowrap;display: flex;background-color: #58a55c;padding: 5px 10px;border-radius: 10px;
|
||||
align-items: center;">
|
||||
<img src="${emergency}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
|
||||
<span style="color: #ffffff">^&</span>
|
||||
</div>`);
|
||||
const labelContent = ref('');
|
||||
|
||||
onMounted(async () => {
|
||||
await initList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
serviceMap.value.destroyMap();
|
||||
});
|
||||
|
||||
async function initList() {
|
||||
try {
|
||||
let majNum = 0;
|
||||
let opNum = 0;
|
||||
let thisYearNum = 0;
|
||||
let totalYearNum = 0;
|
||||
mapList.value = (await listApi({})).map((item) => {
|
||||
majNum += item.majNum;
|
||||
opNum += item.opNum;
|
||||
thisYearNum += item.thisYearNum;
|
||||
totalYearNum += item.totalYearNum;
|
||||
return item;
|
||||
});
|
||||
statisticsInfo.value = [
|
||||
{ value: mapList.value.length, name: '应急中心数量' },
|
||||
{ value: majNum, name: '专业人员数量' },
|
||||
{ value: opNum, name: '操作人员数量' },
|
||||
{ value: thisYearNum, name: '当年应急人次' },
|
||||
{ value: totalYearNum, name: '累计应急人次' },
|
||||
];
|
||||
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap(mapList.value);
|
||||
});
|
||||
} catch (e) {
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap([]);
|
||||
});
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkerInfo(e) {
|
||||
labelContent.value = `
|
||||
<div style="padding: 10px;background-color: #ffffff;border-radius: 10px">
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">专业人员数量:${e.majNum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">操作人员数量:${e.opNum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">当年应急人次:${e.thisYearNum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">累计应急人次:${e.totalYearNum} </div>
|
||||
<div style="padding-top: 8px;text-align: center;color: #5087ec" onclick="getDetail()">查看应急数据></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
serviceMap.value.setLabel(labelContent.value);
|
||||
}
|
||||
|
||||
function getDetail(e) {
|
||||
openModal(true, {
|
||||
record: e,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-d {
|
||||
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.bottom-d {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.bottom-d-item {
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
|
||||
background-color: #ffffff;
|
||||
font-weight: bold;
|
||||
padding: 0 50px;
|
||||
> div {
|
||||
text-align: center;
|
||||
&:nth-child(1) {
|
||||
font-size: 18px;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
padding: 5px 0 5px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map-d {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 70px);
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
}
|
||||
</style>
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" :title="title" width="80%">
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPages';
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import { abnormalApi } from '/@/views/archivesManage/institution/timeService/environment/environment.api';
|
||||
import { ref } from 'vue';
|
||||
import { columns } from '/@/views/archivesManage/institution/timeService/environment/environment.data';
|
||||
|
||||
const title = ref('');
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
setModalProps({ showOkBtn: false, cancelText: '关闭' });
|
||||
setProps({ searchInfo: { type: data?.type, orgCode: data?.orgCode } });
|
||||
title.value = data.title;
|
||||
await reload();
|
||||
});
|
||||
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: abnormalApi,
|
||||
pageTitle: '长庆油田已封存员工',
|
||||
columns,
|
||||
canResize: false,
|
||||
immediate: false,
|
||||
btnArr: ['edit', 'delete'],
|
||||
btnArrText: { add: '新增封存员工', search: '列表查询', export: '信息导出', print: '信息打印' },
|
||||
useSearchForm: false,
|
||||
showIndexColumn: true,
|
||||
indexColumnProps: {
|
||||
dataIndex: 'listIndex',
|
||||
width: 70,
|
||||
},
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { setProps, reload }, {}] = tableContext;
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,11 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/health-intervene/archive/environment/map-list',
|
||||
statistics = '/health-intervene/archive/environment/statistics',
|
||||
abnormal = '/health-intervene/archive/environment/abnormal/page',
|
||||
}
|
||||
|
||||
export const listApi = (params: any) => defHttp.get({ url: Api.list, params });
|
||||
export const statisticsApi = (params: any) => defHttp.get({ url: Api.statistics, params });
|
||||
export const abnormalApi = (params: any) => defHttp.get({ url: Api.abnormal, params });
|
||||
@@ -0,0 +1,27 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '设备所属单位',
|
||||
dataIndex: 'orgName',
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'meterName',
|
||||
},
|
||||
{
|
||||
title: '设备编码',
|
||||
dataIndex: 'meterCode',
|
||||
},
|
||||
{
|
||||
title: '设备地址',
|
||||
dataIndex: 'meterAddress',
|
||||
},
|
||||
{
|
||||
title: '最后一次回传数据时间',
|
||||
dataIndex: 'lastMonitorDate',
|
||||
customRender: ({ text }) => {
|
||||
return text || '-';
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,604 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-title"> 长庆油田环境监测设备 </div>
|
||||
<div class="map-d">
|
||||
<template v-if="!loading">
|
||||
<service-map
|
||||
ref="serviceMap"
|
||||
:map-list="mapList"
|
||||
:marker-content="null"
|
||||
:label-content="labelContent"
|
||||
@get-marker-info="getMarkerInfo"
|
||||
@get-detail="getDetail"
|
||||
id="meterId"
|
||||
/>
|
||||
<div class="search-d">
|
||||
所属单位
|
||||
<ApiSelect
|
||||
:value="orgCode"
|
||||
:api="allSecondaryDepartsNew"
|
||||
@change="
|
||||
(v) => {
|
||||
orgCode = v;
|
||||
}
|
||||
"
|
||||
resultField="result"
|
||||
labelField="departName"
|
||||
valueField="orgCode"
|
||||
:after-fetch="
|
||||
(data) => {
|
||||
data.unshift({
|
||||
orgCode: '1',
|
||||
departName: '全部单位',
|
||||
});
|
||||
return data;
|
||||
}
|
||||
"
|
||||
:allowClear="true"
|
||||
:show-default-value="false"
|
||||
:immediate="true"
|
||||
:showSearch="true"
|
||||
:filterOption="
|
||||
(input: string, option: any): boolean => {
|
||||
const str: string = input.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
}"
|
||||
style="width: 260px"
|
||||
/>
|
||||
<a-button type="primary" @click="searchB">查询</a-button>
|
||||
<a-button style="background-color: #a4adb3; color: #ffffff" @click="resetB">重置</a-button>
|
||||
</div>
|
||||
<div class="z" v-if="radioValue !== '3'">
|
||||
<div class="inner" v-if="radioValue === '0'"></div>
|
||||
<div class="outer" v-if="radioValue === '1'"></div>
|
||||
<div class="water" v-if="radioValue === '3'"></div>
|
||||
<div class="pollen" v-if="radioValue === '2'"></div>
|
||||
|
||||
<div class="z-d">
|
||||
<div v-for="(item, index) in describe[radioValue]" :key="`describe${index}`">
|
||||
{{ item }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="z" style="height: 100px; flex-direction: column; justify-content: space-around" v-else>
|
||||
<div style="display: flex; color: #ffffff; font-weight: bold">
|
||||
<div style="background-color: #00ff1a; width: 20px; height: 20px; border-radius: 6px; margin-right: 10px"></div>
|
||||
<div>达标</div>
|
||||
</div>
|
||||
<div style="display: flex; color: #ffffff; font-weight: bold">
|
||||
<div style="background-color: #ec0808; width: 20px; height: 20px; border-radius: 6px; margin-right: 10px"></div>
|
||||
<div>不达标</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-radio-group v-model:value="radioValue" button-style="solid" class="radio-group-d" @change="initList">
|
||||
<a-radio-button value="0">室内环境</a-radio-button>
|
||||
<a-radio-button value="1">室外环境</a-radio-button>
|
||||
<a-radio-button value="3">水质监测</a-radio-button>
|
||||
<a-radio-button value="2">过敏源监测</a-radio-button>
|
||||
</a-radio-group>
|
||||
|
||||
<div class="bottom-d">
|
||||
<div
|
||||
class="bottom-d-item"
|
||||
v-for="(item, index) in deviceInfo"
|
||||
:key="`bottom-d-item-${index}`"
|
||||
:style="{ margin: index === 1 ? '0 25px 0 50px' : index === 2 ? '0 50px 0 25px' : 0 }"
|
||||
>
|
||||
<div>
|
||||
<span>运行正常:{{ item.working }}台</span>
|
||||
<span
|
||||
style="color: red; cursor: pointer"
|
||||
@click="
|
||||
() => {
|
||||
openModalA(true, {
|
||||
type: item?.value,
|
||||
title: item?.name,
|
||||
orgCode: orgCode === '1' ? '' : orgCode,
|
||||
});
|
||||
}
|
||||
"
|
||||
>异常列表</span
|
||||
>
|
||||
</div>
|
||||
<div style="font-size: 30px; font-weight: bold; display: flex; justify-content: center">
|
||||
<div style="position: relative">
|
||||
{{ item.sum }}
|
||||
<span style="font-size: 16px; margin-left: -7px">台</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: center; align-items: center">
|
||||
<div style="position: relative">
|
||||
<div style="display: flex; align-items: center; position: absolute; top: 0; height: 100%; left: -30px">
|
||||
<img :src="imgInfos[index]" alt="" style="width: 25px; height: 23px" />
|
||||
</div>
|
||||
{{ item?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<environment-modal
|
||||
@register="registerModal"
|
||||
@close-modal="
|
||||
() => {
|
||||
count++;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<environment-abnormal-modal @register="registerModalA" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
|
||||
import { nextTick, onMounted, ref, onBeforeUnmount } from 'vue';
|
||||
import { listApi, statisticsApi } from '/@/views/archivesManage/institution/timeService/environment/environment.api';
|
||||
import { getName } from '/@/views/interveneNew/compoents/utils';
|
||||
import ApiSelect from '/@/components/Form/src/components/ApiSelect.vue';
|
||||
import { allSecondaryDepartsNew } from '/@/utils/orgSearchInfo';
|
||||
import EnvironmentModal from '/@/views/archivesManage/institution/timeService/components/environmentModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import innerPng from '/@/assets/images/enviroment/institution/inner.png';
|
||||
import outerPng from '/@/assets/images/enviroment/institution/outer.png';
|
||||
import waterPng from '/@/assets/images/enviroment/institution/water.png';
|
||||
import pollenPng from '/@/assets/images/enviroment/institution/pollen.png';
|
||||
import innerPngS from '/@/assets/images/enviroment/institution/inner-s.png';
|
||||
import outerPngS from '/@/assets/images/enviroment/institution/outer-s.png';
|
||||
import waterPngS from '/@/assets/images/enviroment/institution/water-s.png';
|
||||
import pollenPngS from '/@/assets/images/enviroment/institution/pollen-s.png';
|
||||
import EnvironmentAbnormalModal from '/@/views/archivesManage/institution/timeService/environment/components/environmentAbnormalModal.vue';
|
||||
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
const [registerModalA, { openModal: openModalA }] = useModal();
|
||||
|
||||
const imgInfo = ref({
|
||||
'0': innerPng,
|
||||
'1': outerPng,
|
||||
'3': waterPng,
|
||||
'2': pollenPng,
|
||||
});
|
||||
const imgInfos = ref({
|
||||
0: innerPngS,
|
||||
1: outerPngS,
|
||||
2: waterPngS,
|
||||
3: pollenPngS,
|
||||
});
|
||||
|
||||
const describe = ref({
|
||||
'0': ['清洁', '未污染', '轻污染', '中污染', '重污染'],
|
||||
'1': ['优', '良', '轻度污染', '中度污染', '重度污染', '严重污染'],
|
||||
'3': ['达标', '不达标'],
|
||||
'2': ['很低', '低', '中等', '高', '很高'],
|
||||
});
|
||||
|
||||
const colorInfo = ref({
|
||||
'0': [
|
||||
{ value: 1, label: '#66c706' },
|
||||
{ value: 2, label: '#f5cc27' },
|
||||
{ value: 3, label: '#fe8700' },
|
||||
{ value: 4, label: '#e60707' },
|
||||
{ value: 5, label: '#940654' },
|
||||
],
|
||||
'1': [
|
||||
{ value: 1, label: '#66c706' },
|
||||
{ value: 2, label: '#f5cc27' },
|
||||
{ value: 3, label: '#fe8700' },
|
||||
{ value: 4, label: '#e60707' },
|
||||
{ value: 5, label: '#65001c' },
|
||||
{ value: 6, label: '#65001c' },
|
||||
],
|
||||
'3': [
|
||||
{ value: 0, label: '#ec0808' },
|
||||
{ value: 1, label: '#66c706' },
|
||||
],
|
||||
'2': [
|
||||
{ value: 1, label: '#66c706' },
|
||||
{ value: 2, label: '#f5cc27' },
|
||||
{ value: 3, label: '#fe8700' },
|
||||
{ value: 4, label: '#e60707' },
|
||||
{ value: 5, label: '#65001c' },
|
||||
],
|
||||
});
|
||||
|
||||
const level = ref({
|
||||
'0': [
|
||||
{ value: 1, label: 'I级' },
|
||||
{ value: 2, label: 'II级' },
|
||||
{ value: 3, label: 'III级' },
|
||||
{ value: 4, label: 'IV级' },
|
||||
{ value: 5, label: 'V级' },
|
||||
],
|
||||
'1': [
|
||||
{ value: 1, label: '一级' },
|
||||
{ value: 2, label: '二级' },
|
||||
{ value: 3, label: '三级' },
|
||||
{ value: 4, label: '四级' },
|
||||
{ value: 5, label: '五级' },
|
||||
{ value: 5, label: '六级' },
|
||||
],
|
||||
'3': [
|
||||
{ value: 0, label: '不合格' },
|
||||
{ value: 1, label: '合格' },
|
||||
],
|
||||
});
|
||||
|
||||
const loading = ref(true);
|
||||
const radioValue = ref('0');
|
||||
const serviceMap = ref();
|
||||
const mapList = ref<any[]>([]);
|
||||
const labelContent = ref('');
|
||||
|
||||
const deviceInfo = ref({});
|
||||
const orgCode = ref('1');
|
||||
const count = ref(0);
|
||||
|
||||
function getMarkerInfo(e) {
|
||||
let color = e.newData ? getName(e.newData.score, colorInfo.value[radioValue.value]) : 'red';
|
||||
switch (radioValue.value) {
|
||||
case '0':
|
||||
labelContent.value = innerDoor(e, color);
|
||||
break;
|
||||
case '1':
|
||||
labelContent.value = outerDoor(e, color);
|
||||
break;
|
||||
case '3':
|
||||
labelContent.value = water(e, color);
|
||||
break;
|
||||
case '2':
|
||||
labelContent.value = pollen(e, color);
|
||||
break;
|
||||
}
|
||||
serviceMap.value.setLabel(labelContent.value);
|
||||
}
|
||||
|
||||
function innerDoor(e, color) {
|
||||
return `
|
||||
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>
|
||||
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
|
||||
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
|
||||
<div style="margin-top: 10px">综合指数:${e.newData ? Math.round(e.newData.compositeIndex * 100) / 100 : '-'}</div>
|
||||
<div style="margin-top: 10px;">空气质量级别:${e.newData ? getName(e.newData.score, level.value[radioValue.value]) : '-'}</div>
|
||||
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
|
||||
</div>
|
||||
<div style="margin-left: 10px">
|
||||
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
|
||||
<div style="text-align: center; font-size: 12px">空气质量</div>
|
||||
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
|
||||
${e.newData?.score_dictText || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 5px 0 0;
|
||||
border-top: 1px dashed #cecece;
|
||||
margin: 5px 0 0;">
|
||||
设备地址:${e?.meterAddress || '-'}
|
||||
</div>
|
||||
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
|
||||
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
function outerDoor(e, color) {
|
||||
return `
|
||||
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>
|
||||
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
|
||||
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
|
||||
<div style="margin-top: 10px">空气质量指数(AQI)${e?.newData?.compositeIndex || '-'}</div>
|
||||
<div style="margin-top: 10px;">空气质量级别:${e.newData ? getName(e.newData.score, level.value[radioValue.value]) : '-'}</div>
|
||||
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
|
||||
</div>
|
||||
<div style="margin-left: 10px">
|
||||
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
|
||||
<div style="text-align: center; font-size: 12px">空气质量评价</div>
|
||||
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
|
||||
${e.newData?.score_dictText || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 5px 0 0;
|
||||
border-top: 1px dashed #cecece;
|
||||
margin: 5px 0 0;">
|
||||
设备地址:${e?.meterAddress || '-'}
|
||||
</div>
|
||||
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
|
||||
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
function water(e, color) {
|
||||
return `
|
||||
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>
|
||||
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
|
||||
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
|
||||
<div style="margin-top: 10px">TDS:${e.newData?.tds || '-'}</div>
|
||||
<div style="margin-top: 10px;">PH:${e.newData?.ph || '-'}</div>
|
||||
<div style="margin-top: 10px;">电导率:${e.newData?.conductivity || '-'}</div>
|
||||
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
|
||||
</div>
|
||||
<div style="margin-left: 10px">
|
||||
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
|
||||
<div style="text-align: center; font-size: 12px">空气质量评价</div>
|
||||
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
|
||||
${e.newData?.score_dictText || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 5px 0 0;
|
||||
border-top: 1px dashed #cecece;
|
||||
margin: 5px 0 0;">
|
||||
设备地址:${e?.meterAddress || '-'}
|
||||
</div>
|
||||
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
|
||||
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
function pollen(e, color) {
|
||||
return `
|
||||
<div style="background-color: #ffffff; padding: 10px; border-radius: 10px;z-index: 999">
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>
|
||||
<div style="font-size: 18px; font-weight: bold">${e.meterName}</div>
|
||||
<div style="margin-top: 10px">单位名称:${e.orgName || '-'}</div>
|
||||
<div style="margin-top: 10px">花粉浓度:${e.newData?.totalPollen || '-'}</div>
|
||||
<div style="margin-top: 10px;">主要过敏源:${e.newData?.majorAllergens || '-'}</div>
|
||||
<div style="margin-top: 10px;">更新时间:${e.lastMonitorDate || '-'}</div>
|
||||
</div>
|
||||
<div style="margin-left: 10px">
|
||||
<div style="padding: 30px; border-radius: 50%; border: 5px solid ${color}">
|
||||
<div style="text-align: center; font-size: 12px">空气质量评价</div>
|
||||
<div style="text-align: center; font-size: 19px; font-weight: bold; color: green;margin-top: 10px">
|
||||
${e.newData?.score_dictText || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 5px 0 0;
|
||||
border-top: 1px dashed #cecece;
|
||||
margin: 5px 0 0;">
|
||||
设备地址:${e?.meterAddress || '-'}
|
||||
</div>
|
||||
<div style="text-align: center;height: 30px;line-height: 30px;" onclick="getDetail('${e.meterCode}')">
|
||||
<span style="cursor: pointer;color: #2189ff">查看监测数据></span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function getDetail(e) {
|
||||
openModal(true, {
|
||||
typeId: radioValue.value,
|
||||
meterCode: e.meterCode,
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await initList();
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap(mapList.value);
|
||||
});
|
||||
await getStatistics();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
serviceMap.value.destroyMap();
|
||||
});
|
||||
|
||||
async function getStatistics() {
|
||||
try {
|
||||
const res = await statisticsApi({ orgCode: orgCode.value === '1' ? '' : orgCode.value });
|
||||
deviceInfo.value = [
|
||||
{
|
||||
sum: res?.indoorMeterSum || 0,
|
||||
working: res?.indoorMeterWorking || 0,
|
||||
name: '室内环境',
|
||||
value: '0',
|
||||
},
|
||||
{
|
||||
sum: res?.outdoorMeterSum || 0,
|
||||
working: res?.outdoorMeterWorking || 0,
|
||||
name: '室外环境',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
sum: res?.waterQualityMeterSum || 0,
|
||||
working: res?.waterQualityMeterWorking || 0,
|
||||
name: '水质监测设备',
|
||||
value: '3',
|
||||
},
|
||||
{
|
||||
sum: res?.pollenMeterSum || 0,
|
||||
working: res?.pollenMeterWorking || 0,
|
||||
name: '过敏源监测设备',
|
||||
value: '2',
|
||||
},
|
||||
];
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function initList() {
|
||||
try {
|
||||
mapList.value = (await listApi({ type: radioValue.value, orgCode: orgCode.value === '1' ? '' : orgCode.value })).map((item) => {
|
||||
let color = item.newData ? getName(item.newData.score, colorInfo.value[radioValue.value]) : 'red';
|
||||
item['img'] = imgInfo.value[radioValue.value];
|
||||
item[
|
||||
'markerContent'
|
||||
] = `<div style="white-space: nowrap;display: flex;background-color: ${color};padding: 5px 10px;border-radius: 10px">
|
||||
<img src="${imgInfo.value[radioValue.value]}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
|
||||
<span style="color: #ffffff">${
|
||||
item.newData
|
||||
? item.newData.score_dictText +
|
||||
(radioValue.value !== '3' ? '(' + item.newData[radioValue.value !== '2' ? 'compositeIndex' : 'totalPollen'] + ')' : '')
|
||||
: '暂无数据'
|
||||
}</span>
|
||||
</div>`;
|
||||
return item;
|
||||
});
|
||||
} catch (e) {
|
||||
mapList.value = [];
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function searchB() {
|
||||
await initList();
|
||||
await getStatistics();
|
||||
}
|
||||
async function resetB() {
|
||||
orgCode.value = '1';
|
||||
await searchB();
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-d {
|
||||
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.radio-group-d {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 10px;
|
||||
z-index: 99;
|
||||
}
|
||||
.bottom-d {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bottom-d-item {
|
||||
width: 200px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
|
||||
background-color: #ffffff;
|
||||
> div {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
&:nth-child(1) {
|
||||
color: green;
|
||||
text-align: left;
|
||||
padding: 5px 15px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding: 3px 0 3px 0;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding: 0 0 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map-d {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 70px);
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
}
|
||||
.z {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
right: 50px;
|
||||
background-color: rgba(#8c8c8c, 0.5);
|
||||
border-radius: 10px;
|
||||
padding: 10px 30px 10px 10px;
|
||||
display: flex;
|
||||
height: 300px;
|
||||
|
||||
.inner {
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-radius: 7px;
|
||||
background: linear-gradient(#02fb1b 0, #2ab539 25%, #f7e303 50%, #fe8a02 75%, #ed1507 100%);
|
||||
}
|
||||
.outer {
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-radius: 7px;
|
||||
background: linear-gradient(#0efe19 0, #fed302 20%, #fe8702 40%, #ef1b07 60%, #962e91 80%, #3d095f 100%);
|
||||
}
|
||||
.pollen {
|
||||
width: 15px;
|
||||
height: 100%;
|
||||
border-radius: 7px;
|
||||
background: linear-gradient(#01fbe2 0, #36ce20 25%, #f3df04 50%, #fe8902 75%, #ed1008 100%);
|
||||
}
|
||||
|
||||
.z-d {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 8px;
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper) {
|
||||
color: #1684fc !important;
|
||||
border-color: #1684fc !important;
|
||||
&:before {
|
||||
background-color: #1684fc !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper-checked) {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
knowledgePage = '/health-intervene/archive/knowledge/browse-top',
|
||||
knowledgeStat = '/health-intervene/archive/knowledge/statistics',
|
||||
}
|
||||
|
||||
export const knowledgePageApi = (params) => defHttp.get({ url: Api.knowledgePage, params });
|
||||
export const knowledgeStatApi = (params) => defHttp.get({ url: Api.knowledgeStat, params });
|
||||
@@ -0,0 +1,49 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '资源名称',
|
||||
dataIndex: 'title',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '内容简介',
|
||||
dataIndex: 'content',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '所属类别',
|
||||
dataIndex: 'type_dictText',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '主讲人姓名',
|
||||
dataIndex: 'keynoteSpeaker',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '主讲人所在机构',
|
||||
dataIndex: 'speakerDept',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '职务职称',
|
||||
dataIndex: 'duty',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '浏览人次',
|
||||
dataIndex: 'browseCount',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
sorter: {
|
||||
compare: (a, b) => a.browseCount - b.browseCount,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<BasicTables @register="registerTable">
|
||||
<template #btnTop>
|
||||
<div class="all-stat">
|
||||
<span>
|
||||
视频知识总数量:{{ allData?.videoCount ? allData?.videoCount : '--' }}, 浏览总人数:{{
|
||||
allData?.videoBrowse ? allData?.videoBrowse : '--'
|
||||
}}
|
||||
</span>
|
||||
<span>
|
||||
图文知识总数量:{{ allData?.imageCount ? allData?.imageCount : '--' }}, 浏览总人数:{{
|
||||
allData?.imageBrowse ? allData?.imageBrowse : '--'
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="title-p">知识浏览次数排名</p>
|
||||
<a-radio-group v-model:value="dataType" button-style="solid" @change="chooseData">
|
||||
<a-radio-button :value="1">视频知识</a-radio-button>
|
||||
<a-radio-button :value="0">图文知识</a-radio-button>
|
||||
<!-- <a-radio-button :value="2">音频知识</a-radio-button>-->
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex == 'title'">
|
||||
<a-button type="link" @click="handleClick(record)">{{ record.title }}</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTables>
|
||||
<div style="display: none">
|
||||
<ImagePreviewGroup v-if="imgList && imgList.length > 0" :preview="{ visible, onVisibleChange: (vis) => (visible = vis) }">
|
||||
<Image v-for="(item, index) in imgList" :key="index" :width="200" :fallback="getFamaleDefaultImage()" :src="getFileAccessHttpUrl(item)" />
|
||||
</ImagePreviewGroup>
|
||||
</div>
|
||||
<video-preview ref="videoPreviewRef" :url="videoUrl" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicTables from '/@/components/Table/src/BasicTables.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPages';
|
||||
import { columns } from '/@/views/archivesManage/institution/timeService/knowledge/knowledge.data';
|
||||
import { knowledgePageApi, knowledgeStatApi } from '/@/views/archivesManage/institution/timeService/knowledge/knowledge.api';
|
||||
import { ref, nextTick, onMounted } from 'vue';
|
||||
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons-vue';
|
||||
import VideoPreview from '/@/components/Video/VideoPreview.vue';
|
||||
import { Image, ImagePreviewGroup, message } from 'ant-design-vue';
|
||||
import { getFamaleDefaultImage, getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||
const videoPreviewRef = ref();
|
||||
const dataType = ref(1);
|
||||
const imgList = ref<string[]>([]);
|
||||
const visible = ref(false);
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
pageTitle: '长庆油田知识资源',
|
||||
btnArr: ['add', 'search', 'edit', 'delete', 'export', 'total', 'print'],
|
||||
api: knowledgePageApi,
|
||||
columns: columns,
|
||||
beforeFetch: (params) => {
|
||||
params.type = dataType.value;
|
||||
return params;
|
||||
},
|
||||
canResize: false,
|
||||
showIndexColumn: true,
|
||||
indexColumnProps: {
|
||||
dataIndex: 'listIndex',
|
||||
width: 70,
|
||||
},
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload }] = tableContext;
|
||||
const allData = ref();
|
||||
onMounted(async () => {
|
||||
allData.value = await knowledgeStatApi({});
|
||||
});
|
||||
function chooseData() {
|
||||
reload();
|
||||
}
|
||||
function handleClick(record) {
|
||||
console.log(record);
|
||||
switch (dataType.value) {
|
||||
case 1:
|
||||
previewResources(record?.videoUrl);
|
||||
break;
|
||||
case 2:
|
||||
const audio = new Audio('13203.wav');
|
||||
audio.play();
|
||||
break;
|
||||
default:
|
||||
handleAva(record?.titlePic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
function handleAva(images) {
|
||||
nextTick(() => {
|
||||
imgList.value = images?.split(',');
|
||||
visible.value = true;
|
||||
});
|
||||
}
|
||||
const videoUrl = ref('');
|
||||
const showVideo = ref(false);
|
||||
function previewResources(url: string) {
|
||||
if (!url) return message.info('未找到文件资源');
|
||||
videoUrl.value = url && url.indexOf('http') !== -1 ? url : getFileAccessHttpUrl(url);
|
||||
videoPreviewRef.value && videoPreviewRef.value.showPreview();
|
||||
showVideo.value = true;
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.all-stat {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
border: 1px solid #e9e9e9;
|
||||
span {
|
||||
border-right: 1px solid #e9e9e9;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title-p {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.count {
|
||||
position: relative;
|
||||
.lined-arr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* margin-left: 27px; */
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper) {
|
||||
color: #1684fc !important;
|
||||
border-color: #1684fc !important;
|
||||
&:before {
|
||||
background-color: #1684fc !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper-checked) {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" title="服务数据" width="80%">
|
||||
<div class="top-d-outer">
|
||||
<div class="top-d">
|
||||
<div>医院名称:{{ hospitalInfo?.centerName || '-' }}</div>
|
||||
<div>医护人员数量:{{ hospitalInfo?.medicalCareNum }}</div>
|
||||
<div>当年服务人次:{{ hospitalInfo?.thisYearNum }}</div>
|
||||
<div>累计服务人次:{{ hospitalInfo?.totalYearNum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; padding-right: 5px">
|
||||
<a-radio-group v-model:value="radioValue" button-style="solid" class="radio-group-d" @change="changeRadio">
|
||||
<a-radio-button value="0">就诊服务</a-radio-button>
|
||||
<a-radio-button value="1">随访服务</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<BasicTable @register="registerTable" table-type="1">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'nr1'">
|
||||
<a-button
|
||||
type="link"
|
||||
@click="
|
||||
() => {
|
||||
openDrawer(true, {
|
||||
// record: res,
|
||||
userInfo: record,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
type: '详情',
|
||||
});
|
||||
}
|
||||
"
|
||||
>查看</a-button
|
||||
>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'nr2'">
|
||||
<a-button type="link" @click="openViewDrawerD(record)">查看</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
|
||||
<MedicalStaffDrawer @register="registerDrawer" type="1" />
|
||||
<FollowUpTasksViewDrawer @register="registerViewDrawer" type="1">
|
||||
<template #taskList>
|
||||
<div v-if="taskList.length > 0" style="width: 100%; border: 1px dashed #999; padding: 10px; margin-top: 10px">
|
||||
<div style="font-weight: bold; margin: 0 0 10px 0; font-size: 14px; display: flex; align-items: center">
|
||||
<span class="circular"></span> 当前关联的任务
|
||||
</div>
|
||||
<template v-for="(item, index) in taskList" :key="`taskList-${index}`">
|
||||
<div style="width: 100%; display: flex; padding: 3px 10px; margin-bottom: 10px; background: #ececec">
|
||||
<div style="width: 40px; display: flex; align-items: center"> </div>
|
||||
<div style="width: calc(100% - 40px)">
|
||||
<div style="display: flex; justify-content: space-between; width: 100%; padding: 2px 0">
|
||||
<span>{{ getTaskName(item.type) }}</span>
|
||||
<span
|
||||
v-if="item.type != 2"
|
||||
style="color: #ffffff; padding: 1px 5px"
|
||||
:style="{ background: item.status == 1 ? '#FCA318' : item.status == 2 ? '#FD2121' : '#2AC18B' }"
|
||||
>
|
||||
{{ getName(item.status, taskStatus) }}
|
||||
</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; width: 100%; padding: 2px 0">
|
||||
<span>计划随访日期:{{ dayjs(item.expectDate).format('YYYY-MM-DD') }}</span>
|
||||
|
||||
<template v-if="item.status === 1">
|
||||
<template v-if="getStatusName(item.expectDate) === 0"> <span>今日</span> </template>
|
||||
<template v-else>
|
||||
<span>
|
||||
还剩 <span style="color: red">{{ getStatusName(item.expectDate) * -1 }}</span> 天
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="item.status === 2">
|
||||
<span>
|
||||
逾期 <span style="color: red">{{ getStatusName(item.expectDate) * -1 }}</span> 天
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</FollowUpTasksViewDrawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { userPageApi, yearPageApi } from '/@/views/archivesManage/institution/timeService/medical/medical.api';
|
||||
import dayjs from 'dayjs';
|
||||
import { columns1, columns2 } from '/@/views/archivesManage/institution/timeService/medical/medical.data';
|
||||
import MedicalStaffDrawer from '/@/views/interveneNew/medicalPoints/employeeTreatment/components/employeeTreatmentDrawer.vue';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { getName } from '/@/views/interveneNew/compoents/utils';
|
||||
import FollowShow from '/@/views/interveneNew/medicalPoints/follow/componets/followShow.vue';
|
||||
import FollowUpTasksViewDrawer from '/@/views/interveneNew/medicalPoints/followUpTasks/components/followUpTasksViewDrawer.vue';
|
||||
import { queryByIdNewApi } from '/@/views/interveneNew/medicalPoints/follow/follow.api';
|
||||
|
||||
const [registerDrawer, { openDrawer }] = useDrawer();
|
||||
const [registerViewDrawer, { openDrawer: openViewDrawer }] = useDrawer();
|
||||
|
||||
async function openViewDrawerD(record: Recordable) {
|
||||
taskList.value = [];
|
||||
openViewDrawer(true, {
|
||||
records: record,
|
||||
});
|
||||
try {
|
||||
taskList.value = await queryByIdNewApi({ recordId: record.id });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
const radioValue = ref('0');
|
||||
const hospitalInfo = ref({});
|
||||
const taskList = ref<any[]>([]);
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
radioValue.value = '0';
|
||||
setModalProps({ showCancelBtn: false, showOkBtn: false });
|
||||
hospitalInfo.value = data.record;
|
||||
|
||||
setProps({
|
||||
api: yearPageApi,
|
||||
columns: columns1,
|
||||
searchInfo: { medicalCenterId: hospitalInfo.value.centerId, departCode: hospitalInfo.value.orgCode, userSign: true },
|
||||
});
|
||||
await reload({ page: 1 });
|
||||
});
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
canResize: false,
|
||||
orderFlag: false,
|
||||
immediate: false,
|
||||
showIndexColumn: true,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
},
|
||||
});
|
||||
const [registerTable, { setProps, reload, setTableData, setPagination }] = tableContext;
|
||||
|
||||
async function changeRadio(v) {
|
||||
setTableData([]);
|
||||
setPagination({ total: 0 });
|
||||
if (v.target.value === '0') {
|
||||
setProps({
|
||||
api: yearPageApi,
|
||||
columns: columns1,
|
||||
searchInfo: { medicalCenterId: hospitalInfo.value.centerId, departCode: hospitalInfo.value.orgCode, userSign: true },
|
||||
});
|
||||
await reload({ page: 1 });
|
||||
} else {
|
||||
setProps({
|
||||
api: userPageApi,
|
||||
columns: columns2,
|
||||
searchInfo: { medicalId: hospitalInfo.value.centerId, medicalOrgCode: hospitalInfo.value.orgCode, type: 0 },
|
||||
});
|
||||
await reload({ page: 1 });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.top-d-outer {
|
||||
padding: 10px;
|
||||
.top-d {
|
||||
border-bottom: 1px dashed #cecece;
|
||||
display: flex;
|
||||
padding: 0 0 10px;
|
||||
> div {
|
||||
margin-right: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper) {
|
||||
color: #1684fc !important;
|
||||
border-color: #1684fc !important;
|
||||
&:before {
|
||||
background-color: #1684fc !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-button-wrapper-checked) {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/medical-center/archives/medical-center/centers',
|
||||
statistics = '/health-consultation/archives/consultation/statistics',
|
||||
userPage = '/medical-center/medicalCenter/followUpRecord/list',
|
||||
yearPage = '/medical-center/medicalCenter/dailyDiagnosis/list',
|
||||
}
|
||||
|
||||
export const listApi = (params: any) => defHttp.get({ url: Api.list, params });
|
||||
export const statisticsApi = (params: any) => defHttp.get({ url: Api.statistics, params });
|
||||
export const userPageApi = (params: any) => defHttp.get({ url: Api.userPage, params });
|
||||
export const yearPageApi = (params: any) => defHttp.get({ url: Api.yearPage, params });
|
||||
@@ -0,0 +1,158 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import dayjs from 'dayjs';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
import { getNotHaveName } from '/@/views/interveneNew/compoents/utils';
|
||||
|
||||
export const columns1: BasicColumn[] = [
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'userOrgName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'userDepartName',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'userName',
|
||||
width: 90,
|
||||
},
|
||||
{
|
||||
title: '员工编号',
|
||||
dataIndex: 'workNo',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
customRender: ({ text }) => {
|
||||
return render.renderDict(text, 'sex2');
|
||||
},
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'phone',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
dataIndex: 'idCard',
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
title: '就诊医疗点',
|
||||
dataIndex: 'medicalCenterName',
|
||||
},
|
||||
{
|
||||
title: '就诊疾病',
|
||||
dataIndex: 'diagnosisDisease',
|
||||
},
|
||||
{
|
||||
title: '就诊医生',
|
||||
dataIndex: 'doctorName',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '就诊时间',
|
||||
dataIndex: 'diagnosisDate',
|
||||
},
|
||||
{
|
||||
title: '就诊内容',
|
||||
dataIndex: 'nr1',
|
||||
width: 80,
|
||||
},
|
||||
];
|
||||
export const columns2: BasicColumn[] = [
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'orgName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'userDepartName',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'userName',
|
||||
width: 90,
|
||||
},
|
||||
{
|
||||
title: '员工编号',
|
||||
dataIndex: 'userNo',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex_dictText',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '手机号码',
|
||||
dataIndex: 'telPhone',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
dataIndex: 'idNo',
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
title: '随访医疗点',
|
||||
dataIndex: 'medicalName',
|
||||
},
|
||||
{
|
||||
title: '症状',
|
||||
dataIndex: 'symptom',
|
||||
},
|
||||
{
|
||||
title: '随访形式',
|
||||
dataIndex: 'followUp',
|
||||
customRender: ({ text }) => {
|
||||
return getNotHaveName(text, followType);
|
||||
},
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '随访医生',
|
||||
dataIndex: 'doctorName',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '随访时间',
|
||||
dataIndex: 'followDate',
|
||||
},
|
||||
{
|
||||
title: '随访内容',
|
||||
dataIndex: 'nr2',
|
||||
width: 80,
|
||||
},
|
||||
];
|
||||
const followType = [
|
||||
{
|
||||
label: '门诊',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '巡诊',
|
||||
value: '4',
|
||||
},
|
||||
{
|
||||
label: '家庭',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: '电话',
|
||||
value: '3',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-title"> 长庆油田一线医疗点 </div>
|
||||
<div class="map-d">
|
||||
<template v-if="!loading">
|
||||
<service-map
|
||||
ref="serviceMap"
|
||||
:marker-content="markerContent"
|
||||
:label-content="labelContent"
|
||||
field="centerName"
|
||||
:map-list="mapList"
|
||||
@get-marker-info="getMarkerInfo"
|
||||
@get-detail="getDetail"
|
||||
id="centerId"
|
||||
/>
|
||||
|
||||
<div class="search-d">
|
||||
所属单位
|
||||
<ApiSelect
|
||||
:value="orgCode"
|
||||
:api="allSecondaryDepartsNew"
|
||||
@change="
|
||||
(v) => {
|
||||
orgCode = v;
|
||||
}
|
||||
"
|
||||
resultField="result"
|
||||
labelField="departName"
|
||||
valueField="orgCode"
|
||||
:after-fetch="
|
||||
(data) => {
|
||||
data.unshift({
|
||||
orgCode: '1',
|
||||
departName: '全部单位',
|
||||
});
|
||||
return data;
|
||||
}
|
||||
"
|
||||
:allowClear="true"
|
||||
:show-default-value="false"
|
||||
:immediate="true"
|
||||
:showSearch="true"
|
||||
:filterOption="
|
||||
(input: string, option: any): boolean => {
|
||||
const str: string = input.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
}"
|
||||
style="width: 260px"
|
||||
/>
|
||||
<a-button type="primary" @click="searchB">查询</a-button>
|
||||
<a-button style="background-color: #a4adb3; color: #ffffff" @click="resetB">重置</a-button>
|
||||
</div>
|
||||
<div class="bottom-d">
|
||||
<div
|
||||
class="bottom-d-item"
|
||||
v-for="(item, index) in statisticsInfo"
|
||||
:key="`bottom-d-item-${index}`"
|
||||
:style="{ margin: index === 1 ? '0 25px 0 50px' : index === 2 ? '0 50px 0 25px' : 0 }"
|
||||
>
|
||||
<div>{{ item.value }}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<consult-modal @register="registerModal" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
|
||||
import { nextTick, onMounted, ref, onBeforeUnmount } from 'vue';
|
||||
import { listApi } from '/@/views/archivesManage/institution/timeService/medical/medical.api';
|
||||
import ConsultModal from '/@/views/archivesManage/institution/timeService/medical/components/medicalModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { allSecondaryDepartsNew } from '/@/utils/orgSearchInfo';
|
||||
import ApiSelect from '/@/components/Form/src/components/ApiSelect.vue';
|
||||
import building from '/@/assets/images/archivesManage/building.png';
|
||||
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
const loading = ref(true);
|
||||
const serviceMap = ref();
|
||||
const statisticsInfo = ref<any[]>([]);
|
||||
const orgCode = ref('1');
|
||||
const mapList = ref();
|
||||
const markerContent = ref(`<div style="white-space: nowrap;display: flex;background-color: #58a55c;padding: 5px 10px;border-radius: 10px;
|
||||
align-items: center;">
|
||||
<img src="${building}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
|
||||
<span style="color: #ffffff">^&</span>
|
||||
</div>`);
|
||||
const labelContent = ref('');
|
||||
|
||||
onMounted(async () => {
|
||||
await initList();
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap(mapList.value);
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
serviceMap.value.destroyMap();
|
||||
});
|
||||
async function initList() {
|
||||
try {
|
||||
let specialistSum = 0;
|
||||
let thisYearSessionSum = 0;
|
||||
let allSessionSum = 0;
|
||||
mapList.value = (await listApi({ orgCode: orgCode.value === '1' ? '' : orgCode.value })).map((item) => {
|
||||
specialistSum += item.medicalCareNum;
|
||||
thisYearSessionSum += item.thisYearNum;
|
||||
allSessionSum += item.totalYearNum;
|
||||
return item;
|
||||
});
|
||||
statisticsInfo.value = [
|
||||
{ value: mapList.value.length, name: '医疗点数量' },
|
||||
{ value: specialistSum, name: '医护人员数量' },
|
||||
{ value: thisYearSessionSum, name: '当年服务人次' },
|
||||
{ value: allSessionSum, name: '累计服务人次' },
|
||||
];
|
||||
} catch (e) {
|
||||
mapList.value = [];
|
||||
|
||||
statisticsInfo.value = [
|
||||
{ value: 0, name: '医疗点数量' },
|
||||
{ value: 0, name: '医护人员数量' },
|
||||
{ value: 0, name: '当年服务人次' },
|
||||
{ value: 0, name: '累计服务人次' },
|
||||
];
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkerInfo(e) {
|
||||
labelContent.value = `
|
||||
<div style="padding: 10px;background-color: #ffffff;border-radius: 10px">
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">医护人员数量:${e.medicalCareNum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">当年服务人次:${e.thisYearNum} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">累计服务人次:${e.totalYearNum} </div>
|
||||
<div style="padding-top: 8px;text-align: center;color: #5087ec" onclick="getDetail()">查看服务数据></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
serviceMap.value.setLabel(labelContent.value);
|
||||
}
|
||||
|
||||
async function searchB() {
|
||||
await initList();
|
||||
}
|
||||
async function resetB() {
|
||||
orgCode.value = '1';
|
||||
await searchB();
|
||||
}
|
||||
|
||||
function getDetail(e) {
|
||||
openModal(true, {
|
||||
record: e,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-d {
|
||||
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.bottom-d {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bottom-d-item {
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
|
||||
background-color: #ffffff;
|
||||
font-weight: bold;
|
||||
padding: 0 50px;
|
||||
> div {
|
||||
text-align: center;
|
||||
&:nth-child(1) {
|
||||
font-size: 18px;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
padding: 5px 0 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map-d {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 70px);
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
}
|
||||
</style>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { stServerUrl } from '/@/utils/http/stRequestToken/serverUrl';
|
||||
import { getStToken } from '/@/utils/http/stRequestToken';
|
||||
|
||||
export enum Api {
|
||||
userFoodEnergyInfo = '/foodNourishmentReport/getUserFoodEnergyInfo',
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const getUserFoodEnergyInfo = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.userFoodEnergyInfo,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '序号',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
customRender: ({ index }) => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '餐品名称',
|
||||
align: 'center',
|
||||
dataIndex: 'foodName',
|
||||
},
|
||||
{
|
||||
title: '取用量(克)',
|
||||
align: 'center',
|
||||
dataIndex: 'eatWeight',
|
||||
},
|
||||
{
|
||||
title: '热量(kcal)',
|
||||
align: 'center',
|
||||
dataIndex: 'energy',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" title="摄入食品详情" :footer="null" destroyOnClose :width="800">
|
||||
<a-descriptions style="padding: 0 10px">
|
||||
<a-descriptions-item label="姓名">{{ realName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="餐次">{{ dinnerType }}</a-descriptions-item>
|
||||
<a-descriptions-item label="用餐时间">{{ eatDate }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicTable } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { getUserFoodEnergyInfo } from './info.api';
|
||||
import { columns } from './info.data';
|
||||
|
||||
let userId = ref('');
|
||||
let realName = ref('');
|
||||
let dinnerType = ref('');
|
||||
let eatDate = ref('');
|
||||
const [registerModal] = useModalInner(async (data) => {
|
||||
if (data.record?.id) {
|
||||
realName.value = data.record.realname;
|
||||
userId.value = data.record.id;
|
||||
dinnerType.value = data.record.dinnerType;
|
||||
eatDate.value = data.record.statisticsDay;
|
||||
}
|
||||
});
|
||||
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: getUserFoodEnergyInfo,
|
||||
beforeFetch: (params) => {
|
||||
params.userId = unref(userId);
|
||||
params.dinnerType = unref(dinnerType);
|
||||
params.eatDate = unref(eatDate);
|
||||
},
|
||||
columns,
|
||||
maxHeight: 500,
|
||||
canResize: true,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
},
|
||||
});
|
||||
|
||||
// BasicTable绑定注册
|
||||
const [registerTable] = tableContext;
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.scrollbar__wrap) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
</style>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { stServerUrl } from '/@/utils/http/stRequestToken/serverUrl';
|
||||
import { getStToken } from '/@/utils/http/stRequestToken';
|
||||
|
||||
export enum Api {
|
||||
list = '/foodNourishmentReport/canteenInfoDevice',
|
||||
canteenDepartNameList = '/foodNourishmentReport/getCanteenDepartNameList',
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.list,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 部门
|
||||
* @param params
|
||||
*/
|
||||
export const getCanteenDepartNameList = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.canteenDepartNameList,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
<template>
|
||||
<div class="mapPage">
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<div id="maps"></div>
|
||||
|
||||
<div id="search">
|
||||
所属单位
|
||||
<a-select v-model:value="canteenId" placeholder="请选择单位" style="width: 260px">
|
||||
<a-select-option v-for="item in canteenIdList" :label="item.departName" :value="item.departId" :key="item.departId">
|
||||
{{ item['departName'] }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-button style="margin: 0 15px" type="primary" @click="getList">查询</a-button>
|
||||
<a-button style="background-color: #a4adb3; color: #ffffff" @click="reset">重置</a-button>
|
||||
</div>
|
||||
|
||||
<div id="total">
|
||||
<div>
|
||||
<div
|
||||
><span>{{ canteenNum }}</span
|
||||
>个</div
|
||||
>
|
||||
<div>营养监控食堂数量</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
><span>{{ deviceNum }}</span
|
||||
>台</div
|
||||
>
|
||||
<div>设备总数</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
><span>{{ normalNum }}</span
|
||||
>台</div
|
||||
>
|
||||
<div>设备正常运行数</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="timeService-nutrition-map" setup>
|
||||
import { nextTick, onMounted, ref } from 'vue';
|
||||
import mapKey from '/@/utils/mapKey';
|
||||
import AMapLoader from '@amap/amap-jsapi-loader';
|
||||
import { getCanteenDepartNameList, list } from './mapPage.api';
|
||||
import canteenIcon from '/@/assets/images/canteenIcon.png';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
const emit = defineEmits(['openInfo']);
|
||||
|
||||
const loading = ref<any>(true);
|
||||
const maps = ref<any>(null);
|
||||
let selfMap = null;
|
||||
const markerList = ref<any>([]);
|
||||
const canteenIdList = ref<any>([]);
|
||||
const canteenId = ref<any>(null);
|
||||
|
||||
const canteenNum = ref<any>(0);
|
||||
const deviceNum = ref<any>(0);
|
||||
const normalNum = ref<any>(0);
|
||||
|
||||
onMounted(() => {
|
||||
getCanteen();
|
||||
getList();
|
||||
});
|
||||
|
||||
const getCanteen = () => {
|
||||
let params = {
|
||||
orgCode: useUserStore()?.getUserInfo.orgCode,
|
||||
};
|
||||
getCanteenDepartNameList(params).then((res) => {
|
||||
canteenIdList.value = res;
|
||||
});
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
canteenId.value = null;
|
||||
getList();
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
loading.value = true;
|
||||
let params = {
|
||||
canteenId: canteenId.value,
|
||||
};
|
||||
list(params).then((res) => {
|
||||
let dinersVos: any = [];
|
||||
canteenNum.value = res.canteenNum;
|
||||
deviceNum.value = res.deviceNum;
|
||||
normalNum.value = res.normalNum;
|
||||
res.dinersVos.map((item) => {
|
||||
if (item.addressLongitude && item.addressLatitude) {
|
||||
dinersVos.push(item);
|
||||
}
|
||||
});
|
||||
markerList.value = dinersVos;
|
||||
loading.value = false;
|
||||
nextTick(() => {
|
||||
initMap();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const initMap = () => {
|
||||
AMapLoader.load({
|
||||
key: mapKey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.Geocoder', 'AMap.Geolocation'],
|
||||
})
|
||||
.then((AMap) => {
|
||||
selfMap = AMap;
|
||||
let lng: any = [];
|
||||
let lat: any = [];
|
||||
let center: any = null;
|
||||
if (markerList.value && markerList.value.length) {
|
||||
markerList.value.map((item) => {
|
||||
lng.push(Number(item.addressLongitude));
|
||||
lat.push(Number(item.addressLatitude));
|
||||
});
|
||||
if (markerList.value.length === 1) {
|
||||
center = [lng[0], lat[0]];
|
||||
} else {
|
||||
center = getCenter(
|
||||
lng.sort((a, b) => {
|
||||
return a - b;
|
||||
}),
|
||||
lat.sort((a, b) => {
|
||||
return a - b;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
maps.value = new AMap.Map('maps', {
|
||||
center: center,
|
||||
zoom: 9,
|
||||
viewMode: '3D',
|
||||
resizeEnable: true,
|
||||
pitchEnable: true,
|
||||
convert: true,
|
||||
});
|
||||
|
||||
const w = window as any;
|
||||
nextTick(() => {
|
||||
w.openInfoW = (canteenId: any) => {
|
||||
let data = markerList.value.filter((item) => {
|
||||
return item.info.canteenId == canteenId;
|
||||
});
|
||||
emit('openInfo', data[0].info);
|
||||
};
|
||||
});
|
||||
|
||||
maps.value.addControl(new AMap.ToolBar());
|
||||
maps.value.addControl(new AMap.Scale());
|
||||
|
||||
addMarkerList();
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
};
|
||||
|
||||
const addMarkerList = () => {
|
||||
if (markerList.value.length === 0) {
|
||||
return;
|
||||
} else {
|
||||
let marker: any;
|
||||
markerList.value = markerList.value.map((item) => {
|
||||
marker = new selfMap.Marker({
|
||||
position: new selfMap.LngLat(Number(item.addressLongitude), Number(item.addressLatitude)),
|
||||
icon: new selfMap.Icon({
|
||||
image: canteenIcon,
|
||||
size: new selfMap.Size(0, 0),
|
||||
imageSize: new selfMap.Size(0, 0),
|
||||
}),
|
||||
label: {
|
||||
content: `<div class="labelContent">
|
||||
<div class="restName">
|
||||
<img src="${canteenIcon}" style="height: 15px;width: 15px; margin-right: 3px" alt=""/>
|
||||
<div>${item.restName}</div>
|
||||
</div>
|
||||
<div id="Id${item.canteenId}" class="info">
|
||||
<div>营养监控人数:${item.eatPersonNum}</div>
|
||||
<div>营养监控设备:${item.deviceNum}</div>
|
||||
<div onclick="openInfoW(${item.canteenId})">查看营养监控设备></div>
|
||||
</div>
|
||||
</div>`,
|
||||
icon: null,
|
||||
offset: new selfMap.Pixel(0, 27),
|
||||
direction: 'top',
|
||||
},
|
||||
maxZoom: 8,
|
||||
});
|
||||
marker.info = item;
|
||||
marker.on('click', markerClick);
|
||||
return marker;
|
||||
});
|
||||
maps.value.add(markerList.value);
|
||||
}
|
||||
};
|
||||
|
||||
const getCenter = (lng, lat) => {
|
||||
let lngCenter = (lng[0] + lng[lng.length - 1]) / 2;
|
||||
let latCenter = (lat[0] + lat[lat.length - 1]) / 2;
|
||||
return [lngCenter, latCenter];
|
||||
};
|
||||
|
||||
const markerClick = (e) => {
|
||||
let times = new Date().getTime().toString();
|
||||
e.target.setzIndex(times.substring(times.length - 8, times.length));
|
||||
let idDom = document.getElementById('Id' + e.target.info.canteenId);
|
||||
if (idDom) {
|
||||
let s = idDom.style.display;
|
||||
idDom.style.display = s === 'block' ? 'none' : 'block';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mapPage {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 95px);
|
||||
top: 85px;
|
||||
|
||||
:deep(.ant-spin-nested-loading),
|
||||
:deep(.ant-spin-container) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
background-color: #ffffff;
|
||||
|
||||
#maps {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
:deep(.amap-marker-label) {
|
||||
border: none !important;
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
|
||||
:deep(.labelContent) {
|
||||
position: relative;
|
||||
|
||||
.restName {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
background-color: #58a55c;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 30px;
|
||||
padding: 12px 20px;
|
||||
border-radius: 3px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
|
||||
|
||||
> div {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-of-type {
|
||||
cursor: pointer;
|
||||
color: #1890ff;
|
||||
font-size: 12px;
|
||||
margin-bottom: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#search {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
border-radius: 3px;
|
||||
padding: 10px 20px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#total {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 900px;
|
||||
bottom: 30px;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-around;
|
||||
|
||||
> div {
|
||||
width: 200px;
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
height: 32px;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
span {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { stServerUrl } from '/@/utils/http/stRequestToken/serverUrl';
|
||||
import { getStToken } from '/@/utils/http/stRequestToken';
|
||||
|
||||
export enum Api {
|
||||
canteenInfo = '/foodNourishmentReport/userEatInfoByCanteenId',
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.canteenInfo,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '序号',
|
||||
align: 'center',
|
||||
dataIndex: 'index',
|
||||
width: 80,
|
||||
customRender: ({ index }): any => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '单位',
|
||||
align: 'left',
|
||||
width: 200,
|
||||
dataIndex: 'secondDepartName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
align: 'center',
|
||||
width: 200,
|
||||
dataIndex: 'thirdDepartName',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
align: 'center',
|
||||
dataIndex: 'realname',
|
||||
},
|
||||
{
|
||||
title: '工号',
|
||||
align: 'center',
|
||||
dataIndex: 'workNo',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
align: 'center',
|
||||
dataIndex: 'sex',
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
align: 'center',
|
||||
dataIndex: 'age',
|
||||
},
|
||||
{
|
||||
title: '身高(cm)',
|
||||
align: 'center',
|
||||
dataIndex: 'height',
|
||||
},
|
||||
{
|
||||
title: '体重(kg)',
|
||||
align: 'center',
|
||||
dataIndex: 'weight',
|
||||
},
|
||||
{
|
||||
title: 'BMI',
|
||||
align: 'center',
|
||||
dataIndex: 'bmi',
|
||||
},
|
||||
{
|
||||
title: '体力劳动',
|
||||
align: 'center',
|
||||
dataIndex: 'workStrength',
|
||||
},
|
||||
{
|
||||
title: '餐次总数量',
|
||||
align: 'center',
|
||||
dataIndex: 'dinnerTypeNum',
|
||||
},
|
||||
{
|
||||
title: '平均摄入数量(kcal)',
|
||||
align: 'center',
|
||||
dataIndex: 'energy',
|
||||
},
|
||||
];
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicModal v-bind="$attrs" title="查看营养监控数据" @register="registerModal" :width="1250" destroyOnClose :maskClosable="true" :footer="null">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #tableTitle>
|
||||
<a-descriptions :column="5" v-if="record">
|
||||
<a-descriptions-item label="食堂名称">{{ record.restName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="营养监控人数">{{ record.eatPersonNum }}</a-descriptions-item>
|
||||
<a-descriptions-item label="营养监控设备">{{ record.deviceNum }}</a-descriptions-item>
|
||||
<a-descriptions-item label="所属单位">{{ record.flatsName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="管理部门">{{ record.departName }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
|
||||
<meal-modal @register="registerMealModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { list } from './mapData.api';
|
||||
import { columns } from './mapData.data';
|
||||
import { BasicTable, TableAction} from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import MealModal from '../meal/meal.vue';
|
||||
|
||||
const record = ref<any>(null);
|
||||
|
||||
const [registerModal] = useModalInner(async (data) => {
|
||||
if (data.record) {
|
||||
record.value = data.record;
|
||||
}
|
||||
});
|
||||
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '营养监控数据',
|
||||
api: list,
|
||||
beforeFetch: (params) => {
|
||||
params.canteenId = record.value.canteenId;
|
||||
params.orgCode = useUserStore()?.getUserInfo.orgCode;
|
||||
},
|
||||
columns,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
clickToRowSelect: false,
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
title: '摄入记录',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable] = tableContext;
|
||||
const [registerMealModal, { openModal: openMealModal }] = useModal();
|
||||
|
||||
const openMeal = (record) => {
|
||||
openMealModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '摄入记录',
|
||||
onClick: openMeal.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { stServerUrl } from '/@/utils/http/stRequestToken/serverUrl';
|
||||
import { getStToken } from '/@/utils/http/stRequestToken';
|
||||
|
||||
export enum Api {
|
||||
userFoodEnergyInfo = '/foodNourishmentReport/getUserInfoAndEatNum',
|
||||
exportList = '/foodNourishmentReport/getUserInfoAndEatNum2/export',
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const getUserFoodEnergyInfo = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.userFoodEnergyInfo,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出接口
|
||||
* @param params
|
||||
*/
|
||||
export const exportList = async (params) => {
|
||||
const token = await getStToken({});
|
||||
return defHttp.get(
|
||||
{
|
||||
url: Api.exportList,
|
||||
params,
|
||||
headers: {
|
||||
'X-Access-Token': token,
|
||||
},
|
||||
responseType: 'blob',
|
||||
},
|
||||
{
|
||||
apiUrl: stServerUrl,
|
||||
withToken: false,
|
||||
isTransformResponse: false,
|
||||
}
|
||||
);
|
||||
};
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '序号',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
customRender: ({ index }) => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '用餐时间',
|
||||
align: 'center',
|
||||
dataIndex: 'statisticsDay',
|
||||
},
|
||||
{
|
||||
title: '用餐餐次',
|
||||
align: 'center',
|
||||
dataIndex: 'dinnerType',
|
||||
},
|
||||
{
|
||||
title: '摄入餐品数',
|
||||
align: 'center',
|
||||
dataIndex: 'foodNum',
|
||||
},
|
||||
{
|
||||
title: '摄入热量(kcal)',
|
||||
align: 'center',
|
||||
dataIndex: 'energy',
|
||||
},
|
||||
];
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: '用餐时间',
|
||||
field: 'days',
|
||||
component: 'RangeDate',
|
||||
componentProps: () => {
|
||||
return {
|
||||
showTime: false,
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
getPopupContainer: () => document.body,
|
||||
style: {
|
||||
width: '100%',
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" title="摄入记录" :footer="null" destroyOnClose :width="1200">
|
||||
<template v-if="record">
|
||||
<a-descriptions :column="6" style="padding: 0 10px">
|
||||
<a-descriptions-item label="姓名">{{ record.realname }}</a-descriptions-item>
|
||||
<a-descriptions-item label="性别">{{ record.sex }}</a-descriptions-item>
|
||||
<a-descriptions-item label="年龄">{{ record.age }}</a-descriptions-item>
|
||||
<a-descriptions-item label="工号">{{ record.workNo }}</a-descriptions-item>
|
||||
<a-descriptions-item label="所属单位">{{ record.secondDepartName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="所属部门">{{ record.thirdDepartName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="身高(cm)">{{ record.height }}</a-descriptions-item>
|
||||
<a-descriptions-item label="体重(kg)">{{ record.weight }}</a-descriptions-item>
|
||||
<a-descriptions-item label="BMI">{{ record.bmi }}</a-descriptions-item>
|
||||
<a-descriptions-item label="体力劳动">{{ record.workStrength }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</template>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="exportExcel">导出</a-button>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
|
||||
<info-modal @register="registerInfoModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicTable, TableAction} from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { BasicModal, useModal, useModalInner} from '/@/components/Modal';
|
||||
import InfoModal from '../info/info.vue';
|
||||
import { getUserFoodEnergyInfo, exportList } from './meal.api';
|
||||
import { columns, searchFormSchema } from './meal.data';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
let userId = ref('');
|
||||
let record = ref(null);
|
||||
const [registerModal] = useModalInner(async (data) => {
|
||||
if (data.record?.id) {
|
||||
userId.value = data.record.id;
|
||||
record.value = data.record;
|
||||
}
|
||||
});
|
||||
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: getUserFoodEnergyInfo,
|
||||
beforeFetch: (params) => {
|
||||
params.userId = unref(userId);
|
||||
},
|
||||
columns,
|
||||
maxHeight: 500,
|
||||
canResize: true,
|
||||
formConfig: {
|
||||
labelWidth: '70px',
|
||||
labelAlign: 'left',
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
fieldMapToTime: [['days', ['startDay', 'endDay'], 'YYYY-MM-DD']],
|
||||
},
|
||||
showTableSetting: false,
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
title: '食品详情',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// BasicTable绑定注册
|
||||
const [registerTable, { setLoading, getForm }] = tableContext;
|
||||
|
||||
const [registerInfoModal, { openModal: openInfoModal }] = useModal();
|
||||
|
||||
const exportExcel = () => {
|
||||
let { getFieldsValue } = getForm();
|
||||
setLoading(true);
|
||||
let params = {
|
||||
orgCode: useUserStore()?.getUserInfo.orgCode,
|
||||
userId: unref(userId),
|
||||
startDay: getFieldsValue().startDay,
|
||||
endDay: getFieldsValue().endDay,
|
||||
};
|
||||
exportList(params).then((res) => {
|
||||
setLoading(false);
|
||||
const url = window.URL.createObjectURL(new Blob([res]));
|
||||
const link = document.createElement('a');
|
||||
link.style.display = 'none';
|
||||
link.href = url;
|
||||
link.setAttribute('download', '摄入记录.xls');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
});
|
||||
};
|
||||
|
||||
const openInfo = (record) => {
|
||||
openInfoModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: '查看',
|
||||
onClick: openInfo.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.scrollbar__wrap) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="pageTitle">长庆油田营养监控食堂</div>
|
||||
|
||||
<map-page @openInfo="openInfo" />
|
||||
|
||||
<map-data @register="registerSearchModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="timeService-nutrition" setup>
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import MapPage from './components/map/mapPage.vue';
|
||||
import MapData from './components/mapData/mapData.vue';
|
||||
|
||||
const [registerSearchModal, { openModal: openSearchModal }] = useModal();
|
||||
|
||||
const openInfo = (record) => {
|
||||
openSearchModal(true, {
|
||||
record: record,
|
||||
isUpdate: true,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page {
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
|
||||
.pageTitle {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
font-size: 26px;
|
||||
line-height: 72px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" destroyOnClose @register="registerModal" title="监测数据" width="80%">
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<div style="width: 100%; padding: 0 20px 20px">
|
||||
<div class="top-info">
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 员工姓名:{{ infoData.bindRealName || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 员工编号:{{ infoData.workNo || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 工具编码:{{ infoData.watchNo || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 性别:{{ getName(infoData.sex, Dict.getDict('sex2')) || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 年龄:{{ infoData.age || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 单位:{{ infoData.userTwoOrgName || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 部门:{{ infoData.userThreeOrgName || '-' }} </div>
|
||||
<div style="margin-bottom: 10px; font-weight: bold"> 绑定日期:{{ infoData.bindDate }} </div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="0" tab="总览" />
|
||||
<a-tab-pane key="1" tab="心率" />
|
||||
<a-tab-pane key="2" tab="血氧" />
|
||||
<a-tab-pane key="3" tab="压力" />
|
||||
<a-tab-pane key="4" tab="睡眠" />
|
||||
<a-tab-pane key="5" tab="体温" />
|
||||
<a-tab-pane key="6" tab="锻炼" />
|
||||
<a-tab-pane key="7" tab="步数" />
|
||||
</a-tabs>
|
||||
<div style="height: 60vh; overflow: auto">
|
||||
<all-look
|
||||
@change-params-date="changeParamsDate"
|
||||
v-if="activeKey === '0'"
|
||||
:info-data="info"
|
||||
:userId="infoData.bindUserId"
|
||||
class="tabs-d"
|
||||
/>
|
||||
<heart-rate v-if="activeKey === '1'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<blood-oxygen v-if="activeKey === '2'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<pressure v-if="activeKey === '3'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<sleep v-if="activeKey === '4'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<temperature v-if="activeKey === '5'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<motion v-if="activeKey === '6'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
<step-number v-if="activeKey === '7'" :userId="infoData.bindUserId" class="tabs-d" :keyType="activeKey" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { ref } from 'vue';
|
||||
import AllLook from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/allLook.vue';
|
||||
import HeartRate from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/heartRate.vue';
|
||||
import BloodOxygen from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/bloodOxygen.vue';
|
||||
import Pressure from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/pressure.vue';
|
||||
import Sleep from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/sleep.vue';
|
||||
import Temperature from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/temperature.vue';
|
||||
import Motion from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/motion.vue';
|
||||
import StepNumber from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/componets/stepNumber.vue';
|
||||
import { bindInfoByUserApi, queryAllStatisticsApi } from '/@/views/healthMonitor/healMonitorManage/monitorToll/userInfo/userInfo.api';
|
||||
import { getName } from '/@/views/interveneNew/compoents/utils';
|
||||
import { Dict } from '/@/utils/cache/dict';
|
||||
|
||||
const activeKey = ref('0');
|
||||
const infoData = ref({});
|
||||
const paramsDate = ref('0');
|
||||
const info = ref({});
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
infoData.value = {};
|
||||
activeKey.value = '0';
|
||||
paramsDate.value = '0';
|
||||
info.value = {};
|
||||
setModalProps({ footer: false });
|
||||
let result: any;
|
||||
try {
|
||||
result = await bindInfoByUserApi({ userId: data.record.bindUserId });
|
||||
} catch {}
|
||||
infoData.value = { ...data.record, ...{ bindDate: result ? result?.bindDate : '' } };
|
||||
await getInfo();
|
||||
});
|
||||
|
||||
async function changeParamsDate(v) {
|
||||
paramsDate.value = v;
|
||||
await getInfo();
|
||||
}
|
||||
|
||||
async function getInfo() {
|
||||
await queryAllStatisticsApi({ type: paramsDate.value, userId: infoData.value.bindUserId }).then((res) => {
|
||||
info.value = res;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
:deep(.ant-tabs-nav-wrap) {
|
||||
justify-content: center;
|
||||
}
|
||||
:deep(.ant-tabs-top > .ant-tabs-nav::before, .ant-tabs-top > div > .ant-tabs-nav::before) {
|
||||
display: none;
|
||||
}
|
||||
:deep(.ant-tabs-tab + .ant-tabs-tab) {
|
||||
margin-left: calc(100% / 14);
|
||||
}
|
||||
:deep(.ant-tabs-nav-list) {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
.tabs-d {
|
||||
padding: 20px;
|
||||
}
|
||||
.top-info {
|
||||
flex-wrap: wrap;
|
||||
border-bottom: 1px dashed #cecece;
|
||||
display: flex;
|
||||
> div {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" title="服务数据" width="80%">
|
||||
<div class="top-d-outer">
|
||||
<div class="top-d">
|
||||
<div>所属单位:{{ wearInfo?.departName || '-' }}</div>
|
||||
<div>设备数量:{{ wearInfo?.total }}</div>
|
||||
<div>配发人数:{{ wearInfo?.distribution }}</div>
|
||||
<div>设备正常运行数量:{{ wearInfo?.normal }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BasicTable @register="registerTable" table-type="1">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'dataInfo'">
|
||||
<a-button v-if="record?.bindUserId" type="link" @click="lookDataInfo(record)">监测数据</a-button>
|
||||
<template v-else>-</template>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
<user-info-modal @register="registerModal1" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { useModal, useModalInner } from '/@/components/Modal';
|
||||
import { ref } from 'vue';
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { deviceListApi } from '/@/views/archivesManage/institution/timeService/wear/wear.api';
|
||||
import { columns } from '/@/views/archivesManage/institution/timeService/wear/wear.data';
|
||||
import UserInfoModal from '/@/views/archivesManage/institution/timeService/wear/components/userInfoModal.vue';
|
||||
|
||||
const wearInfo = ref({});
|
||||
const [registerModal1, { openModal }] = useModal();
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
setModalProps({ showCancelBtn: false, showOkBtn: false });
|
||||
wearInfo.value = data.record;
|
||||
setProps({ searchInfo: { deptId: data?.record?.deptId } });
|
||||
await reload({ page: 1 });
|
||||
});
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: deviceListApi,
|
||||
columns,
|
||||
canResize: false,
|
||||
orderFlag: false,
|
||||
immediate: false,
|
||||
showIndexColumn: true,
|
||||
useSearchForm: false,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload, setProps }] = tableContext;
|
||||
|
||||
function lookDataInfo(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.top-d-outer {
|
||||
padding: 10px;
|
||||
.top-d {
|
||||
border-bottom: 1px dashed #cecece;
|
||||
display: flex;
|
||||
padding: 0 0 10px;
|
||||
> div {
|
||||
margin-right: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/health-watch/archives/watch/device/page',
|
||||
deviceList = '/health-watch/watch/watchDevice/list',
|
||||
}
|
||||
|
||||
export const listApi = (params: any) => defHttp.get({ url: Api.list, params }, { isTransformResponse: false });
|
||||
export const deviceListApi = (params: any) => defHttp.get({ url: Api.deviceList, params });
|
||||
@@ -0,0 +1,68 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '工具编码',
|
||||
dataIndex: 'watchNo',
|
||||
},
|
||||
{
|
||||
title: '归属单位',
|
||||
dataIndex: 'departmentName',
|
||||
},
|
||||
{
|
||||
title: '入库日期',
|
||||
dataIndex: 'createDate',
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
title: '绑定状态',
|
||||
dataIndex: 'watchStatus',
|
||||
customRender: ({ text }) => {
|
||||
switch (text) {
|
||||
case '0':
|
||||
return '未绑定';
|
||||
case '1':
|
||||
return '已绑定';
|
||||
default:
|
||||
return;
|
||||
}
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '绑定员工',
|
||||
dataIndex: 'bindRealName',
|
||||
customRender: ({ text }) => {
|
||||
return text || '-';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '员工编号',
|
||||
dataIndex: 'workNo',
|
||||
customRender: ({ text }) => {
|
||||
return text || '-';
|
||||
},
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '员工所属部门',
|
||||
dataIndex: 'userThreeOrgName',
|
||||
customRender: ({ text }) => {
|
||||
return text || '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '绑定日期',
|
||||
dataIndex: 'bindDate',
|
||||
customRender: ({ text }) => {
|
||||
return text || '-';
|
||||
},
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
title: '监测数据',
|
||||
dataIndex: 'dataInfo',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-title"> 长庆油田穿戴设备 </div>
|
||||
<div class="map-d">
|
||||
<template v-if="!loading">
|
||||
<service-map
|
||||
ref="serviceMap"
|
||||
:map-list="mapList"
|
||||
@get-marker-info="getMarkerInfo"
|
||||
:label-content="labelContent"
|
||||
:marker-content="markerContent"
|
||||
@get-detail="getDetail"
|
||||
field="departName"
|
||||
id="departCode"
|
||||
/>
|
||||
<div class="search-d">
|
||||
所属单位
|
||||
<ApiSelect
|
||||
:value="orgCode"
|
||||
:api="allSecondaryDepartsNew"
|
||||
@change="
|
||||
(v) => {
|
||||
orgCode = v;
|
||||
}
|
||||
"
|
||||
resultField="result"
|
||||
labelField="departName"
|
||||
valueField="orgCode"
|
||||
:after-fetch="
|
||||
(data) => {
|
||||
data.unshift({
|
||||
orgCode: '1',
|
||||
departName: '全部单位',
|
||||
});
|
||||
return data;
|
||||
}
|
||||
"
|
||||
:allowClear="true"
|
||||
:show-default-value="false"
|
||||
:immediate="true"
|
||||
:showSearch="true"
|
||||
:filterOption="
|
||||
(input: string, option: any): boolean => {
|
||||
const str: string = input.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
}"
|
||||
style="width: 260px"
|
||||
/>
|
||||
<a-button type="primary" @click="searchB">查询</a-button>
|
||||
<a-button style="background-color: #a4adb3; color: #ffffff" @click="resetB">重置</a-button>
|
||||
</div>
|
||||
|
||||
<div class="bottom-d">
|
||||
<div
|
||||
class="bottom-d-item"
|
||||
v-for="(item, index) in wearInfo"
|
||||
:key="`bottom-d-item-${index}`"
|
||||
:style="{ margin: index === 1 ? '0 25px 0 50px' : index === 2 ? '0 50px 0 25px' : 0 }"
|
||||
>
|
||||
<div>{{ item.value }}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<wear-modal @register="registerModal" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ServiceMap from '/@/views/archivesManage/institution/timeService/components/serviceMap.vue';
|
||||
import { nextTick, onMounted, ref, onBeforeUnmount } from 'vue';
|
||||
import { allSecondaryDepartsNew } from '/@/utils/orgSearchInfo';
|
||||
import ApiSelect from '/@/components/Form/src/components/ApiSelect.vue';
|
||||
import { listApi } from '/@/views/archivesManage/institution/timeService/wear/wear.api';
|
||||
import WearModal from '/@/views/archivesManage/institution/timeService/wear/components/wearModal.vue';
|
||||
import watch from '/@/assets/images/watch.png';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
const loading = ref(true);
|
||||
const serviceMap = ref();
|
||||
const mapList = ref();
|
||||
const orgCode = ref('1');
|
||||
const wearInfo = ref<any[]>([]);
|
||||
const markerContent = ref(`<div style="white-space: nowrap;display: flex;background-color: #58a55c;padding: 5px 10px;border-radius: 10px;
|
||||
align-items: center;">
|
||||
<img src="${watch}" alt="" style="width: 20px;height: 20px; margin-right: 5px"/>
|
||||
<span style="color: #ffffff">^&</span>
|
||||
</div>`);
|
||||
const labelContent = ref('');
|
||||
|
||||
onMounted(async () => {
|
||||
await initList();
|
||||
loading.value = false;
|
||||
await nextTick(() => {
|
||||
serviceMap.value.initMap(mapList.value);
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
serviceMap.value.destroyMap();
|
||||
});
|
||||
|
||||
async function initList() {
|
||||
try {
|
||||
const { code, result, total, distribution, wear, normal } = await listApi({ orgCode: orgCode.value === '1' ? '' : orgCode.value });
|
||||
if (code === 200) {
|
||||
mapList.value = result;
|
||||
wearInfo.value = [
|
||||
{ value: total, name: '穿戴设备总数' },
|
||||
{ value: distribution, name: '穿戴设备配发人数' },
|
||||
{ value: wear, name: '佩带人数' },
|
||||
{ value: normal, name: '运行正常设备数' },
|
||||
];
|
||||
}
|
||||
} catch (e) {
|
||||
mapList.value = [];
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkerInfo(e) {
|
||||
labelContent.value = `
|
||||
<div style="padding: 10px;background-color: #ffffff;border-radius: 10px">
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">所属单位:${e.departName || '-'} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">设备数量:${e.total} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">配发人数:${e.distribution} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">佩戴人数:${e.wear} </div>
|
||||
<div style="padding-top: 8px;font-weight: bold;font-size: 14px">设备运行正常数量:${e.normal} </div>
|
||||
<div style="padding-top: 8px;text-align: center;color: #5087ec" onclick="getDetail()">查看设备数据></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
serviceMap.value.setLabel(labelContent.value);
|
||||
}
|
||||
async function searchB() {
|
||||
await initList();
|
||||
}
|
||||
async function resetB() {
|
||||
orgCode.value = '1';
|
||||
await searchB();
|
||||
}
|
||||
|
||||
function getDetail(e) {
|
||||
openModal(true, {
|
||||
record: e,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-d {
|
||||
box-shadow: 2px 2px 0 0 rgba(0, 0, 0, 0.35);
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 99;
|
||||
> :nth-child(n + 1) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.bottom-d {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bottom-d-item {
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.35);
|
||||
background-color: #ffffff;
|
||||
font-weight: bold;
|
||||
padding: 0 50px;
|
||||
> div {
|
||||
text-align: center;
|
||||
&:nth-child(1) {
|
||||
font-size: 18px;
|
||||
padding: 10px 0 5px 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
padding: 5px 0 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map-d {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 70px);
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user