feat:排班视图
This commit is contained in:
1 parent
6ffc58d517
commit
6057f30c7f
11 files changed
+452
-7
No files matched your search
@@ -1,5 +1,13 @@
|
||||
import request from "/@/utils/request"
|
||||
|
||||
export function select(query?: Object) {
|
||||
return request({
|
||||
url: '/admin/sys-duty/select',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchList(query?: Object) {
|
||||
return request({
|
||||
url: '/admin/sys-duty/page',
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<el-select style="width: 100%" v-model="state.selectId" :placeholder="props.placeholder"
|
||||
:clearable="props.clearable" remote-show-suffix filterable remote :disabled="props.disabled"
|
||||
:remote-method="remoteSearch" :loading="state.loading" @visible-change="(e: boolean) => e && getOptions()"
|
||||
@change="change">
|
||||
<el-option v-for="v in state.options" :key="v.id" :label="v.title" :value="v.id" />
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SelectDuty">
|
||||
import { reactive } from "vue"
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
|
||||
import * as sysDutyApi from "/@/api/sys/sysDuty"
|
||||
|
||||
const emit = defineEmits(["change"])
|
||||
|
||||
const selectId = defineModel()
|
||||
|
||||
type Props = {
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
clearable?: boolean
|
||||
autoFirst?: boolean
|
||||
apiParams?: any
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
placeholder: "请选择",
|
||||
disabled: false,
|
||||
clearable: true,
|
||||
autoFirst: false,
|
||||
apiParams: {},
|
||||
})
|
||||
|
||||
const queryForm = reactive<any>({
|
||||
name: "",
|
||||
current: 1,
|
||||
size: 10,
|
||||
})
|
||||
|
||||
const state = reactive<any>({
|
||||
loading: true,
|
||||
selectId: selectId,
|
||||
options: [],
|
||||
hardType: [],
|
||||
})
|
||||
|
||||
watch(
|
||||
selectId,
|
||||
(newVal, oldValue) => {
|
||||
if (newVal == oldValue) return
|
||||
state.selectId = newVal
|
||||
getOptions()
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
async function getOptions() {
|
||||
try {
|
||||
state.loading = true
|
||||
const _pa = {
|
||||
...queryForm,
|
||||
...props.apiParams,
|
||||
}
|
||||
const { data } = await sysDutyApi.select(_pa)
|
||||
state.options = data.records ?? []
|
||||
if (props.autoFirst && state.options.length != 0 && !state.selectId) {
|
||||
state.selectId = state.options[0].id
|
||||
emit("change", state.selectId)
|
||||
}
|
||||
const { hard_type } = useDict("hard_type")
|
||||
state.hardType = hard_type
|
||||
} finally {
|
||||
setTimeout(() => (state.loading = false), 500)
|
||||
}
|
||||
}
|
||||
|
||||
function remoteSearch(params: string) {
|
||||
if (params != queryForm.name) {
|
||||
queryForm.name = params
|
||||
getOptions()
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
state.selectId = null
|
||||
getOptions()
|
||||
}
|
||||
|
||||
function change() {
|
||||
emit("change", selectId)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
props.autoFirst && getOptions()
|
||||
})
|
||||
</script>
|
||||
@@ -25,6 +25,7 @@ import TagUserStatus from "/@/components/Tag/TagUserStatus.vue"
|
||||
|
||||
import SelectArea from "/@/components/Select/SelectArea.vue"
|
||||
import SelectDevice from "/@/components/Select/SelectDevice.vue"
|
||||
import SelectDuty from "/@/components/Select/SelectDuty.vue"
|
||||
import SelectDutyType from "/@/components/Select/SelectDutyType.vue"
|
||||
import SelectTreeChannel from "/@/components/Select/SelectTreeChannel.vue"
|
||||
import SelectTreeChannelRadio from "/@/components/Select/SelectTreeChannelRadio.vue"
|
||||
@@ -83,6 +84,7 @@ export default {
|
||||
|
||||
app.component('SelectArea', SelectArea);
|
||||
app.component('SelectDevice', SelectDevice);
|
||||
app.component('SelectDuty', SelectDuty);
|
||||
app.component('SelectDutyType', SelectDutyType);
|
||||
app.component('SelectTreeChannel', SelectTreeChannel);
|
||||
app.component('SelectTreeChannelRadio', SelectTreeChannelRadio);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<!-- 车辆信息 -->
|
||||
<template>
|
||||
<com-title title="过车数据">
|
||||
<div class="h-[5px]" />
|
||||
<div v-for="v in 10" class="container flex items-center gap-2 mb-[5px] overflow-y-scroll">
|
||||
<el-image class="w-[55px] h-[55px] rounded-[2px]"
|
||||
src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" fit="cover" />
|
||||
<div class="flex-1 flex flex-col">
|
||||
<div class="container-content">
|
||||
<span>车牌号</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
<div class="container-content">
|
||||
<span>位置</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
<div class="container-content">
|
||||
<span>抓拍时间</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</com-title>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="carList">
|
||||
|
||||
const comTitle = defineAsyncComponent(() => import('./com-title.vue'));
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
padding: 4px 6px;
|
||||
background-color: white;
|
||||
box-shadow: 0px 4px 13px -2px rgba(210, 210, 210, 0.5);
|
||||
border-radius: 6px;
|
||||
|
||||
.container-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
span:nth-child(1) {
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="title flex justify-between items-center">
|
||||
<div class="title-text" :class="props.titleDirection == 'left' ? 'justify-start' : 'justify-end'">
|
||||
<span>{{ props.title }}</span>
|
||||
</div>
|
||||
<div class="w-full h-full">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="comTitle">
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
titleDirection: "left" | "right"
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: "标题",
|
||||
titleDirection: "left"
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
|
||||
&-text {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 0 10px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #577cf7;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<!-- 车辆信息 -->
|
||||
<template>
|
||||
<com-title title="过车数据">
|
||||
<div class="h-[5px]" />
|
||||
<div v-for="v in 10" class="container flex items-center gap-2 mb-[5px] overflow-y-scroll">
|
||||
<el-image class="w-[55px] h-[55px] rounded-[2px]"
|
||||
src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" fit="cover" />
|
||||
<div class="flex-1 flex flex-col">
|
||||
<div class="container-content">
|
||||
<span>车牌号</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
<div class="container-content">
|
||||
<span>位置</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
<div class="container-content">
|
||||
<span>抓拍时间</span>
|
||||
<span>2023-08-01 10:00:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</com-title>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="carList">
|
||||
|
||||
const comTitle = defineAsyncComponent(() => import('./com-title.vue'));
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
padding: 4px 6px;
|
||||
background-color: white;
|
||||
box-shadow: 0px 4px 13px -2px rgba(210, 210, 210, 0.5);
|
||||
border-radius: 6px;
|
||||
|
||||
.container-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
span:nth-child(1) {
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,133 @@
|
||||
<!-- 排班视图 -->
|
||||
<template>
|
||||
<div class="w-full h-full flex flex-col">
|
||||
<com-title title="基地周值班表">
|
||||
<select-duty v-model="refreshForm.dutyId" autoFirst style="width: 250px;" />
|
||||
</com-title>
|
||||
<el-table v-if="tableHeaderList && tableHeaderList.length" style="padding-top: 10px;" :data="disposeDataList"
|
||||
v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle" @sort-change="sortChangeHandle">
|
||||
<el-table-column v-for="(v, i) in tableHeaderList" width="110" :prop="v.prop" :label="v.label">
|
||||
<el-table-column v-if="v.children && v.children.length" v-for="(v2, i2) in v.children" :prop="v2.prop"
|
||||
:label="v2.label" />
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty class="w-full h-full flex justify-center items-center" v-else description="暂无排班数据" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="dutyTable">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
|
||||
import * as sysDutyApi from "/@/api/sys/sysDuty";
|
||||
import * as sysDutyItemApi from "/@/api/sys/sysDutyItem";
|
||||
|
||||
const comTitle = defineAsyncComponent(() => import('./com-title.vue'));
|
||||
|
||||
const tableHeaderList = ref<Array<{
|
||||
prop: string,
|
||||
label: string,
|
||||
children: Array<{
|
||||
prop: string,
|
||||
label: string,
|
||||
}>
|
||||
}>>([])
|
||||
|
||||
const refreshForm = reactive<any>({
|
||||
dutyId: ""
|
||||
})
|
||||
|
||||
const detail = reactive<any>({})
|
||||
|
||||
const disposeDataList = ref<any>([])
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
createdIsNeed: false,
|
||||
queryForm: {
|
||||
dutyId: ""
|
||||
},
|
||||
pageList: sysDutyItemApi.fetchList
|
||||
})
|
||||
|
||||
// table hook
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state)
|
||||
|
||||
watch(
|
||||
() => refreshForm.dutyId,
|
||||
(newVal, oldValue) => {
|
||||
if (newVal == oldValue) return
|
||||
refresh(newVal)
|
||||
},
|
||||
)
|
||||
|
||||
const refresh = async (id: string) => {
|
||||
state.queryForm.dutyId = id
|
||||
if (!id) return
|
||||
await getsysDutyData(id)
|
||||
await getDataList()
|
||||
const _list: Array<any> = []
|
||||
if (state.dataList && state.dataList.length) {
|
||||
for (const v of state.dataList) {
|
||||
if (!v.rowJson || !v.rowJson.length) continue
|
||||
const _obj: any = {}
|
||||
for (const item of v.rowJson) {
|
||||
_obj[item.key] = item.content
|
||||
}
|
||||
_list.push(_obj)
|
||||
}
|
||||
}
|
||||
disposeDataList.value = _list
|
||||
}
|
||||
|
||||
// 初始化表单数据
|
||||
const getsysDutyData = async (id: string) => {
|
||||
// 获取数据
|
||||
try {
|
||||
const { data } = await sysDutyApi.getObj(id)
|
||||
Object.assign(detail, data)
|
||||
const _tableHeaderList: Array<{
|
||||
prop: string,
|
||||
label: string,
|
||||
children: []
|
||||
}> = []
|
||||
if (data && data.configJson && data.configJson.length) {
|
||||
for (let index = 0; index < data.configJson.length; index++) {
|
||||
const element = data.configJson[index];
|
||||
if (!element) continue
|
||||
const isExist = _tableHeaderList.some(v => v.label == element.mainLabel)
|
||||
if (isExist) continue
|
||||
const entity = {
|
||||
prop: element.key,
|
||||
label: element.mainLabel,
|
||||
children: []
|
||||
}
|
||||
const children = data.configJson.filter((v: any) => v.mainLabel == element.mainLabel) ?? []
|
||||
if (children.length >= 2) {
|
||||
entity.prop = ""
|
||||
entity.children = children.map((v: any) => {
|
||||
return {
|
||||
prop: v.key,
|
||||
label: v.subLabel,
|
||||
}
|
||||
})
|
||||
}
|
||||
_tableHeaderList.push(entity as any)
|
||||
}
|
||||
}
|
||||
tableHeaderList.value = _tableHeaderList
|
||||
console.log("tableHeaderList:", tableHeaderList.value);
|
||||
} catch (error) {
|
||||
console.log("|初始化表单数据|意外的错误:", error);
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- 视频预览 -->
|
||||
<template>
|
||||
<div class="w-full h-full pt-[10px]">
|
||||
<com-title title="监控预览"></com-title>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="videoPay">
|
||||
|
||||
const comTitle = defineAsyncComponent(() => import('./com-title.vue'));
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -1,13 +1,50 @@
|
||||
<!-- 值班类型 -->
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
</div>
|
||||
<el-container>
|
||||
<el-aside class="aside">
|
||||
<car-list />
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header class="header">
|
||||
<duty-table />
|
||||
</el-header>
|
||||
<el-main class="main">
|
||||
<video-pay />
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-aside class="aside">
|
||||
<door-list />
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="dutyPlan">
|
||||
|
||||
const CarList = defineAsyncComponent(() => import('./components/car-list.vue'));
|
||||
const DoorList = defineAsyncComponent(() => import('./components/door-list.vue'));
|
||||
const DutyTable = defineAsyncComponent(() => import('./components/duty-table.vue'));
|
||||
const VideoPay = defineAsyncComponent(() => import('./components/video-pay.vue'));
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.aside {
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
padding: 0 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -42,8 +42,7 @@ const queryForm = reactive<any>({
|
||||
id: ''
|
||||
})
|
||||
|
||||
const detail = reactive<any>({
|
||||
})
|
||||
const detail = reactive<any>({})
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
createdIsNeed: false,
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
:header-cell-style="tableStyle.headerCellStyle" @selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="applyId" label="创建人" />
|
||||
<el-table-column type="index" label="#" width="80" />
|
||||
<el-table-column prop="applyUsername" label="创建人" />
|
||||
<el-table-column prop="title" label="标题" />
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
<el-table-column label="排班时间">
|
||||
|
||||
Reference in new issue
Block a user