zhou zhou
2 小时以前 89847f0c5a5d37e5a720afd32cdd7e4d9ead664b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<template>
  <div class="art-full-height flex flex-col gap-6">
    <section class="grid gap-6 md:grid-cols-2 xl:grid-cols-4" v-loading="sectionLoading.summary">
      <div
        v-for="item in overviewCards"
        :key="item.key"
        class="art-card flex cursor-pointer items-start justify-between rounded-3xl px-7 py-6"
        @click="navigateTo(item.route)"
      >
        <div class="min-w-0 pr-6">
          <p class="text-sm font-medium text-g-700">{{ item.title }}</p>
          <ArtCountTo
            class="mt-3 block text-[2.3rem] font-semibold leading-none text-g-900"
            :target="item.total"
            :duration="1200"
          />
          <div class="mt-4 flex items-center gap-2 text-sm">
            <span class="text-g-500">{{ item.badgeText }}</span>
            <span class="text-g-600">{{ item.subtitle }}</span>
          </div>
        </div>
        <div
          class="flex size-13 shrink-0 items-center justify-center rounded-2xl"
          :class="item.iconBoxClass"
        >
          <ArtSvgIcon :icon="item.icon" class="text-2xl" :class="item.iconClass" />
        </div>
      </div>
    </section>
 
    <section class="grid gap-6 xl:grid-cols-[0.92fr_1.08fr]">
      <div class="art-card h-98 p-5 box-border" v-loading="sectionLoading.summary">
        <div class="art-card-header">
          <div class="title">
            <h4>异常入口</h4>
            <p>聚合现有异常相关真实业务页</p>
          </div>
        </div>
 
        <div class="mt-3 grid gap-3">
          <button
            v-for="item in entryItems"
            :key="item.key"
            class="flex items-center justify-between rounded-2xl border border-[var(--art-border-color)] bg-[var(--art-main-bg-color)] px-4 py-4 text-left transition hover:border-[var(--el-color-primary-light-5)]"
            type="button"
            @click="navigateTo(item.route)"
          >
            <div class="flex min-w-0 items-center gap-3">
              <div
                class="flex size-11 shrink-0 items-center justify-center rounded-2xl bg-[var(--el-color-primary-light-9)]"
              >
                <ArtSvgIcon :icon="item.icon" class="text-xl text-[var(--el-color-primary)]" />
              </div>
              <div class="min-w-0">
                <p class="truncate text-sm font-medium text-[var(--art-gray-900)]">{{
                  item.title
                }}</p>
                <p class="mt-1 truncate text-xs text-g-500">{{ item.description }}</p>
              </div>
            </div>
            <div class="pl-3 text-right">
              <p class="text-2xl font-semibold text-[var(--art-gray-900)]">{{ item.count }}</p>
              <p class="mt-1 text-xs text-g-500">条记录</p>
            </div>
          </button>
        </div>
      </div>
 
      <div class="art-card h-98 p-5 box-border" v-loading="sectionLoading.summary">
        <div class="art-card-header">
          <div class="title">
            <h4>最近异常动态</h4>
            <p>来自盘点差异、质检、冻结库存、库位调整</p>
          </div>
        </div>
 
        <div class="mt-3 h-[calc(100%-3.75rem)] overflow-hidden">
          <ElScrollbar>
            <div
              v-for="item in activityItems"
              :key="item.key"
              class="flex items-start gap-4 border-b border-g-300 py-4 last:border-b-0"
            >
              <div class="flex flex-col items-center pt-1">
                <span class="size-3 rounded-full bg-[var(--el-color-danger)]"></span>
                <span class="mt-2 min-h-10 w-px bg-[var(--art-border-color)]"></span>
              </div>
              <div class="min-w-0 flex-1">
                <div class="flex items-center gap-2">
                  <p class="truncate text-base font-medium text-[var(--art-gray-900)]">{{
                    item.title
                  }}</p>
                  <ElTag size="small" effect="light" type="danger">{{ item.source }}</ElTag>
                </div>
                <p class="mt-2 text-sm text-g-600">{{ item.summary }}</p>
                <p class="mt-2 text-xs text-g-500">{{ item.time }}</p>
              </div>
              <ElButton text type="primary" @click="navigateTo(item.route)">查看</ElButton>
            </div>
 
            <ElEmpty v-if="!activityItems.length" description="暂无异常动态" :image-size="88" />
          </ElScrollbar>
        </div>
      </div>
    </section>
  </div>
</template>
 
<script setup>
  import { useRouter } from 'vue-router'
  import { withRequestGuard } from '@/utils/sys/requestGuard'
  import { fetchCheckDiffPage } from '@/api/check-diff'
  import { fetchQlyInspectPage } from '@/api/qly-inspect'
  import { fetchFreezePage } from '@/api/freeze'
  import { fetchLocRevisePage } from '@/api/loc-revise'
  import {
    ABNORMAL_PAGE_TITLE,
    buildAbnormalActivityItems,
    buildAbnormalEntryItems,
    buildAbnormalOverviewCards,
    createAbnormalOverviewState,
    normalizeSummaryResponse
  } from './abnormalPage.helpers'
 
  defineOptions({ name: 'AbnormalManage' })
 
  const router = useRouter()
  const sectionLoading = reactive({
    summary: false
  })
  const overviewState = ref(createAbnormalOverviewState())
 
  const overviewCards = computed(() => buildAbnormalOverviewCards(overviewState.value))
  const entryItems = computed(() => buildAbnormalEntryItems(overviewState.value))
  const activityItems = computed(() => buildAbnormalActivityItems(overviewState.value))
 
  onMounted(() => {
    document.title = `${ABNORMAL_PAGE_TITLE} - RSF Design`
    void loadOverview()
  })
 
  async function loadOverview() {
    sectionLoading.summary = true
 
    const [checkDiffResponse, qlyInspectResponse, freezeResponse, locReviseResponse] =
      await Promise.all([
        withRequestGuard(fetchCheckDiffPage({ current: 1, pageSize: 5 }), {
          records: [],
          total: 0
        }),
        withRequestGuard(fetchQlyInspectPage({ current: 1, pageSize: 5 }), {
          records: [],
          total: 0
        }),
        withRequestGuard(fetchFreezePage({ current: 1, pageSize: 5 }), { records: [], total: 0 }),
        withRequestGuard(fetchLocRevisePage({ current: 1, pageSize: 5 }), { records: [], total: 0 })
      ])
 
    overviewState.value = {
      checkDiff: normalizeSummaryResponse(checkDiffResponse),
      qlyInspect: normalizeSummaryResponse(qlyInspectResponse),
      freeze: normalizeSummaryResponse(freezeResponse),
      locRevise: normalizeSummaryResponse(locReviseResponse)
    }
 
    sectionLoading.summary = false
  }
 
  function navigateTo(path) {
    if (!path) return
    router.push(path)
  }
</script>