Blame view

pages/workbench/index.vue 15.5 KB
c293da23   刘淇   新园林init
1
  <template>
48ff5b95   刘淇   底部导航
2
    <view class="page-container">
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
3
      <!-- 加载页 -->
9b30ab8c   刘淇   新增快速工单,原版
4
      <up-loading-page
48ff5b95   刘淇   底部导航
5
          :loading="loading"
9b30ab8c   刘淇   新增快速工单,原版
6
7
          loading-text="加载中..."
          color="#577ee3"
48ff5b95   刘淇   底部导航
8
          zIndex="1000"
9b30ab8c   刘淇   新增快速工单,原版
9
10
      ></up-loading-page>
  
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
11
      <!-- 蓝色装饰块 -->
c64da17b   刘淇   新的业务线
12
      <view class="blue-decor-block" v-if="!loading">
e2e5221c   刘淇   验证码登录
13
14
        <text class="welcome-text u-line-1">你好{{ userInfo?.user?.nickname || '' }}</text>
        <text class="platform-name">蓟城山水全域智能运营管理平台</text>
12e66ec8   刘淇   新增树
15
      </view>
c293da23   刘淇   新园林init
16
  
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
17
      <!-- 内容容器 -->
37c26bd3   刘淇   巡查计划
18
      <view class="content-wrap">
ecbfbe06   刘淇   树巡检记录
19
        <!-- 空状态 -->
37c26bd3   刘淇   巡查计划
20
        <u-empty
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
21
            v-if="!filteredModuleList.length && !loading"
48ff5b95   刘淇   底部导航
22
            mode="permission"
37c26bd3   刘淇   巡查计划
23
24
        ></u-empty>
  
ecbfbe06   刘淇   树巡检记录
25
26
27
28
29
30
31
32
33
34
35
36
        <view class="" v-if="!userInfo?.user?.nickname">
          <text class="welcome-text u-line-1 " style="padding: 20px 0;text-align: center;">本小程序仅限特定服务人群使用,需验证账号后方可登录</text>
          <up-button
              class="login-btn"
              type="primary"
              size="large"
              @click="ToLoginPage"
              shape="circle"
          >
            前往登录
          </up-button>
        </view>
c64da17b   刘淇   新的业务线
37
  
ecbfbe06   刘淇   树巡检记录
38
        <!-- 菜单卡片列表 -->
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
39
        <view class="menu-card-wrap">
37c26bd3   刘淇   巡查计划
40
          <up-card
578c1373   刘淇   样式优化
41
42
              :title-size="14"
              :titleColor="'#000'"
48ff5b95   刘淇   底部导航
43
44
              :border="false"
              :shadow="true"
ecbfbe06   刘淇   树巡检记录
45
              :head-style="{ fontWeight:'500' }"
48ff5b95   刘淇   底部导航
46
              :foot-border-top="false"
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
47
              v-for="(parentModule, index) in filteredModuleList"
48ff5b95   刘淇   底部导航
48
              :key="`$parentModule.id_${index}`"
993d98fa   刘淇   工作台
49
              :title="parentModule.name"
48ff5b95   刘淇   底部导航
50
              class="card-container"
37c26bd3   刘淇   巡查计划
51
          >
37c26bd3   刘淇   巡查计划
52
            <template #body>
48ff5b95   刘淇   底部导航
53
54
55
56
57
58
              <view class="card-content">
                <view
                    v-for="(listItem, listIndex) in parentModule.children"
                    :key="listItem.id"
                    class="content-block"
                    @click="handleMenuClick(listItem)"
37c26bd3   刘淇   巡查计划
59
                >
48ff5b95   刘淇   底部导航
60
61
62
                  <u-image
                      :src="listItem.icon"
                      mode="aspectFit"
578c1373   刘淇   样式优化
63
64
                      width="48px"
                      height="48px"
48ff5b95   刘淇   底部导航
65
                      lazy-load
cf70629b   刘淇   养护计划 照片 自己写样式
66
                      radius="8px"
48ff5b95   刘淇   底部导航
67
68
69
70
                      class="block-icon"
                  ></u-image>
                  <text class="grid-text">{{ listItem.name }}</text>
                </view>
37c26bd3   刘淇   巡查计划
71
72
73
              </view>
            </template>
          </up-card>
c293da23   刘淇   新园林init
74
        </view>
ecbfbe06   刘淇   树巡检记录
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  
        <!-- 工单统计模块 -->
        <view v-if="isInspectorGlobal" class="work-order-container">
          <view class="header-row">
            <view class="stat-title-main">工单统计</view>
            <view class="date-picker-wrap">
              <neo-datetime-pro
                v-model="dateRange"
                type="daterange"
                :clearable="false"
                placeholder="请选择日期范围"
                @confirm="handleDateConfirm"
                :max-date="maxDate"
                @popup-show="handlePopupShow"
                @popup-hide="handlePopupHide"
              />
            </view>
          </view>
  
          <up-tabs :list="tabList" @click="handleTabChange" lineWidth="50"></up-tabs>
  
          <!-- 空数据提示 -->
          <view class="empty-tip" v-if="isEmptyData">
            暂无统计数据
          </view>
  
          <!-- 图表+图例 左右布局区域 -->
          <view class="chart-wrap" v-else>
            <!-- 左侧图表 -->
            <view class="charts-box">
              <qiun-data-charts
                v-if="!isDatePickerOpen"
                type="ring"
                :opts="chartOpts"
                :chartData="chartData"
              />
            </view>
            <!-- 右侧图例:垂直排列、均分高度 + 点击事件 -->
            <view class="legend-wrap">
              <view
                class="legend-item"
                v-for="(item, idx) in tableData"
                :key="idx"
                @click="handleLegendClick(item)"
              >
                <view class="legend-color" :style="{backgroundColor: COLOR_POOL[idx % COLOR_POOL.length]}"></view>
                <text class="legend-text">{{ item.companyName }}</text>
              </view>
            </view>
          </view>
  
          <!-- 统计表格 -->
          <view class="stat-table" v-if="!isEmptyData">
            <view class="table-header">
              <text class="table-col">公司名称</text>
              <text class="table-col">工单量</text>
              <text class="table-col">已完成</text>
              <text class="table-col">进行中</text>
            </view>
            <view
              class="table-row"
              v-for="(row, idx) in tableData"
              :key="idx"
            >
              <view class="table-col">
                <view class="dot" :style="{backgroundColor: COLOR_POOL[idx % COLOR_POOL.length]}"></view>
                {{ row.companyName }}
              </view>
              <text class="table-col">{{ row.total }}</text>
              <text class="table-col">{{ row.finish }}</text>
              <text class="table-col"> {{ row.ongoing }}</text>
            </view>
          </view>
        </view>
c293da23   刘淇   新园林init
149
150
151
152
      </view>
    </view>
  </template>
  
37c26bd3   刘淇   巡查计划
153
  <script setup lang="ts">
ecbfbe06   刘淇   树巡检记录
154
  import {ref, computed, reactive, watch} from 'vue';
578c1373   刘淇   样式优化
155
156
  import {onShow} from '@dcloudio/uni-app';
  import {useUserStore} from '@/pinia/user';
993d98fa   刘淇   工作台
157
158
  import globalConfig from '@/common/config/global';
  import cache from '@/common/utils/cache';
ecbfbe06   刘淇   树巡检记录
159
160
  import {timeFormat} from '@/uni_modules/uview-plus';
  import {iWorkOrderSummary} from "@/api/index/index";
37c26bd3   刘淇   巡查计划
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  
  interface MenuItem {
    id: number;
    name: string;
    subtitle?: string;
    type: number;
    sort: number;
    parentId: number;
    icon: string;
    jumpUrl: string;
    miniAppId?: string;
    badgeText?: string;
    badgeColor?: string;
    statisticCount: number | null;
    hasStatistic: boolean;
    extra: any;
    children: MenuItem[];
  }
c293da23   刘淇   新园林init
179
  
ecbfbe06   刘淇   树巡检记录
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  // 接口返回结构定义
  interface IOrderSummaryItem {
    companyName: string;
    companyId?: string | number;
    total: number;
    finish: number;
    ongoing: number;
    percent: number;
  }
  interface IOrderSummaryRes {
    totalNum: string | number;
    legend: string[];
    percents: number[];
    table: IOrderSummaryItem[];
  }
  
  // ========== 基础变量 ==========
9b30ab8c   刘淇   新增快速工单,原版
197
  const loading = ref(true);
c293da23   刘淇   新园林init
198
  const userStore = useUserStore();
37c26bd3   刘淇   巡查计划
199
  const moduleList = ref<MenuItem[]>([]);
12e66ec8   刘淇   新增树
200
  const userInfo = ref<any>(cache.get(globalConfig.cache.userInfoKey) || userStore.userInfo || {});
ecbfbe06   刘淇   树巡检记录
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  const isInspectorGlobal = ref(false);
  
  const dateRange = ref<string[]>([]);
  const maxDate = ref('');
  const isDatePickerOpen = ref(false);
  
  const activeTab = ref(0);
  const tabList = ref([
    { name: '部派工单' },
    { name: '子公司全量工单' }
  ]);
  
  // 颜色池,可随意增加颜色,自动循环复用
  const COLOR_POOL = ['#e80a0e', '#00f', '#0ff', '#EFD234', '#9c27b0'];
  
  // 接口返回业务数据
  const summaryData = reactive<IOrderSummaryRes>({
    totalNum: 0,
    legend: [],
    percents: [],
    table: []
  });
  
  // 计算属性:判断是否为空数据
  const isEmptyData = computed(() => {
    const num = Number(summaryData.totalNum);
    return num <= 0 || summaryData.table.length === 0;
  });
  const tableData = computed(() => summaryData.table);
37c26bd3   刘淇   巡查计划
230
  
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
231
232
  const filteredModuleList = computed(() => {
    return moduleList.value.filter(item => {
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
233
234
235
236
      return Array.isArray(item.children) && item.children.length > 0;
    });
  });
  
ecbfbe06   刘淇   树巡检记录
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  // ========== uCharts 图表配置 ==========
  const showDataLabel = ref(true);
  const chartOpts = ref({
    rotate: false,
    rotateLock: false,
    color: COLOR_POOL,
    dataLabel: showDataLabel.value,
    enableScroll: false,
    legend: {
      show: false,
      position: "right",
      lineHeight: 25
    },
    title: {
      name: "工单总量",
      fontSize: 12,
      color: "#666666"
    },
    subtitle: {
      name: "0",
      fontSize: 16,
      color: "#7cb5ec"
    },
    extra: {
      ring: {
        ringWidth: 15,
        activeOpacity: 0.5,
        activeRadius: 20,
        offsetAngle: 0,
        labelWidth: 5,
        border: true,
        borderWidth: 1,
        borderColor: "#FFFFFF",
        linearType: ""
      }
    }
  });
  
  const chartData = ref<any>({});
  
  // 组装图表数据
  const setChartData = () => {
    const seriesData = summaryData.table.map((item, idx) => {
      const percent = summaryData.percents[idx] ?? 0
      return {
        name: item.companyName || '未知',
        value: percent
      };
    });
    chartData.value = { series: [{ data: seriesData }] };
    chartOpts.value.subtitle.name = String(Number(summaryData.totalNum));
    chartOpts.value.dataLabel = showDataLabel.value;
  };
  
  // ========== 请求工单统计接口 ==========
  const getWorkOrderSummary = async () => {
    if (!dateRange.value.length) return;
    const [beginTime, endTime] = dateRange.value;
    const queryType = activeTab.value === 0 ? '1' : '0';
  
    try {
      const res = await iWorkOrderSummary({
        queryType,
        beginTime,
        endTime
      });
  
      summaryData.totalNum = res.totalNum;
      summaryData.legend = res.legend || [];
      summaryData.percents = res.percents || [];
      summaryData.table = res.table || [];
  
      setChartData();
    } catch (err) {
      console.error('获取工单统计失败:', err);
      uni.showToast({ title: '数据加载失败', icon: 'none' });
      summaryData.totalNum = 0;
      summaryData.legend = [];
      summaryData.percents = [];
      summaryData.table = [];
      setChartData();
    }
  };
  
  // ========== 事件方法 ==========
  const handlePopupShow = () => {
    isDatePickerOpen.value = true;
  };
  const handlePopupHide = () => {
    isDatePickerOpen.value = false;
  };
  const handleDateConfirm = (val: string[]) => {
    dateRange.value = val;
    getWorkOrderSummary();
  };
  
  // Tab 切换
  const handleTabChange = (item: any) => {
    activeTab.value = item.index;
    console.log(activeTab.value);
    
    getWorkOrderSummary();
  };
  
  // 初始化默认日期
  const initDefaultDate = () => {
    const today = new Date();
    maxDate.value = timeFormat(today, 'yyyy-mm-dd');
  
    const thirtyDaysAgo = new Date(today);
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
    dateRange.value = [
      timeFormat(thirtyDaysAgo, 'yyyy-mm-dd'),
      timeFormat(today, 'yyyy-mm-dd')
    ];
  };
  
  // 图例点击跳转工单页面
  const handleLegendClick = (item: IOrderSummaryItem) => {
    const [beginTime, endTime] = dateRange.value;
    const targetUrl = `/pages-sub/problem/regional-order-manage/list?companyId=${item.companyId}&companyName=${item.companyName}&beginTime=${beginTime}&endTime=${endTime}&queryType=${activeTab.value}`;
  
    uni.navigateTo({
      url: targetUrl,
      fail: () => {
        uni.showToast({ title: '跳转失败', icon: 'none' });
      }
    });
  };
  
37c26bd3   刘淇   巡查计划
367
  onShow(async () => {
c293da23   刘淇   新园林init
368
    try {
9b30ab8c   刘淇   新增快速工单,原版
369
      loading.value = true;
12e66ec8   刘淇   新增树
370
      userInfo.value = cache.get(globalConfig.cache.userInfoKey) || userStore.userInfo || {};
e6a04285   刘淇   单图情况 宽高70*70
371
  
e6a04285   刘淇   单图情况 宽高70*70
372
      const isLogin = () => {
e6a04285   刘淇   单图情况 宽高70*70
373
        const token = cache.get(globalConfig.cache.tokenKey) || userStore.token;
12e66ec8   刘淇   新增树
374
        const userInfoVal = userInfo.value;
12e66ec8   刘淇   新增树
375
        return !!token && !!userInfoVal;
e6a04285   刘淇   单图情况 宽高70*70
376
377
      };
  
e6a04285   刘淇   单图情况 宽高70*70
378
      if (!isLogin()) {
e6a04285   刘淇   单图情况 宽高70*70
379
        loading.value = false;
e6a04285   刘淇   单图情况 宽高70*70
380
381
382
        return;
      }
  
993d98fa   刘淇   工作台
383
      const rawMenuData = userStore.moduleListInfo || cache.get(globalConfig.cache.moduleListKey);
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
384
      moduleList.value = rawMenuData || [];
ecbfbe06   刘淇   树巡检记录
385
386
387
388
389
390
391
392
393
394
395
  
      // 支持两个角色查看工单统计
      const USER_ROLES = userStore.userInfo?.roles || [];
      isInspectorGlobal.value = USER_ROLES.includes('Inspector_global') || USER_ROLES.includes('Inspector_global_leader');
  //  isInspectorGlobal.value
      if(isInspectorGlobal.value){
        initDefaultDate();
        await getWorkOrderSummary();
      }
     
  
48ff5b95   刘淇   底部导航
396
      loading.value = false;
37c26bd3   刘淇   巡查计划
397
398
399
    } catch (error) {
      console.error('获取菜单数据失败:', error);
      moduleList.value = [];
9b30ab8c   刘淇   新增快速工单,原版
400
      loading.value = false;
c293da23   刘淇   新园林init
401
    }
37c26bd3   刘淇   巡查计划
402
  });
c293da23   刘淇   新园林init
403
  
ecbfbe06   刘淇   树巡检记录
404
405
406
407
408
409
410
411
412
  const ToLoginPage = () => {
    uni.reLaunch({
      url: '/pages/login/index',
      fail: (err) => {
        console.error('跳转登录页失败:', err);
        uni.showToast({ title: '跳转登录页异常', icon: 'none' });
      }
    });
  };
c64da17b   刘淇   新的业务线
413
  
37c26bd3   刘淇   巡查计划
414
415
  const handleMenuClick = (item: MenuItem) => {
    if (!item.jumpUrl) {
ecbfbe06   刘淇   树巡检记录
416
      uni.showToast({ title: '暂无跳转链接', icon: 'none', duration: 2000 });
37c26bd3   刘淇   巡查计划
417
      return;
c293da23   刘淇   新园林init
418
    }
37c26bd3   刘淇   巡查计划
419
420
421
422
    uni.navigateTo({
      url: item.jumpUrl,
      fail: (err) => {
        console.error('页面跳转失败:', err);
ecbfbe06   刘淇   树巡检记录
423
        uni.showToast({ title: '页面路径错误', icon: 'none', duration: 2000 });
37c26bd3   刘淇   巡查计划
424
425
      }
    });
c293da23   刘淇   新园林init
426
  };
ecbfbe06   刘淇   树巡检记录
427
428
429
430
431
432
433
  
  const goToQuickWorkOrder = () => { };
  const showDatePicker = () => { };
  
  watch(showDataLabel, () => {
    chartOpts.value.dataLabel = showDataLabel.value;
  });
c293da23   刘淇   新园林init
434
435
  </script>
  
48ff5b95   刘淇   底部导航
436
  <style scoped lang="scss">
48ff5b95   刘淇   底部导航
437
  .page-container {
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
438
439
    position: relative;
    min-height: 100vh;
5cb33b90   刘淇   完成巡查计划 详情
440
  }
37c26bd3   刘淇   巡查计划
441
  
37c26bd3   刘淇   巡查计划
442
443
444
445
446
  .blue-decor-block {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
24c0bbe7   刘淇   登录账号密码 加密存储
447
    padding: 80px 15px 115px;
12e66ec8   刘淇   新增树
448
449
    background: url("https://img.jichengshanshui.com.cn:28207/appimg/bg.jpg") no-repeat;
    background-size: 100% 100%;
37c26bd3   刘淇   巡查计划
450
    z-index: 1;
578c1373   刘淇   样式优化
451
    color: #fff;
12e66ec8   刘淇   新增树
452
    text-align: left;
cf70629b   刘淇   养护计划 照片 自己写样式
453
  
12e66ec8   刘淇   新增树
454
    .welcome-text {
4570c70a   刘淇   消息中心
455
      font-size: 16px;
12e66ec8   刘淇   新增树
456
      display: block;
24c0bbe7   刘淇   登录账号密码 加密存储
457
      margin-bottom: 4px;
12e66ec8   刘淇   新增树
458
459
460
461
    }
  
    .platform-name {
      margin-bottom: 10px;
4570c70a   刘淇   消息中心
462
      font-size: 16px;
12e66ec8   刘淇   新增树
463
      display: block;
12e66ec8   刘淇   新增树
464
    }
c293da23   刘淇   新园林init
465
  }
37c26bd3   刘淇   巡查计划
466
  
37c26bd3   刘淇   巡查计划
467
468
469
  .content-wrap {
    position: relative;
    z-index: 2;
24c0bbe7   刘淇   登录账号密码 加密存储
470
    padding: 125px 0 0;
48ff5b95   刘淇   底部导航
471
472
    display: flex;
    flex-direction: column;
cf70629b   刘淇   养护计划 照片 自己写样式
473
    gap: 10px;
48ff5b95   刘淇   底部导航
474
475
  }
  
48ff5b95   刘淇   底部导航
476
477
478
479
  .menu-card-wrap {
    width: 100%;
  }
  
48ff5b95   刘淇   底部导航
480
  .card-container {
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
481
    --u-card-content-padding: 0;
cf70629b   刘淇   养护计划 照片 自己写样式
482
    border-radius: 4px;
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
483
    overflow: hidden;
48ff5b95   刘淇   底部导航
484
485
  }
  
48ff5b95   刘淇   底部导航
486
487
  .card-content {
    display: flex;
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
488
    flex-wrap: wrap;
cf70629b   刘淇   养护计划 照片 自己写样式
489
    gap: 10px;
48ff5b95   刘淇   底部导航
490
491
  }
  
48ff5b95   刘淇   底部导航
492
  .content-block {
cf70629b   刘淇   养护计划 照片 自己写样式
493
    width: calc((100% - 3 * 10px) / 4);
48ff5b95   刘淇   底部导航
494
495
    display: flex;
    flex-direction: column;
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
496
497
    align-items: center;
    justify-content: center;
cf70629b   刘淇   养护计划 照片 自己写样式
498
499
    padding: 7px 0;
    border-radius: 4px;
48ff5b95   刘淇   底部导航
500
501
    touch-action: manipulation;
    transition: background-color 0.2s;
c293da23   刘淇   新园林init
502
  }
37c26bd3   刘淇   巡查计划
503
  
48ff5b95   刘淇   底部导航
504
505
506
  .content-block:active {
    background-color: #e9ecef;
  }
37c26bd3   刘淇   巡查计划
507
  
48ff5b95   刘淇   底部导航
508
  .block-icon {
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
509
510
    display: block;
    margin: 0 auto;
48ff5b95   刘淇   底部导航
511
512
  }
  
37c26bd3   刘淇   巡查计划
513
  .grid-text {
cf70629b   刘淇   养护计划 照片 自己写样式
514
    font-size: 13px;
578c1373   刘淇   样式优化
515
    color: #1C1C1C;
37c26bd3   刘淇   巡查计划
516
    text-align: center;
cf70629b   刘淇   养护计划 照片 自己写样式
517
    margin-top: 5px;
67af4c8e   刘淇   工作台 如果没有子节点就不渲染父节点
518
    display: block;
c293da23   刘淇   新园林init
519
  }
ecbfbe06   刘淇   树巡检记录
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  
  /* 工单模块 */
  .work-order-container {
    margin: 0 15px;
    background: #ffff;
    padding: 13px 15px;
  }
  
  .header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
  }
  
  .stat-title-main {
    font-size: 16px;
    font-weight: 600;
    color: #000;
  }
  
  .date-picker-wrap {
    padding: 2px 4px;
    border-radius: 3px;
    transition: background-color 0.2s;
    position: relative;
    z-index: 9999 !important;
    &:active {
      background-color: #f5f5f7;
    }
  }
  
  /* 空数据提示样式 */
  .empty-tip {
    text-align: center;
    padding: 60px 0;
    font-size: 14px;
    color: #999;
  }
  
  /* 图表+图例 左右布局核心样式 */
  .chart-wrap {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
  }
  
  /* 左侧图表容器 */
  .charts-box {
    width: 70%;
    height: 220px;
  }
  
  /* 右侧图例容器 */
  .legend-wrap {
    width: 30%;
    height: 220px;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
  }
  
  
  /* 单个图例项 */
  .legend-item {
    display: flex;
    align-items: center;
    padding: 4px 6px;
    border-radius: 4px;
    transition: background-color 0.2s;
    &:active {
      background-color: #f0f0f0;
    }
  }
  
  .legend-color {
    /* 固定尺寸,禁止压缩 */
    flex: 0 0 12px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    margin-right: 5px;
  }
  
  .legend-text {
    font-size: 13px;
    color: #333;
    /* 单行 + 溢出省略 */
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  
  /* 表格样式 */
  .stat-table {
    margin-top: 20px;
    border: 1px solid #eee;
    border-radius: 4px;
    overflow: hidden;
  }
  
  .table-header, .table-row {
    display: flex;
    align-items: center;
    padding: 10px 5px;
    border-bottom: 1px solid #eee;
    &:last-child {
      border-bottom: none;
    }
  }
  
  .table-header {
    background-color: #fafafa;
    font-weight: bold;
  }
  
  .table-col {
    flex: 1;
    text-align: center;
    font-size: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  
  /* 表格圆点 */
  .dot {
    flex: 0 0 10px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 5px;
  }
37c26bd3   刘淇   巡查计划
655
  </style>