| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>AI调度管理</title>
- <link rel="stylesheet" href="/static/elementui2.15.5/index.css"/>
- <link rel="stylesheet" href="/static/ai/css/dispatch_center.css"/>
- <script src="/static/hplus/js/jquery.min.js?v=2.1.4"></script>
- <script src="/static/layer3.2.0/layer.js"></script>
- <script src="/static/elementui2.15.5/vue-2.6.14.js"></script>
- <script src="/static/elementui2.15.5/index.js"></script>
- <script src="/static/echarts.js"></script>
- </head>
- <body>
- <div class="page-box">
- <!-- 顶部导航 -->
- <div class="top-nav">
- <div
- class="top-item active"
- data-type="ai">
- AI调度中心
- </div>
- <div
- class="top-item "
- data-type="dispatch">
- 派单列表
- </div>
- <div
- class="top-item"
- data-type="setting">
- 派单设置
- </div>
- </div>
- <!-- 派单列表 / 派单设置 -->
- <div
- class="main"
- id="mainContainer"
- style="display:none;">
- <div class="sidebar">
- </div>
- <div class="content">
- <!-- Loading -->
- <div id="pageLoading">
- <div class="loading-box">
- <div class="loading-spinner"></div>
- <div class="loading-text">
- 一大批数据正在赶来......
- </div>
- </div>
- </div>
- <iframe id="contentFrame" src="">
- </iframe>
- </div>
- </div>
- <!-- AI调度中心 -->
- <div id="aiContainer">
- <!-- <el-card class="main-card">-->
- <!-- 顶部 -->
- <el-row :gutter="10" class="top-area">
- <!-- 左侧整体 -->
- <el-col :lg="18" :md="24">
- <!-- 上部分 -->
- <el-row :gutter="10">
- <!-- 左侧统计 -->
- <el-col :span="8">
- <div class="stat-wrap" v-loading="loading" element-loading-text="数据加载中......">
- <div class="big-card" style='background-image: url("/static/ai/img/dispatched.png")' @click="handleModeChange(0)">
- <div class="big-left">
- <div class="big-title">AI派单总数</div>
- <div class="big-value">{{done.total}}</div>
- </div>
- </div>
- <div class="small-grid">
- <el-row :gutter="8" style="height:100%;">
- <el-col :span="12" style="margin-bottom:8px;">
- <div class="stat-card" style='background-image: url("/static/ai/img/bj.png")'>
- <h3>保洁派单数</h3><p style="color: #0983E2FF">{{done.bj}}</p>
- </div>
- </el-col>
- <el-col :span="12" style="margin-bottom:8px;">
- <div class="stat-card" style='background-image: url("/static/ai/img/bx.png")'>
- <h3>维修派单数</h3><p style="color: #00905DFF">{{done.bx}}</p>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="stat-card" style='background-image: url("/static/ai/img/ys.png")'>
- <h3>运送工单数</h3><p style="color: #E68417FF">{{done.ys}}</p>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="stat-card" style='background-image: url("/static/ai/img/ab.png")'>
- <h3>安保待派单数</h3><p style="color: #8943DDFF">{{done.ab}}</p>
- </div>
- </el-col>
- </el-row>
- </div>
- </div>
- </el-col>
- <!-- 中间banner -->
- <el-col :span="16">
- <div class="center-banner">
- <video
- class="video"
- src="/static/ai/img/ai.mp4"
- autoplay
- loop
- muted
- playsinline
- webkit-playsinline
- x5-playsinline
- disablePictureInPicture>
- 您的浏览器不支持视频播放
- </video>
- </div>
- </el-col>
- </el-row>
- </el-col>
- <!-- 右侧 -->
- <el-col :lg="6" :md="24">
- <div class="stat-wrap" v-loading="loading" element-loading-text="数据加载中......">
- <div class="big-card" style='background-image: url("/static/ai/img/un-dispatched.png")' @click="handleModeChange2(0)">
- <div class="big-left">
- <div class="big-title">待派单总数</div>
- <div class="big-value">{{undo.total}}</div>
- </div>
- </div>
- <div class="small-grid">
- <el-row :gutter="8" style="height:100%;">
- <el-col :span="12" style="margin-bottom:8px;">
- <div class="stat-card" style='background-image: url("/static/ai/img/bj.png")'>
- <h3>保洁待派单数</h3><p style="color: #0983E2FF">{{undo.bj}}</p>
- </div>
- </el-col>
- <el-col :span="12" style="margin-bottom:8px;">
- <div class="stat-card" style='background-image: url("/static/ai/img/bx.png")'>
- <h3>维修待派单数</h3><p style="color: #00905DFF">{{undo.bx}}</p>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="stat-card" style='background-image: url("/static/ai/img/ys.png")'>
- <h3>运送待派单数</h3><p style="color: #E68417FF">{{undo.ys}}</p>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="stat-card" style='background-image: url("/static/ai/img/ab.png")'>
- <h3>安保待派单数</h3><p style="color: #8943DDFF">{{undo.ab}}</p>
- </div>
- </el-col>
- </el-row>
- </div>
- </div>
- </el-col>
- </el-row>
- <!-- </el-card>-->
- <div class="table-header" >
- <div
- v-for="item in tabs"
- :key="item.value"
- class="tab-item"
- :class="{ active: currentTab === item.value }"
- @click="changeTab(item)"
- >
- <span class="tab-text" :style="{ fontSize: getFontSize(item) }">
- {{ item.label }}(
- <span :ref="`count_${item.value}`" class="count-number">{{ item.count }}</span>
- )
- </span>
- </div>
- </div>
- <!-- 底部表格 -->
- <el-card class="table-card" shadow="never">
- <el-row style="margin-top:10px;">
- <el-col :span="24">
- <el-table v-loading="tableLoading"
- element-loading-text="一大批数据正在赶来......"
- ref="dispatchedTable"
- :data="tableData"
- style="width:100%;min-height: 50vh">
- <el-table-column prop="sn" label="订单编号">
- <template slot-scope="scope">
- <a href="javascript:;"
- data-title="详情"
- @click="layerOpen(scope.row.id)"
- data-title="详情"
- style="color:#0056DBFF;text-decoration: none">
- {{ scope.row.sn }}
- </a>
- </template>
- </el-table-column>
- <el-table-column prop="type" label="订单类型"></el-table-column>
- <el-table-column prop="user" label="发起人"></el-table-column>
- <el-table-column v-if="currentTab == 'today'" prop="status" label="订单状态">
- <template slot-scope="scope">
- <span class="status-dispatch">已派单</span>
- </template>
- </el-table-column>
- <el-table-column v-if="currentTab == 'today'" prop="create_time" label="派单时间"></el-table-column>
- <el-table-column v-if="currentTab == 'today'" prop="toUser" label="指派员工"></el-table-column>
- <el-table-column v-if="currentTab == 'today'" label="操作">
- <template slot-scope="scope">
- <a href="javascript:;"
- data-title="重新派单"
- @click="send(scope.row.todo_id,scope.row.mode,0)"
- style="color:#0056DBFF;text-decoration: none">
- 重新派单
- </a>
- </template>
- </el-table-column>
- <el-table-column v-if="currentTab != 'today'" prop="status" label="状态">
- <template slot-scope="scope">
- <div v-if="currentTab == 'error'">
- <span class="status-fail">派单未匹配</span>
- </div>
- <div v-else>
- <img v-if="scope.row.flag" src="/static/ai/img/wait.png" class="loading-ico">
- <span :class="scope.row.flag ? 'status-inprogress':'status-pending'">{{ scope.row.flag && ai == 1 ? 'Ai派单中...':'待派单' }}</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column v-if="currentTab == 'error'" prop="fail" label="操作">
- <template slot-scope="scope">
- <a href="javascript:;"
- data-title="手动派单"
- @click="send(scope.row.id,scope.row.work_type_mode,1)"
- style="color:#0056DBFF;text-decoration: none">
- 手动派单
- </a>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <div class="page" v-if="tableData.length > 0">
- <el-pagination
- background
- layout="prev, pager, next, total"
- :total="total"
- :page-size="pageSize"
- :current-page.sync="currentPage"
- @current-change="handlePageChange">
- </el-pagination>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <!-- 员工数据分析-->
- <el-card class="dashboard-card">
- <el-row :gutter="20" class="dashboard-row">
- <!-- 左侧 -->
- <el-col :xl="10" :lg="10" :md="24" :sm="24" class="left-col">
- <div class="panel" v-loading="staffLoading" element-loading-text="数据加载中......">
- <div class="panel-title">
- 在岗员工数据
- </div>
- <div class="staff-wrap">
- <div
- ref="staffChart"
- class="staff-chart">
- </div>
- <div class="staff-cards">
- <div class="staff-card">
- <div class="card-label">
- <img src="/static/ai/img/bj-icon.png" class="staff-icon">
- <span>保洁在岗</span>
- </div>
- <div class="card-num">
- {{bjInfo.active || 0}}
- <span>/{{bjInfo.total || 0}}</span>
- </div>
- </div>
- <div class="staff-card">
- <div class="card-label">
- <img src="/static/ai/img/ys-icon.png" class="staff-icon">
- <span>运送在岗</span>
- </div>
- <div class="card-num">
- {{ysInfo.active || 0}}
- <span>/{{ysInfo.total || 0}}</span>
- </div>
- </div>
- <div class="staff-card">
- <div class="card-label">
- <img src="/static/ai/img/bx-icon.png" class="staff-icon">
- <span>维修在岗</span>
- </div>
- <div class="card-num">
- {{bxInfo.active || 0}}
- <span>/{{bxInfo.total || 0}}</span>
- </div>
- </div>
- <div class="staff-card">
- <div class="card-label">
- <img src="/static/ai/img/ab-icon.png" class="staff-icon">
- <span>安保在岗</span>
- </div>
- <div class="card-num">
- {{abInfo.active || 0}}
- <span>/{{abInfo.total || 0}}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="panel mt20" v-loading="orderLoading" element-loading-text="数据加载中......">
- <div class="panel-header">
- <div class="panel-title">
- 各类型订单派单分析
- </div>
- <div class="date-tabs">
- <div
- v-for="item in chartTabs"
- :key="item.value"
- class="date-tab"
- :class="{ active: orderTab === item.value }"
- @click="changeOrderTab(item)"
- >
- {{item.label}}
- </div>
- </div>
- </div>
- <div
- ref="orderChart"
- class="order-chart">
- </div>
- </div>
- </el-col>
- <!-- 右侧 -->
- <el-col :xl="14" :lg="14" :md="24" :sm="24" v-loading="userLoading" element-loading-text="一大批数据正在赶来......">
- <div class="panel table-panel" ref="user">
- <div class="table-header2">
- <div class="panel-title">
- 员工数据总览
- </div>
- <div class="role-tabs">
- <div
- v-for="item in roleTabs"
- :key="item.value"
- class="role-tab"
- :class="{ active: roleTab === item.value }"
- @click="changeRoleTab(item)"
- >
- {{item.label}}
- </div>
- </div>
- </div>
- <el-table
- :data="userData"
- class="staff-table"
- ref="userTable"
- style="width:100%;">
- <el-table-column show-overflow-tooltip label="员工">
- <template slot-scope="scope">
- <div>
- <span>
- {{scope.row.real_name}}
- </span>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="role_name" label="角色"></el-table-column>
- <el-table-column prop="status" label="状态">
- <template slot-scope="scope">
- <div>
- <el-tag
- :type="scope.row.work === 1 ? 'success' : 'danger'"
- size="small">
- {{ scope.row.work === 1 ? '在岗' : '离岗' }}
- </el-tag>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="doing" label="进行中"></el-table-column>
- <el-table-column prop="wait" label="待处理"></el-table-column>
- <el-table-column prop="receive" label="接单平均时长"></el-table-column>
- <el-table-column prop="finish" label="任务平均耗时"></el-table-column>
- </el-table>
- <div class="pagination-wrap" v-if="userData.length > 0">
- <el-pagination
- background
- layout="prev, pager, next, total"
- :total="userTotal"
- :page-size="7"
- :current-page.sync="userCurrentPage"
- @current-change="handleUserPageChange">
- </el-pagination>
- </div>
- </div>
- </el-col>
- </el-row>
- </el-card>
- <!-- 趋势图 -->
- <el-card class="chart-card" v-loading="loading3" element-loading-text="数据加载中......" shadow="never">
- <div class="chart-header">
- <div class="chart-title">
- 派单趋势分析
- </div>
- <div class="chart-tabs">
- <div
- v-for="item in chartTabs"
- :key="item.value"
- class="chart-tab"
- :class="{ active: chartTab === item.value }"
- @click="changeChartTab(item)"
- >
- {{item.label}}
- </div>
- </div>
- </div>
- <div ref="chart" id="chart"></div>
- </el-card>
- </div>
- </div>
- <script>
- new Vue({
- el:'#aiContainer',
- data: function() {
- return {
- ai:{$ai},
- aiList:[0,0,0,0,0,0,0],
- userList:[0,0,0,0,0,0,0],
- orderAi:[0,0,0,0,],
- orderUser:[0,0,0,0],
- modes:[],
- done: {'total':0,'bx':0, 'bj': 0, 'ys' : 0, 'ab' : 0,},
- undo: {'total':0,'bx':0, 'bj': 0, 'ys' : 0, 'ab' : 0},
- dateList:[],
- currentPage: 1,
- pageSize: 10,
- total: 0,
- mode: 0,
- tableData:[],
- loading:true,
- tableLoading:true,
- loading3:true,
- userCurrentPage: 1,
- userTotal: 0,
- chartLoading: true,
- staffLoading: true,
- orderLoading: true,
- userLoading: true,
- bxInfo: {},
- bjInfo: {},
- ysInfo: {},
- abInfo: {},
- staffData:{},
- staffSummary:{},
- currentTab: 'today',
- tabs: [
- {
- value: 'today',
- label: '今日已派单',
- count: 0
- },
- {
- value: 'wait',
- label: '待派单',
- count: 0
- },
- {
- value: 'error',
- label: '异常订单',
- count: 0
- }
- ],
- userData: [],
- chartTabs: [
- {
- value: 'day',
- label: '近七日',
- },
- {
- value: 'month',
- label: '本月',
- },
- {
- value: 'year',
- label: '本年',
- }
- ],
- chartTab: 'day',
- orderTab: 'day',
- roleTabs: [
- {
- value: 0,
- label: '综合',
- },
- {
- value: 2,
- label: '保洁',
- },
- {
- value: 3,
- label: '运送',
- },
- {
- value: 1,
- label: '维修',
- },
- {
- value: 4,
- label: '安保',
- },
- ],
- roleTab: 0,
- flag1: false,
- flag2: false,
- flag3: false,
- flag4: false,
- }
- },
- mounted(){
- this.observe('staffChart', () => {
- this.flag1 = true;
- this.fetchStaffData();
- })
- this.observe('orderChart', () => {
- this.flag2 = true;
- this.fetchOrderData();
- })
- this.observe('chart', () => {
- this.flag3 = true;
- this.fetchEchart();
- })
- this.observe('user', () => {
- this.flag4 = true;
- this.fetchUserData();
- })
- this.getData();
- setInterval(() => {
- this.getData();
- if (this.flag1) this.fetchStaffData();
- if (this.flag2) this.fetchOrderData();
- if (this.flag3) this.fetchEchart();
- if (this.flag4) this.fetchUserData();
- }, 1000 * 60);
- },
- methods: {
- getData(){
- if (this.currentTab === 'today'){
- this.fetchDispatchedData();
- }else{
- this.fetchUnDispatchedData();
- }
- this.fetchStatistics();
- this.fetchCount();
- },
- fetchStatistics() {
- this.loading = true;
- const url = "{:url('AiStatistics/statisticsData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- success: (res) => {
- this.done = res.done;
- this.undo = res.undo;
- this.loading = false;
- },
- error: function(xhr, status, error) {
- this.loading = false;
- console.error('请求失败:', error);
- }
- });
- },
- fetchEchart() {
- this.loading3 = true;
- const url = "{:url('AiStatistics/chartData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- data:{
- type:this.chartTab
- },
- success: (res) => { // 使用箭头函数
- this.aiList = res.ai;
- this.userList = res.user;
- this.date = res.date
- this.initEchart();
- },
- error: function(xhr, status, error) {
- console.error('请求失败:', error);
- }
- });
- },
- fetchDispatchedData() {
- this.tableData = [];
- this.tableLoading = true;
- const url = "{:url('AiStatistics/dispatchedData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- data:{
- page:this.currentPage,
- size:this.pageSize,
- mode:this.mode
- },
- success: (res) => { // 使用箭头函数
- this.tableData = res.data;
- this.total = res.total;
- this.tableLoading = false;
- },
- error: function(xhr, status, error) {
- this.tableLoading = false;
- console.error('请求失败:', error);
- }
- });
- },
- fetchUnDispatchedData() {
- this.tableData = [];
- this.tableLoading = true;
- const url = "{:url('AiStatistics/unDispatchedData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- data:{
- page:this.currentPage,
- size:this.pageSize,
- type:this.currentTab,
- },
- success: (res) => { // 使用箭头函数
- this.tableData = res.data;
- this.total = res.total;
- this.tableLoading = false;
- },
- error: function(xhr, status, error) {
- this.tableLoading = false;
- console.error('请求失败:', error);
- }
- });
- },
- fetchCount() {
- const url = "{:url('AiStatistics/countData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- success: (res) => { // 使用箭头函数
- this.updateCountByValue('today', res.today);
- this.updateCountByValue('wait', res.wait);
- this.updateCountByValue('error', res.error);
- },
- error: function(xhr, status, error) {
- console.error('请求失败:', error);
- }
- });
- },
- fetchStaffData() {
- this.staffLoading = true;
- const url = "{:url('AiStatistics/staffData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- success: (res) => { // 使用箭头函数
- this.bxInfo = res.bxInfo;
- this.bjInfo = res.bjInfo;
- this.ysInfo = res.ysInfo;
- this.abInfo = res.abInfo;
- this.staffData = res.staffData;
- this.staffSummary = res.staffSummary;
- this.initStaffChart();
- },
- error: function(xhr, status, error) {
- this.staffLoading = false;
- console.error('请求失败:', error);
- }
- });
- },
- fetchOrderData() {
- this.orderLoading = true;
- const url = "{:url('AiStatistics/orderData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- data:{
- type:this.orderTab
- },
- success: (res) => { // 使用箭头函数
- this.orderAi = res.ai;
- this.orderUser = res.user;
- this.modes = res.modes;
- this.initOrderChart();
- },
- error: function(xhr, status, error) {
- this.orderLoading = false;
- console.error('请求失败:', error);
- }
- });
- },
- fetchUserData() {
- this.userData = [];
- this.userLoading = true;
- const url = "{:url('AiStatistics/userData')}";
- $.ajax({
- url: url,
- type: 'POST',
- dataType: 'json',
- data:{
- mode:this.roleTab,
- page: this.userCurrentPage
- },
- success: (res) => { // 使用箭头函数
- this.userLoading = false;
- this.userData = res.data;
- this.userTotal = res.total
- },
- error: function(xhr, status, error) {
- this.userLoading = false;
- console.error('请求失败:', error);
- }
- });
- },
- handlePageChange(page) {
- this.currentPage = page;
- if (this.currentTab === 'today'){
- this.fetchDispatchedData();
- }else{
- this.fetchUnDispatchedData();
- }
- },
- handleSizeChange(val) {
- this.pageSize = val;
- if (this.currentTab === 'today'){
- this.fetchDispatchedData();
- }else{
- this.fetchUnDispatchedData();
- }
- },
- handleModeChange(val) {
- layer.open({
- type: 2,
- title: "历史派单",
- shadeClose: true,
- shade: 0.3,
- maxmin: true,
- area: ['90%', '90%'],
- content: "{:url('history')}",
- end: function () {
- // window.location.reload();
- }
- });
- },
- handleUserPageChange(page){
- this.userCurrentPage = page;
- this.fetchUserData()
- },
- handleModeChange2(val) {
- layer.open({
- type: 2,
- title: "待派订单",
- shadeClose: true,
- shade: 0.3,
- maxmin: true,
- area: ['90%', '90%'],
- content: "{:url('UnDispatched')}",
- end: function () {
- // window.location.reload();
- }
- });
- },
- changeTab(item) {
- if (this.currentTab === item.value) return;
- this.currentPage = 1;
- this.currentTab = item.value;
- this.fetchCount();
- if (this.currentTab === 'today'){
- this.fetchDispatchedData();
- }else{
- this.fetchUnDispatchedData();
- }
- },
- changeChartTab(item) {
- if (this.chartTab === item.value) return;
- this.chartTab = item.value;
- this.fetchEchart();
- },
- changeOrderTab(item) {
- if (this.orderTab === item.value) return;
- this.orderTab = item.value;
- this.fetchOrderData();
- },
- changeRoleTab(item) {
- if (this.roleTab === item.value) return;
- this.userCurrentPage = 1;
- this.roleTab = item.value;
- this.fetchUserData();
- },
- getFontSize(item){
- const text = `${item.label}(${item.count})`;
- const len = text.length;
- if(len <= 10) return '16px';
- if(len <= 15) return '14px';
- if(len <= 20) return '12px';
- return '10px';
- },
- initEchart() {
- // 左侧折线图
- var chart = echarts.init(document.getElementById('chart'));
- window.addEventListener('resize', () => {
- chart.resize();
- });
- var option = {
- grid:{
- left:40,
- right:100,
- bottom:-5,
- containLabel:true
- },
- tooltip:{trigger:'axis'},
- legend:{data:['AI派单','人工派单']},
- xAxis:{type:'category', splitLine: {show: false}, data:this.date},
- yAxis: {
- type: 'value',
- splitLine: { show: false },
- name: '',
- nameTextStyle: {
- fontSize: 15,
- color: '#333',
- }
- },
- series:[
- { name:'AI派单', type:'line',symbolSize: 10, data:this.aiList, smooth:false , itemStyle:{color:'#7000FBFF'}, areaStyle:{color: {
- type: 'linear',
- x: 0, y: 0,
- x2: 0, y2: 1, // 从左到右
- colorStops: [
- { offset: 0, color: '#eee0ffFF' },
- { offset: 1, color: '#7000fb03' }
- ]
- }}},
- { name:'人工派单', type:'line',symbolSize: 10, data:this.userList, smooth:false, itemStyle:{color:'#0062FBFF'},areaStyle: {
- color: {
- type: 'linear',
- x: 0, y: 0,
- x2: 0, y2: 1, // 从左到右
- colorStops: [
- { offset: 0, color: '#a9cbffFF' },
- { offset: 1, color: '#ffffff03' }
- ]
- }
- }}
- ]
- };
- chart.setOption(option);
- this.loading3 = false;
- },
- initStaffChart() {
- const chart = echarts.init(this.$refs.staffChart)
- chart.setOption({
- tooltip: {
- trigger: 'item'
- },
- series:[
- {
- name: '在岗人数',
- type:'pie',
- radius:['65%','90%'],
- avoidLabelOverlap:true,
- label:{
- show:true,
- position:'center',
- formatter: `在岗人数\n${this.staffSummary.active} / ${this.staffSummary.total}`,
- fontSize:22,
- fontWeight:'bold',
- lineHeight:34
- },
- data:this.staffData
- }
- ]
- })
- this.staffLoading = false;
- },
- initOrderChart() {
- const chart = echarts.init(this.$refs.orderChart)
- chart.setOption({
- grid:{
- left:10,
- right:10,
- top:40,
- bottom:-5,
- containLabel:true
- },
- tooltip:{
- trigger:'axis'
- },
- legend:{
- top:0
- },
- xAxis:{
- type:'category',
- splitLine: { show: false },
- data:this.modes
- },
- yAxis:{
- splitLine: { show: false },
- type:'value'
- },
- series:[
- {
- name:'AI派单',
- type:'bar',
- barWidth:14,
- itemStyle:{
- normal: {
- barBorderRadius: [10, 10, 0, 0],
- color:new echarts.graphic.LinearGradient(
- 0,0,0,1,
- [
- {offset:0,color:'#5F5BFF'},
- {offset:1,color:'#B046FF'}
- ]
- )
- },
- },
- barCategoryGap: "50%",
- data:this.orderAi
- },
- {
- name:'人工派单',
- type:'line',
- smooth:true,
- symbol:'circle',
- symbolSize:8,
- itemStyle:{
- color:'#2A8CFF'
- },
- areaStyle:{
- color:new echarts.graphic.LinearGradient(
- 0,0,0,1,
- [
- {
- offset:0,
- color:'rgba(42,140,255,.25)'
- },
- {
- offset:1,
- color:'rgba(42,140,255,0)'
- }
- ]
- )
- },
- data:this.orderUser
- }
- ]
- })
- this.orderLoading = false;
- },
- observe(refName, callback) {
- const observer = new IntersectionObserver(entries => {
- if (entries[0].isIntersecting) {
- callback()
- observer.disconnect()
- }
- }, { threshold: 0.1 })
- observer.observe(this.$refs[refName])
- },
- updateCountByValue(value, newCount) {
- const item = this.tabs.find(tab => tab.value === value);
- if (item) {
- const oldCount = item.count; // 保存旧值
- item.count = newCount;
- this.$nextTick(() => {
- const el = this.$refs[`count_${value}`];
- if (el && el[0]) {
- this.animateNumber(el[0], oldCount, newCount, 1000);
- }
- });
- }
- },
- animateNumber(el, start, end, duration = 1000, callback = null) {
- if (start === end) {
- el.textContent = this.formatNumber(end);
- if (callback) callback();
- return;
- }
- const startTime = performance.now();
- const diff = end - start;
- const update = (currentTime) => {
- let progress = Math.min((currentTime - startTime) / duration, 1);
- const easeOut = 1 - Math.pow(1 - progress, 3);
- const current = Math.round(start + diff * easeOut);
- // 格式化显示
- el.textContent = this.formatNumber(current);
- if (progress < 1) {
- requestAnimationFrame(update);
- } else {
- el.textContent = this.formatNumber(end);
- if (callback) callback();
- }
- };
- requestAnimationFrame(update);
- },
- formatNumber(num) {
- return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
- },
- layerOpen(id){
- layer.open({
- type: 2,
- title: "详情",
- shadeClose: true,
- shade: 0.3,
- maxmin: true,
- area: ['80%', '80%'],
- content: "{:url('orders/detail2',[],'')}/id/"+id,
- end: function () {
- // window.location.reload();
- }
- });
- },
- send(id,mode,type){
- const self = this;
- layer.open({
- type: 2,
- title: "派单",
- shadeClose: true,
- shade: 0.3,
- maxmin: true,
- area: ['80%', '80%'],
- content: "{:url('send',[],'')}/id/"+id+"/mode/"+mode+"/type/"+type,
- end: function () {
- self.tableLoading = true;
- if (type === 0){
- self.fetchDispatchedData();
- }else{
- self.fetchUnDispatchedData();
- }
- }
- });
- },
- },
- });
- </script>
- <script>
- /**
- * 菜单配置
- */
- var menuConfig = {
- dispatch: [
- {
- title:'待派单列表',
- url:'UnDispatched.html'
- },
- {
- title:'已派单列表',
- url:'history.html'
- },
- {
- title:'异常单列表',
- url:"{:url('abnormal',['type'=>1])}"
- },
- {
- title:'保洁单列表',
- url:"{:url('orders/index',['mode'=>2])}"
- },
- {
- title:'运送单列表',
- url: "{:url('orders/index',['mode'=>3])}"
- },
- {
- title:'维修单列表',
- url:"{:url('orders/index',['mode'=>1])}"
- },
- {
- title:'安保单列表',
- url:"{:url('orders/index',['mode'=>4])}"
- }
- ],
- setting: [
- {
- title:'基础设置',
- url:'config.html'
- },
- {
- title:'人员技能标签',
- url:'userskill.html'
- },
- {
- title:'维修部门负责人',
- url:'dep.html'
- },
- {
- title:'运送地点负责人',
- url:'address.html'
- }
- ]
- };
- /**
- * 渲染菜单
- */
- function renderSidebar(type){
- showLoading('一大批数据正在赶来...');
- var menus = menuConfig[type];
- var html='';
- $.each(menus,function(index,item){
- html += `
- <div
- class="menu-item ${index===0?'active':''}"
- data-url="${item.url}">
- ${item.title}
- </div>
- `;
- });
- $('.sidebar').html(html);
- if(menus.length){
- $('#contentFrame').attr(
- 'src',
- menus[0].url
- );
- }
- }
- $('#contentFrame').on('load', function () {
- hideLoading();
- });
- /**
- * 顶部菜单切换
- */
- $('.top-item').click(function(){
- $('.top-item').removeClass('active');
- $(this).addClass('active');
- var type = $(this).data('type');
- if(type === 'ai'){
- $('#mainContainer').hide();
- $('#aiContainer').show();
- return;
- }
- $('#aiContainer').hide();
- $('#mainContainer').show();
- renderSidebar(type);
- });
- /**
- * 左侧菜单切换
- */
- $(document).on(
- 'click',
- '.menu-item',
- function(){
- $('.menu-item').removeClass('active');
- $(this).addClass('active');
- showLoading('一大批数据正在赶来...');
- $('#contentFrame').attr(
- 'src',
- $(this).data('url')
- );
- }
- );
- var loadingStart = 0;
- function showLoading(text){
- loadingStart = Date.now();
- $('#pageLoading').show();
- if(text){
- $('.loading-text').text(text);
- }
- }
- function hideLoading(){
- var spend = Date.now() - loadingStart;
- var delay = Math.max(0,300-spend);
- setTimeout(function(){
- $('#pageLoading').fadeOut(200);
- },delay);
- }
- </script>
- </body>
- </html>
|