This commit is contained in:
dzc committed 2026-06-30 19:11:19 +08:00
1 parent 866a11277e
commit 07df08e847
11 files changed
+557 -97

No files matched your search

+42 -31
View File
@@ -1,70 +1,81 @@
import request from "/@/utils/request"
import request from "/@/utils/request";
/* start 人闸统计 start */
/* start 车闸统计 start */
export function beLateRecordPage(data: any) {
return request({
url: "/admin/car/total/be-late-page",
method: "post",
params: {
current: data.current,
size: data.size,
},
data,
});
}
export function totalPage(params: any) {
return request({
url: '/admin/car/total/page',
method: 'get',
url: "/admin/car/total/page",
method: "get",
params,
})
});
}
// 军车出车次数(根据时间类型)
export function armyCarCountByDateType(data: any) {
return request({
url: '/admin/car/total/army-car-count-by-date-type',
method: 'post',
url: "/admin/car/total/army-car-count-by-date-type",
method: "post",
data,
})
});
}
/* end 人闸统计 end */
export function dataCleaning(data?: Object) {
return request({
url: '/admin/car/carRecord/data-cleaning',
method: 'post',
url: "/admin/car/carRecord/data-cleaning",
method: "post",
data,
})
});
}
export function fetchList(query?: Object) {
return request({
url: '/admin/car/carRecord/page',
method: 'get',
params: query
})
url: "/admin/car/carRecord/page",
method: "get",
params: query,
});
}
export function addObj(obj?: Object) {
return request({
url: '/admin/car/carRecord',
method: 'post',
data: obj
})
url: "/admin/car/carRecord",
method: "post",
data: obj,
});
}
export function getObj(id?: string) {
return request({
url: '/admin/car/carRecord/' + id,
method: 'get'
})
url: "/admin/car/carRecord/" + id,
method: "get",
});
}
export function delObjs(ids?: Object) {
return request({
url: '/admin/car/carRecord',
method: 'delete',
data: ids
})
url: "/admin/car/carRecord",
method: "delete",
data: ids,
});
}
export function putObj(obj?: Object) {
return request({
url: '/admin/car/carRecord',
method: 'put',
data: obj
})
url: "/admin/car/carRecord",
method: "put",
data: obj,
});
}
+59 -26
View File
@@ -1,14 +1,8 @@
<template>
<div class="flex flex-col border border-br" :style="styles">
<Toolbar class="border-b border-br" :editor="editorRef" :mode="mode" />
<Editor
class="flex-1 overflow-y-auto"
:mode="mode"
:defaultConfig="state.editorConfig"
v-model="state.editorVal"
@onCreated="handleCreated"
@onChange="handleChange"
/>
<Editor class="flex-1 overflow-y-auto" :mode="mode" :defaultConfig="state.editorConfig"
v-model="state.editorVal" @onCreated="handleCreated" @onChange="handleChange" />
</div>
</template>
@@ -18,9 +12,18 @@ import { reactive, shallowRef, watch, onBeforeUnmount, CSSProperties } from 'vue
// @ts-ignore
import { IDomEditor } from '@wangeditor/editor';
import { Toolbar, Editor } from '@wangeditor/editor-for-vue';
import request from '/@/utils/request';
import { useMessage } from '/@/hooks/message';
import { Session } from '/@/utils/storage';
import other from '/@/utils/other';
const { proxy } = getCurrentInstance();
type ImageInsertFn = (src: string) => void;
type VideoInsertFn = (src: string, poster: string) => void;
const proxy = getCurrentInstance()?.proxy as { baseURL?: string } | null;
const baseURL = proxy?.baseURL || '';
const message = useMessage();
const VIDEO_MAX_SIZE = 10 * 1024 * 1024;
const VIDEO_MAX_SIZE_TEXT = '10MB';
// 定义父组件传过来的值
const props = defineProps({
@@ -71,13 +74,43 @@ const headers = computed(() => {
};
});
// 定义上传需要的字段信息
const uploadAttr = reactive({
// 定义图片上传需要的字段信息
const uploadImageAttr = reactive({
fieldName: 'file',
server: proxy.baseURL + props.uploadFileUrl,
server: baseURL + props.uploadFileUrl,
headers: headers,
customInsert(res, insertFn) {
insertFn(proxy.baseURL + res.data.url);
customInsert(res: any, insertFn: ImageInsertFn) {
insertFn(baseURL + res.data.url);
},
});
// 定义视频上传需要的字段信息
const uploadVideoAttr = reactive({
fieldName: 'file',
server: baseURL + props.uploadFileUrl,
headers: headers,
maxFileSize: VIDEO_MAX_SIZE,
async customUpload(file: File, insertFn: VideoInsertFn) {
if (file.size > VIDEO_MAX_SIZE) {
message.warning(`上传视频大小不能超过 ${VIDEO_MAX_SIZE_TEXT}`);
return;
}
const formData = new FormData();
formData.append('file', file);
try {
const res = await request({
url: props.uploadFileUrl,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
'Enc-Flag': 'false',
},
data: formData,
});
insertFn(baseURL + res.data.url, '');
} catch (error: any) {
message.error(error?.msg || '视频上传失败');
}
},
});
@@ -86,8 +119,8 @@ const state = reactive({
editorConfig: {
placeholder: props.placeholder,
MENU_CONF: {
uploadImage: uploadAttr,
uploadVideo: uploadAttr,
uploadImage: uploadImageAttr,
uploadVideo: uploadVideoAttr,
},
},
editorVal: props.getHtml,
@@ -96,7 +129,7 @@ const state = reactive({
const styles = computed<CSSProperties>(() => ({
height: other.addUnit(props.height),
width: other.addUnit(props.width),
'z-index': 1000,
'z-index': 1000,
}));
// 编辑器回调函数
@@ -114,18 +147,18 @@ const handleChange = (editor: IDomEditor) => {
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
emit('update:getHtml', '');
emit('update:getText', '');
editor.destroy();
emit('update:getHtml', '');
emit('update:getText', '');
editor.destroy();
});
// 监听是否禁用改变
onMounted(() =>{
nextTick(()=>{
const editor = editorRef.value;
if (editor == null) return;
props.disable ? editor.disable() : editor.enable();
})
onMounted(() => {
nextTick(() => {
const editor = editorRef.value;
if (editor == null) return;
props.disable ? editor.disable() : editor.enable();
})
})
// 监听双向绑定值改变,用于回显
+194
View File
@@ -0,0 +1,194 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-row shadow="hover" v-show="showSearch" class="ml10">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item style="width: 250px;" label="类型" prop="alarmTypeList">
<dict-select v-model="state.queryForm.alarmTypeList" :options="dk_type" multiple
placeholder="请选择类型" />
</el-form-item>
<el-form-item style="width: 450px;" label="时间" prop="capTimeList">
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<right-toolbar v-model:showSearch="showSearch" :export="false" @exportExcel="exportExcel"
class="ml10 mr20" style="float: right;" @queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle" @selection-change="selectionChangHandle"
@sort-change="sortChangeHandle">
<el-table-column type="selection" width="80" align="center" />
<el-table-column type="index" label="#" width="80" />
<el-table-column min-width="100" label="人员车辆信息">
<el-table-column prop="personId" min-width="180" label="车牌号">
<template #default="{ row }">
<span v-if="row.carNumbers">{{ row.carNumbers }}</span>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
<el-table-column prop="personId" min-width="100" label="人员编号">
<template #default="{ row }">
<span v-if="row.personId">{{ row.personId }}</span>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
<el-table-column prop="personName" min-width="100" label="姓名">
<template #default="{ row }">
<span v-if="row.personName">{{ row.personName }}</span>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
<el-table-column prop="deptName" min-width="100" label="部门名称">
<template #default="{ row }">
<span v-if="row.deptName">{{ row.deptName }}</span>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column min-width="100" label="统计">
<el-table-column min-width="100" label="打卡次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.reignCount ?? 0 }}</span>
<span>次</span>
</div>
</template>
</el-table-column>
<el-table-column min-width="100" label="异常进入次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.earlyCount ?? 0 }}</span>
<span>次</span>
</div>
</template>
</el-table-column>
<el-table-column min-width="100" label="异常外出次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.lateCount ?? 0 }}</span>
<span>次</span>
</div>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button icon="InfoFilled" text type="primary" @click="openCarTableDialogRef(row)">
详情
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination" />
</div>
<car-table-dialog ref="carTableDialogRef" />
</div>
</template>
<script setup lang="ts" name="carReignRecord">
import { BasicTableProps, useTable } from "/@/hooks/table";
import * as doorRecordApi from "/@/api/door/doorRecord";
import { useDict } from '/@/hooks/dict';
import { usePanel } from "/@/stores/panel"
import { getDefaultAlarmDateList } from "/@/utils/other"
import * as carRecordApi from "/@/api/car/carRecord"
// 引入组件
const CarTableDialog = defineAsyncComponent(() => import("../components/carTableDialog.vue"));
// 定义查询字典
const { dk_type } = useDict("dk_type")
const storesPanel = usePanel()
const queryRef = ref()
const showSearch = ref(true)
const carTableDialogRef = ref<any>(null)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: { capTimeList: getDefaultAlarmDateList() },
pageList: carRecordApi.beLateRecordPage,
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
getDataList()
}
onBeforeMount(() => {
const query: any = useRoute().query
if (query && query.action == 'panel') {
if (query.params) {
Object.assign(state.queryForm, JSON.parse(query.params))
getDataList()
}
storesPanel.openFromPanel()
}
if (query && query.params) {
Object.assign(state.queryForm, JSON.parse(query.params))
getDataList()
}
})
onBeforeUnmount(() => {
const query = useRoute().query
if (query && query.action == 'panel') {
storesPanel.closeFromPanel()
}
})
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
selectObjs.value = objs.map(({ id }) => id);
multiple.value = !objs.length;
};
function openCarTableDialogRef(row: any) {
const query: any = {
personName: row.personName,
alarmTypeList: state.queryForm.alarmTypeList,
}
if (state.queryForm.capTimeList) {
query.capTimeList = [state.queryForm.capTimeList[0], state.queryForm.capTimeList[1]]
}
carTableDialogRef.value.openDialog(query)
}
// 导出excel
const exportExcel = () => {
downBlobFile('/car/carRecord/export', Object.assign(state.queryForm, { ids: selectObjs }), 'carRecord.xlsx')
}
</script>
+173
View File
@@ -0,0 +1,173 @@
<!-- 车辆出入次数统计详情 -->
<template>
<el-dialog title="车辆进出详情" v-model="visible" width="85%" :close-on-click-modal="false" draggable>
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-row shadow="hover" class="ml10">
<el-form-item style="width: 150px;" label="姓名" prop="personName">
<el-input v-model="state.queryForm.personName" placeholder="请输入人员姓名" />
</el-form-item>
<el-form-item style="width: 250px;" label="类型" prop="alarmTypeList">
<dict-select v-model="state.queryForm.alarmTypeList" :options="dk_type" multiple
placeholder="请选择类型" />
</el-form-item>
<el-form-item v-if="false" style="width: 250px;" label="进出门类型" prop="carDirect">
<dict-select v-model="state.queryForm.carDirect" :options="dh_car_direct" placeholder="请选择进出门类型" />
</el-form-item>
<el-form-item style="width: 350px;" label="抓拍时间" prop="capTimeList">
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD HH:mm:ss"
type="daterange" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
<el-table :data="state.dataList" v-loading="state.loading" height="50vh" border
:cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle.headerCellStyle"
@sort-change="sortChangeHandle">
<el-table-column prop="capTime" label="抓拍时间" min-width="180" />
<el-table-column prop="personCode" min-width="120" label="异常出入类型">
<template #default="{ row }">
<div v-if="row.alarmDkList" class="flex items-center justify-start gap-2"
v-for="(v) in row.alarmDkList">
<el-tag v-if="v == '1'" type="danger">异常进入</el-tag>
<el-tag v-else-if="v == '2'" type="danger">异常外出</el-tag>
</div>
<el-tag v-else type="success">无异常</el-tag>
</template>
</el-table-column>
<el-table-column label="车辆信息">
<el-table-column prop="carDirect" width="120" label="行车方向">
<template #default="{ row }">
<dict-tag :options="dh_car_direct" :value="row.carDirect" />
</template>
</el-table-column>
<el-table-column prop="carColor" width="120" label="车辆颜色">
<template #default="{ row }">
<dict-tag :options="dh_car_color" :value="row.carColor" />
</template>
</el-table-column>
<el-table-column prop="carInnerCategory" width="120" label="车辆类型">
<template #default="{ row }">
<dict-tag :options="dh_car_inner_category" :value="row.carInnerCategory" />
</template>
</el-table-column>
<el-table-column prop="carNum" width="200" label="车牌号码">
<template #default="{ row }">
<div class="flex items-center gap-2">
<dict-tag v-if="row.carNumColor" :options="dh_car_num_color"
:value="row.carNumColor" />
<el-tag v-else type="danger">未知</el-tag>
<span v-if="row.carNum">{{ row.carNum }}</span>
<span v-else class="color-danger">未知</span>
</div>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="人员信息">
<el-table-column prop="ownerName" width="120" label="人员">
<template #default="{ row }">
<div v-if="row.ownerName">
<span>{{ row.ownerName }}</span>
</div>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
<el-table-column prop="userPhone" width="120" label="手机号">
<template #default="{ row }">
<div v-if="row.userPhone">
<span>{{ row.userPhone }}</span>
</div>
<span v-else class="color-danger">未知</span>
</template>
</el-table-column>
<el-table-column label="抓拍相机">
<el-table-column prop="devId" min-width="100" label="设备编码" />
<el-table-column prop="devName" min-width="100" label="设备名称" show-overflow-tooltip />
<el-table-column prop="devChnId" min-width="150" label="通道编码" />
<el-table-column prop="devChnName" min-width="100" label="通道名称" show-overflow-tooltip />
</el-table-column>
<el-table-column label="抓拍图片">
<el-table-column min-width="100" label="抓拍图片">
<template #default="{ row }">
<preview-image width="50px" height="50px" v-if="row.parseCarImgUrl"
:src="row.parseCarImgUrl" />
</template>
</el-table-column>
<el-table-column min-width="100" label="车牌图片">
<template #default="{ row }">
<preview-image width="50px" height="50px" v-if="row.parseCarNumPic"
:src="row.parseCarNumPic" />
</template>
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination" />
</el-row>
</el-form>
</el-dialog>
</template>
<script setup lang="ts" name="doorTimesTableDialog">
import { BasicTableProps, useTable } from "/@/hooks/table";
import { useDict } from '/@/hooks/dict';
import { parseTime } from "/@/utils/formatTime"
import * as CarRecordApi from "/@/api/car/carRecord";
defineExpose({
openDialog
});
// 定义查询字典
const { dh_car_color, dh_car_inner_category, dh_car_num_color, dh_car_direct, yes_no_type, dk_type } = useDict("dh_car_color", "dh_car_inner_category", "dh_car_num_color", "dh_car_direct", "yes_no_type", "dk_type")
// 搜索变量
const queryRef = ref()
// 定义变量内容
const visible = ref(false)
const state: BasicTableProps = reactive<BasicTableProps>({
createdIsNeed: false,
pagination: {
size: 10,
},
queryForm: {
},
pageList: CarRecordApi.fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
getDataList()
}
// 打开弹窗
function openDialog(query: any) {
state.queryForm = query
state.queryForm.isDkErrorList = true
state.queryForm.allFindAlarmTypeList = true
visible.value = true
getDataList();
}
</script>
+10 -10
View File
@@ -35,17 +35,17 @@
:cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle.headerCellStyle"
@sort-change="sortChangeHandle">
<el-table-column prop="swingTime" label="抓拍时间" min-width="180" />
<el-table-column prop="personCode" min-width="120" label="异常出入类型">
<template #default="{ row }">
<div v-if="row.alarmDkList" class="flex items-center justify-start gap-2"
v-for="(v) in row.alarmDkList">
<el-tag v-if="v == '1'" type="danger">异常进入</el-tag>
<el-tag v-else-if="v == '2'" type="danger">异常外出</el-tag>
</div>
<el-tag v-else type="success">无异常</el-tag>
</template>
</el-table-column>
<el-table-column min-width="100" label="人员">
<el-table-column prop="personCode" min-width="120" label="异常出入类型">
<template #default="{ row }">
<div v-if="row.alarmDkList" class="flex items-center justify-start gap-2"
v-for="(v) in row.alarmDkList">
<el-tag v-if="v == '1'" type="danger">异常进入</el-tag>
<el-tag v-else-if="v == '2'" type="danger">异常外出</el-tag>
</div>
<el-tag v-else type="success">无异常</el-tag>
</template>
</el-table-column>
<el-table-column prop="personCode" min-width="100" label="人员编号">
<template #default="{ row }">
<span v-if="row.personCode">{{ row.personCode }}</span>
+17
View File
@@ -144,6 +144,23 @@
<dict-tag :options="dh_door_open_type" :value="row.openType" />
</template>
</el-table-column>
<el-table-column label="抓拍相机">
<el-table-column prop="deviceCode" min-width="100" label="设备编码" />
<el-table-column prop="deviceName" min-width="100" label="设备名称" show-overflow-tooltip />
<el-table-column prop="channelCode" min-width="150" label="通道编码" />
<el-table-column prop="channelName" min-width="100" label="通道名称" show-overflow-tooltip />
</el-table-column>
<el-table-column prop="openResult" min-width="100" label="开门结果">
<template #default="{ row }">
<el-tag v-if="row.openResult == 1" type="success">成功</el-tag>
<el-tag v-if="row.openResult == 0" type="danger">失败</el-tag>
</template>
</el-table-column>
<el-table-column prop="openType" label="开门类型" min-width="150">
<template #default="{ row }">
<dict-tag :options="dh_door_open_type" :value="row.openType" />
</template>
</el-table-column>
<el-table-column label="抓图图片" min-width="100">
<template #default="{ row }">
<preview-image width="50px" height="50px" v-if="row.parseRecordImage"
-1
View File
@@ -88,7 +88,6 @@
</template>
</el-table-column>
</el-table-column>
<el-table-column min-width="100" label="卡">
<el-table-column prop="cardType" min-width="100" label="卡类型">
<template #default="{ row }">
+36 -18
View File
@@ -37,34 +37,40 @@
<el-table-column min-width="100" align="center" label="出勤人数">
<el-table-column prop="reignCount" min-width="100" align="center" label="人闸识别">
<template #default="{ row }">
<div class="color-success">
<div class="success-count color-success" @click="openDoorTableDialogRef(row)">
<span> {{ row.reignCount ?? 0 }}</span>
<span>次</span>
<span>人</span>
<span v-if="row.reignCount" style="font-size: 12px; margin-left: 4px; opacity: 0.8;">
(点击查看)
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="carReignCount" min-width="100" align="center" label="道闸识别">
<template #default="{ row }">
<div class="color-success">
<div class="success-count color-success" @click="openCarTableDialogRef(row)">
<span> {{ row.carReignCount ?? 0 }}</span>
<span>次</span>
<span>人</span>
<span v-if="row.carReignCount" style="font-size: 12px; margin-left: 4px; opacity: 0.8;">
(点击查看)
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="totalReignCount" min-width="100" align="center" label="总识别数">
<el-table-column prop="totalReignCount" min-width="100" align="center" label="总识别人数">
<template #default="{ row }">
<div class="color-success">
<span> {{ row.totalReignCount ?? 0 }}</span>
<span>次</span>
<span>人</span>
</div>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="notReignCount" min-width="100" align="center" label="未出勤人数">
<template #default="{ row }">
<div class="not-reign-count color-danger" @click="doNotReignCount(row)">
<div class="danger-count color-danger" @click="doNotReignCount(row)">
<span> {{ row.notReignCount ?? 0 }}</span>
<span>次</span>
<span>人</span>
<span v-if="row.notReignCount" style="font-size: 12px; margin-left: 4px; opacity: 0.8;">
(点击查看)
</span>
@@ -75,7 +81,7 @@
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.lateCount }}</span>
<span>次</span>
<span>人</span>
</div>
</template>
</el-table-column>
@@ -83,17 +89,10 @@
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.earlyCount }}</span>
<span>次</span>
<span>人</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button icon="InfoFilled" text type="primary" @click="openDoorTableDialogRef(row)">
详情
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<door-table-dialog ref="doorTableDialogRef" />
@@ -195,6 +194,13 @@ function openDoorTableDialogRef(row: any) {
push({ path: "/door/doorReignRecord/index", query: { params: JSON.stringify(_params) } })
}
function openCarTableDialogRef(row: any) {
const _params = {
capTimeList: [row.time + " 00:00:00", addDays(row.time, 1) + " 00:00:00"],
}
push({ path: "/car/carReignRecord/index", query: { params: JSON.stringify(_params) } })
}
function addDays(dateStr: string, days: number) {
const date = new Date(dateStr);
date.setDate(date.getDate() + days);
@@ -203,7 +209,7 @@ function addDays(dateStr: string, days: number) {
</script>
<style lang="scss" scoped>
.not-reign-count {
.danger-count {
cursor: pointer;
display: inline-block;
transition: transform 0.2s ease-in-out;
@@ -214,4 +220,16 @@ function addDays(dateStr: string, days: number) {
transform: scale(1.1);
}
}
.success-count {
cursor: pointer;
display: inline-block;
transition: transform 0.2s ease-in-out;
&:hover {
text-decoration: underline;
text-decoration-color: var(--el-color-success);
transform: scale(1.1);
}
}
</style>
+6 -3
View File
@@ -3,6 +3,9 @@
<div class="layout-padding-auto layout-padding-view">
<el-row shadow="hover" v-show="showSearch" class="ml10">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item style="width: 250px;" label="姓名" prop="personName">
<el-input v-model="state.queryForm.personName" placeholder="请输入人员姓名" />
</el-form-item>
<el-form-item style="width: 250px;" label="类型" prop="alarmTypeList">
<dict-select v-model="state.queryForm.alarmTypeList" :options="dk_type" multiple
placeholder="请选择类型" />
@@ -51,7 +54,7 @@
</el-table-column>
</el-table-column>
<el-table-column min-width="100" label="统计">
<el-table-column min-width="100" label="出勤次数">
<el-table-column min-width="100" label="打卡次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.reignCount ?? 0 }}</span>
@@ -62,7 +65,7 @@
<el-table-column min-width="100" label="异常进入次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.earlyCount ?? 0 }}</span>
<span> {{ row.lateCount ?? 0 }}</span>
<span>次</span>
</div>
</template>
@@ -70,7 +73,7 @@
<el-table-column min-width="100" label="异常外出次数">
<template #default="{ row }">
<div class="color-danger">
<span> {{ row.lateCount ?? 0 }}</span>
<span> {{ row.earlyCount ?? 0 }}</span>
<span>次</span>
</div>
</template>
+9 -7
View File
@@ -6,15 +6,18 @@
:defaultTreeWidth="15" :nodeClickable="false">
<el-row shadow="hover" v-show="showSearch" class="ml10">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item style="width: 250px;" label="姓名" prop="name">
<el-form-item style="width: 200px;" label="姓名" prop="name">
<el-input v-model="state.queryForm.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item style="width: 250px;" label="手机号" prop="phone">
<el-form-item style="width: 200px;" label="手机号" prop="phone">
<el-input v-model="state.queryForm.phone" placeholder="请输入手机号" />
</el-form-item>
<el-form-item style="width: 250px;" label="证件号码" prop="paperNumber">
<el-form-item style="width: 200px;" label="证件号码" prop="paperNumber">
<el-input v-model="state.queryForm.paperNumber" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item style="width: 250px;" label="是否加入打卡统计" prop="clockEnable">
<dict-select v-model="state.queryForm.clockEnable" :options="yes_no_type" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
@@ -48,8 +51,7 @@
<el-table-column width="100" label="是否加入打卡">
<template #default="{ row }">
<el-tag :type="row.clockEnable === '1' ? 'success' : 'danger'">
{{ row.clockEnable === '1' ? '已加入' :
'未加入' }}
{{ row.clockEnable === '1' ? '已加入' : '未加入' }}
</el-tag>
</template>
</el-table-column>
@@ -63,7 +65,7 @@
<div class="flex items-center gap-1 overflow-hidden leading-5">
<span class="truncate font-medium">{{ row.name }}</span>
<span v-if="row.age" class="shrink-0 text-xs text-gray-500">{{ row.age
}}岁</span>
}}岁</span>
<tag-sex :code="row.sex" />
</div>
<div class="flex items-center gap-1 text-xs text-gray-500 leading-5">
@@ -149,7 +151,7 @@ import dayjs from "dayjs";
import other from '/@/utils/other'
// 定义查询字典
const { dh_paper_type, user_sync_config } = useDict('dh_paper_type', 'user_sync_config')
const { dh_paper_type, user_sync_config, yes_no_type } = useDict('dh_paper_type', 'user_sync_config', 'yes_no_type')
// 定义变量内容
const tableRef = ref()
+11 -1
View File
@@ -15,6 +15,9 @@
<el-form-item style="width: 250px;" label="证件号码" prop="paperNumber">
<el-input v-model="state.queryForm.paperNumber" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item style="width: 250px;" label="是否加入打卡统计" prop="clockEnable">
<dict-select v-model="state.queryForm.clockEnable" :options="yes_no_type" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
@@ -97,6 +100,13 @@
<tag-sync :isSync="row.isSync == 1" />
</template>
</el-table-column>
<el-table-column width="100" label="是否加入打卡">
<template #default="{ row }">
<el-tag :type="row.clockEnable === '1' ? 'success' : 'danger'">
{{ row.clockEnable === '1' ? '已加入' : '未加入' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="同步配置" min-width="120" show-overflow-tooltip>
<template #default="{ row }">
<dict-tag :options="user_sync_config" :value="row.syncConfigType" />
@@ -146,7 +156,7 @@ const FormDialog = defineAsyncComponent(() => import('./person-form.vue'));
const SyncConfigForm = defineAsyncComponent(() => import('./form.vue'));
// 定义查询字典
const { dh_paper_type, user_sync_config } = useDict('dh_paper_type', 'user_sync_config')
const { dh_paper_type, user_sync_config, yes_no_type } = useDict('dh_paper_type', 'user_sync_config', 'yes_no_type')
// 定义变量内容
const formDialogRef = ref()