Commit 542cec95 authored by “yiyousong”'s avatar “yiyousong”

feat: 排队报表接口调试

parent fa17d4e5
<template>
<div class="app h-full w-full">
<div class="loading" v-if="loading">
<div>
<div class="title">{{ title }}...</div>
<el-progress :percentage="percentage" color="#1890ff"></el-progress>
</div>
</div>
<router-view />
</div>
</template>
<script>
import Vue from "vue";
export default {
data() {
return {};
return {
percentage: 1,
loading: false,
title: "文件导出中",
};
},
beforeCreate() {
Vue.prototype.$app = this;
},
created() {},
methods: {},
};
......@@ -19,5 +32,28 @@ export default {
.app {
background-color: #eff0f4;
font-family: Source Han Sans CN;
.loading {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
position: fixed;
top: 0px;
left: 0px;
z-index: 99999;
.title {
color: #fff;
font-size: 14px;
text-align: center;
}
.el-progress {
width: 300px;
:deep(.el-progress__text) {
color: #fff !important;
}
}
}
}
</style>
......@@ -8,3 +8,37 @@ export const getSiteTree = (params) => {
params,
});
};
// 获取部门
export const getDepartment = (data) => {
return request({
url: `/base/dept/list`,
method: "post",
data,
});
};
// 获取大厅
export const getHall = (data) => {
return request({
url: `/base/site/hall/list`,
method: "post",
data,
});
};
// 获取窗口
export const getWindow = (data) => {
return request({
url: `/base/window/list`,
method: "post",
data,
});
};
// 获取站点业务
export const getSiteBusiness = (data) => {
return request({
url: `/base/site/business/list`,
method: "post",
data,
});
};
......@@ -160,6 +160,11 @@
background-color:var(--primary)
}
.el-descriptions-item__content:empty::before {
content: "--";
color: gray;
}
// .search-popover{
// box-shadow: 0 0 12px 0 rgba(24, 144, 255, 0.1);
// border: 1px solid var(--primary);
......
<template>
<div class="h-full w-full">
<el-tree
:data="siteTree"
:data="areaTree"
:props="defaultProps"
node-key="id"
highlight-current
......@@ -50,8 +50,11 @@ export default {
created() {},
methods: {
handleNodeClick(data) {
let type = data.type;
this.$emit("change", type, data.id);
let form = {
type: data.type,
id: data.id,
};
this.$emit("change", form);
},
},
};
......
<template>
<el-date-picker
:value="value"
type="daterange"
:value-format="valueFormat"
unlink-panels
:picker-options="pickerOptions"
:clearable="Clearable"
v-bind="$attrs"
@input="handleChange"
v-on="$listeners"
>
</el-date-picker>
</template>
<script>
export default {
name: "YDatePicker",
model: {
event: "change",
prop: "value",
},
props: {
value: {
type: Array,
default: () => {
return [];
},
},
clearable: {
type: Boolean,
default: false,
},
valueFormat: {
type: String,
default: "yyyy-MM-dd",
},
},
data() {
return {
pickerOptions: {
shortcuts: [
{
text: "今天",
onClick(picker) {
const end = new Date();
const start = new Date();
picker.$emit("pick", [start, end]);
},
},
{
text: "最近一周",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit("pick", [start, end]);
},
},
{
text: "最近一个月",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit("pick", [start, end]);
},
},
{
text: "最近三个月",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit("pick", [start, end]);
},
},
],
},
};
},
computed: {
Clearable() {
return !!this.clearable;
},
},
methods: {
handleChange(val) {
this.$emit("change", val);
},
},
};
</script>
<style lang="less" scoped></style>
......@@ -62,6 +62,7 @@ export default {
handler() {
this.$nextTick(() => {
this.$refs.MyTable.bodyWrapper.scrollTop = 0;
this.$refs.MyTable.bodyWrapper.scrollLeft = 0;
});
},
immediate: true,
......
......@@ -16,7 +16,7 @@
class="content"
style="min-width: 60vw; max-width: 80vw; min-height: 200px"
>
<div class="flex_row flex_align_c primary-color name">
<div class="name">
<i class="el-icon-location" style="margin-right: 10px"></i>
<span style="">{{ siteName }}</span>
</div>
......@@ -230,40 +230,4 @@ export default {
color: #ffffff;
cursor: pointer;
}
.select-site {
position: fixed;
left: 300px !important;
top: 65px;
background: #fff;
border-radius: 6px;
padding: 10px;
min-width: 60%;
max-width: 80%;
z-index: 9;
color: rgba(0, 0, 0, 0.8);
font-size: 14px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
.name {
font-size: 20px;
}
.site-list {
// padding: 10px 0;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
overflow: hidden;
span {
float: left;
line-height: 1.5;
padding: 10px 20px;
cursor: pointer;
&:hover {
color: #1890ff;
}
}
}
.check-site,
.site-btn {
padding: 0 20px;
}
}
</style>
......@@ -18,7 +18,7 @@
</el-tab-pane>
</el-tabs>
<div class="out-box flex-1 p-[20px]">
<router-view></router-view>
<router-view ref="Page"></router-view>
</div>
</div>
</div>
......@@ -56,8 +56,8 @@ export default {
);
},
// 改变站点选择
changeSite(type, siteId) {
console.log(type, siteId);
changeSite(data) {
this.$refs.Page.getSite(data);
},
},
};
......
......@@ -3,7 +3,13 @@
<!-- 顶部搜索 -->
<div class="w-ful flex items-center justify-between">
<div class="flex items-center gap-4">
<el-button type="primary" size="small">导出</el-button>
<el-button
type="primary"
size="small"
:loading="exportLoading"
@click="exportExcel"
>导出</el-button
>
<div class="text-[#909399]">
取号次数:<span class="take-total-num">{{ total }}</span>
</div>
......@@ -27,26 +33,22 @@
<el-input
v-model="searchForm.keyword"
placeholder="请输入关键字"
@keyup.native.enter="generalSearch"
clearable
@keyup.native.enter="handleSearch"
></el-input>
</el-form-item>
<el-form-item>
<el-date-picker
<y-date-picker
v-model="searchForm.time"
type="daterange"
value-format="yyyy-MM-dd"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
:clearable="false"
>
</el-date-picker>
</y-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="generalSearch">搜索</el-button>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</div>
......@@ -57,41 +59,57 @@
>
<div class="w-full">
<el-form ref="searchForm2" inline size="small" :model="searchForm2">
<el-form-item>
<!-- <el-form-item>
<el-checkbox-group v-model="searchForm2.type">
<el-checkbox label="预约业务" name="type"></el-checkbox>
<el-checkbox label="呼叫业务" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form-item> -->
<el-form-item>
<el-select
v-model="searchForm2.region"
placeholder="请选择活动区域"
style="width: 150px"
v-model="searchForm2.wySignin"
clearable
placeholder="请选择取号方式"
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
<el-option label="现场取号" value="现场取号"></el-option>
<el-option label="在线取号" value="微信取号"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-select
v-model="searchForm2.region"
placeholder="请选择活动区域"
style="width: 180px"
filterable
clearable
v-model="searchForm2.sectionName"
placeholder="请选择部门"
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
<el-option
v-for="v in deptList"
:key="v.id"
:label="v.name"
:value="v.name"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-select
v-model="searchForm2.region"
placeholder="请选择活动区域"
style="width: 180px"
v-model="searchForm2.hallName"
filterable
clearable
placeholder="请选择大厅"
>
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
<el-option
v-for="v in hallList"
:key="v.id"
:label="v.hallName"
:value="v.hallName"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary">搜索</el-button>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</div>
......@@ -102,6 +120,7 @@
</el-popover>
</div>
<div class="main max-w-[1396px] flex-1">
<div>
<y-table
ref="MyTable"
:loading="loading"
......@@ -109,10 +128,11 @@
:column="column"
border
tooltip-effect="dark"
:max-height="600"
:max-height="580"
:row-key="(row) => row.id"
@selection-change="handleSelectionChange"
></y-table>
</div>
<Pagination
:total="total"
:current.sync="current"
......@@ -121,7 +141,7 @@
></Pagination>
</div>
<!-- 详情 -->
<QueueUpDetails :show.sync="show"></QueueUpDetails>
<QueueUpDetails :show.sync="show" :info="detailsInfo"></QueueUpDetails>
</div>
</template>
......@@ -134,7 +154,10 @@ let searchType = {
4: "按群众手机号",
};
import { getQueueList } from "@/api/market";
import { getDepartment, getHall } from "@/api/site";
import storage from "@/utils/storage";
import { formatSeconds, dataSection } from "@/utils";
import { export2Excel } from "@/utils/exportExcel";
export default {
components: {
QueueUpDetails,
......@@ -144,13 +167,21 @@ export default {
searchType,
show: false,
loading: false,
exportLoading: false,
total: 0,
size: 10,
current: 1,
dict: {},
selectionRow: [],
pickerOptions: {
shortcuts: [
{
text: "今天",
onClick(picker) {
const end = new Date();
const start = new Date();
picker.$emit("pick", [start, end]);
},
},
{
text: "最近一周",
onClick(picker) {
......@@ -190,7 +221,9 @@ export default {
siteId: storage.get(2, "siteId"),
},
searchForm2: {
type: [],
wySignin: "", // 取号方式(现场取号,微信取号)
hallName: "", // 大厅名称
sectionName: "", // 部门名称
},
tableData: [],
column: [
......@@ -198,6 +231,7 @@ export default {
type: "selection",
width: "50",
align: "center",
reserveSelection: true,
fixed: "left",
},
{
......@@ -206,6 +240,9 @@ export default {
width: "50",
align: "center",
fixed: "left",
index: (index) => {
return index + 1 + (this.current - 1) * this.size;
},
},
{
label: "站点名称",
......@@ -220,7 +257,7 @@ export default {
prop: "business",
},
{
label: "预约编",
label: "预约编",
align: "center",
width: "150",
prop: "ordernumber",
......@@ -309,30 +346,49 @@ export default {
align: "center",
width: "150",
prop: "taketime",
formatter: (row) => {
return this.$moment(row.taketime).format("YYYY-MM-DD HH:mm:ss");
},
},
{
label: "叫号时间",
align: "center",
width: "150",
prop: "calltime",
formatter: (row) => {
return this.$moment(row.taketime).format("YYYY-MM-DD HH:mm:ss");
},
},
{
label: "结束时间",
align: "center",
width: "150",
prop: "endtime",
formatter: (row) => {
return this.$moment(row.taketime).format("YYYY-MM-DD HH:mm:ss");
},
},
{
label: "等待时间",
align: "center",
width: "150",
prop: "waitTime",
formatter: (row) => {
if (row.waitTime) {
return formatSeconds(row.waitTime);
}
},
},
{
label: "办理时间",
align: "center",
width: "150",
prop: "handleTime",
formatter: (row) => {
if (row.handleTime) {
return formatSeconds(row.handleTime);
}
},
},
{
label: "扩展编号",
......@@ -359,20 +415,38 @@ export default {
},
},
],
detailsInfo: {},
deptList: [], // 部门列表
hallList: [], // 大厅列表
};
},
created() {
this.getQueueList();
this.getDepartment();
this.getHall();
},
methods: {
// 获取列表
async getQueueList(form = {}) {
this.loading = true;
// 获取站点
getSite(data) {
this.current = 1;
this.size = 10;
if (data.type == "site") {
this.searchForm.siteId = data.id;
this.getQueueList();
this.getDepartment();
this.getHall();
} else {
this.tableData = [];
this.total = 0;
}
},
// 获取数据函数
async getData(form = {}) {
let obj = {
page: this.current,
size: this.size,
taketimeStart: this.searchForm.time[0],
taketimeEnd: this.searchForm.time[1],
// taketimeStart: this.searchForm.time[0],
// taketimeEnd: this.searchForm.time[1],
siteId: this.searchForm.siteId,
};
let val = `%${this.searchForm.keyword}%`;
......@@ -390,32 +464,119 @@ export default {
obj.peoplePhone = val;
break;
}
this.loading = false;
let res = await getQueueList({
...obj,
...form,
});
let res = await getQueueList({ ...obj, ...this.searchForm2, ...form });
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
return res.data.data;
} else {
return {
data: [],
total: 0,
};
}
},
// 获取表格数据列表
async getQueueList(form = {}) {
this.loading = true;
let { data, total } = await this.getData(form);
this.tableData = data;
this.total = total;
this.dict = dict;
this.loading = false;
},
// 获取站点部门
async getDepartment() {
let res = await getDepartment({
page: 1,
size: -1,
siteId: this.searchForm.siteId,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.deptList = data;
}
},
// 普通搜索
generalSearch() {
// 获取大厅
async getHall() {
let res = await getHall({
page: 1,
size: -1,
siteId: this.searchForm.siteId,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.hallList = data;
}
},
// 搜索
handleSearch() {
this.current = 1;
this.$clearSelection("MyTable");
this.getQueueList();
},
checkDetails(row) {
console.log(row);
let data = this.$cloneDeep(row);
this.detailsInfo = data;
this.show = true;
},
handleSelectionChange(val) {
this.selectionRow = val;
},
// 导出表格
exportExcel() {
this.exportLoading = true;
let table = this.column.filter((v) => v.prop);
let tHeader = table.map((v) => v.label);
let filterVal = table.map((v) => v.prop);
if (this.selectionRow.length) {
let data = this.$cloneDeep(this.selectionRow);
data.forEach((v) => {
v.taketime =
v.taketime &&
this.$moment(v.taketime).format("YYYY-MM-DD HH:mm:ss");
v.endtime =
v.endtime && this.$moment(v.endtime).format("YYYY-MM-DD HH:mm:ss");
v.calltime =
v.calltime &&
this.$moment(v.calltime).format("YYYY-MM-DD HH:mm:ss");
v.waitTime = v.waitTime && formatSeconds(v.waitTime);
v.handleTime = v.handleTime && formatSeconds(v.handleTime);
});
export2Excel(
tHeader,
filterVal,
data,
"排队数据报表" + this.$moment().format("YYYYMMDDHHmmss")
);
} else {
dataSection(this.getData, {}, (data) => {
if (!data.length) {
this.$message.warning("暂无数据");
return;
}
data.forEach((v) => {
v.taketime =
v.taketime &&
this.$moment(v.taketime).format("YYYY-MM-DD HH:mm:ss");
v.endtime =
v.endtime &&
this.$moment(v.endtime).format("YYYY-MM-DD HH:mm:ss");
v.calltime =
v.calltime &&
this.$moment(v.calltime).format("YYYY-MM-DD HH:mm:ss");
v.waitTime = v.waitTime && formatSeconds(v.waitTime);
v.handleTime = v.handleTime && formatSeconds(v.handleTime);
});
export2Excel(
tHeader,
filterVal,
data,
"排队数据报表" + this.$moment().format("YYYYMMDDHHmmss")
);
});
}
this.exportLoading = false;
},
},
};
</script>
......
......@@ -13,7 +13,7 @@
labelClassName="label-name"
>
<el-descriptions-item
v-for="(v, i) in detailsList"
v-for="(v, i) in dataInfo"
:key="i"
:label="v.title"
>
......@@ -25,123 +25,156 @@
</template>
<script>
import { formatSeconds } from "@/utils";
export default {
props: {
show: {
type: Boolean,
default: false,
},
info: {
required: true,
type: Object,
default: () => {},
},
},
data() {
return {
detailsList: [
{
title: "预约编号",
content: "测试",
prop: "ordernumber",
content: "",
},
{
title: "叫号状态",
content: "测试",
prop: "style",
content: "",
},
{
title: "业务名称",
content: "测试",
prop: "business",
content: "",
},
{
title: "窗口名称",
content: "测试",
prop: "windowName",
content: "",
},
{
title: "窗口编号",
content: "测试",
prop: "windowFromnum",
content: "",
},
{
title: "流水编号,当天的第xxx号",
content: "测试",
prop: "flownum",
content: "",
},
{
title: "呼叫转移号",
content: "测试",
prop: "formernum",
content: "",
},
{
title: "姓名",
content: "测试",
prop: "peopleName",
content: "",
},
{
title: "身份证号",
content: "测试",
prop: "peopleIdcard",
content: "",
},
{
title: "性别",
content: "测试",
prop: "peopleSex",
content: "",
},
{
title: "手机号",
content: "测试",
prop: "peoplePhone",
content: "",
},
{
title: "工作人员姓名",
content: "测试",
prop: "workmanName",
content: "",
},
{
title: "工作人员工号",
content: "测试",
prop: "workmanNumber",
content: "",
},
{
title: "取号时间",
content: "测试",
prop: "taketime",
content: "",
},
{
title: "结束时间",
content: "测试",
prop: "endtime",
content: "",
},
{
title: "等待时间",
content: "测试",
prop: "waitTime",
content: "",
},
{
title: "办理时间",
content: "测试",
prop: "handleTime",
content: "",
},
{
title: "取号设备类型",
content: "测试",
prop: "deviceType",
content: "",
},
{
title: "取号设备名称",
content: "测试",
prop: "deviceName",
content: "",
},
{
title: "呼叫设备",
content: "测试",
prop: "callName",
content: "",
},
{
title: "事项名称",
content: "测试",
prop: "matterName",
content: "",
},
{
title: "排号队列ID,唯一",
content: "测试",
prop: "queueid",
content: "",
},
{
title: "大厅名称",
prop: "hallName",
content: "测试",
},
{
title: "站点ID",
content: "测试",
prop: "siteId",
content: "",
},
{
title: "站点编码",
content: "测试",
prop: "siteCode",
content: "",
},
{
title: "站点名称",
content: "测试",
prop: "siteName",
content: "",
},
{
title: "扩展编号",
content: "测试",
prop: "extNum",
content: "",
},
],
};
......@@ -155,7 +188,22 @@ export default {
this.$emit("update:show", val);
},
},
dataInfo() {
this.detailsList.forEach((v) => {
if (v.prop == "taketime" || v.prop == "endtime") {
v.content = this.$moment(this.info[v.prop]).format(
"YYYY-MM-DD HH:mm:ss"
);
} else if (v.prop == "waitTime" || v.prop == "handleTime") {
v.content = formatSeconds(this.info[v.prop]);
} else {
v.content = this.info[v.prop];
}
});
return this.detailsList;
},
},
methods: {},
};
</script>
......
import Vue from "vue";
import CryptoJS from "crypto-js";
import moment from "moment";
// 加密数据
export let encrypt = (str, keyStr, ivStr) => {
......@@ -121,3 +123,41 @@ export function findBottomSubarrays(arr) {
recursiveSearch(arr);
return bottomSubarrays;
}
// 秒数转HH:mm:ss
export function formatSeconds(secondsNum) {
const time = moment.duration(secondsNum, "seconds");
const hours = time.hours();
const minutes = time.minutes();
const seconds = time.seconds();
return moment({ h: hours, m: minutes, s: seconds }).format("HH:mm:ss");
}
/**
*
* @param {*} fn 数据获取函数
* @param {*} searchForm 搜索表单
* @param {*} callback 回调函数
*/
export const dataSection = async (fn, searchForm = {}, callback) => {
let dataList = [];
let page = 1;
let size = 1000;
let execute = async () => {
let { data, total } = await fn({ page, size, ...searchForm });
dataList = [...dataList, ...data];
Vue.prototype.$app.loading = true;
Vue.prototype.$app.percentage = parseInt((dataList.length / total) * 100);
if (dataList.length >= total || data.data.length == 0) {
if (callback) callback(dataList);
Vue.prototype.$app.loading = false;
Vue.prototype.$app.percentage = 1;
return;
}
setTimeout(() => {
page += 1;
execute();
});
};
execute();
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment