Browse Source

style: 调整表单样式

jiaxing.liao 1 month ago
parent
commit
2c4d4ea9a4
7 changed files with 542 additions and 216 deletions
  1. 2 0
      components.d.ts
  2. 23 14
      src/App.vue
  3. 38 3
      src/layout/index.vue
  4. 245 154
      src/views/home/index.vue
  5. 4 4
      src/views/process/index.vue
  6. 153 28
      src/views/quality/index.vue
  7. 77 13
      src/views/safety/index.vue

+ 2 - 0
components.d.ts

@@ -11,11 +11,13 @@ declare module 'vue' {
     CardTitle: typeof import('./src/components/CardTitle.vue')['default']
     Chart: typeof import('./src/components/Chart/index.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCascader: typeof import('element-plus/es')['ElCascader']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     Panel: typeof import('./src/components/Panel.vue')['default']

+ 23 - 14
src/App.vue

@@ -14,21 +14,30 @@ const baseWidth = 1920;
 const baseHeight = 1080;
 
 // 动态样式
-const styles = ref({
+const styles = ref<Record<string, string>>({
   width: `${baseWidth}px`,
   height: `${baseHeight}px`,
   transform: `scale(1) translate(-50%, -50%)`,
+  transformOrigin: "0 0",
 });
 
 // 计算缩放比例
 function calcScale() {
-  const scaleW = window.innerWidth / baseWidth;
-  const scaleH = window.innerHeight / baseHeight;
+  const { clientWidth, clientHeight } = document.documentElement;
+  // const scaleW = window.innerWidth / baseWidth;
+  // const scaleH = window.innerHeight / baseHeight;
+  const scale = clientHeight / baseHeight;
 
   styles.value = {
-    width: `${baseWidth}px`,
-    height: `${baseHeight}px`,
-    transform: `scale(${Math.min(scaleW, scaleH)}) translate(-50%, -50%)`,
+    position: 'absolute',
+      left: '50%',
+      top: '50%',
+      width: `${clientWidth * (1/scale)}px`,
+      height: `${baseHeight}px`,
+      overflow: "hidden",
+      boxShadow: "0 0 10px rgba(0, 0, 0, 0.1)",
+      transform: `scale(${scale}) translate(-50%, -50%)`,
+      transformOrigin: "0 0",
   };
 }
 
@@ -46,14 +55,14 @@ onBeforeUnmount(() => {
 
 <style lang="less">
 .page-container {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  transform-origin: 0 0;
-  font-family: 'Microsoft YaHei', sans-serif;
+  // position: absolute;
+  // top: 50%;
+  // left: 50%;
+  // width: 100%;
+  // height: 100%;
+  // overflow: hidden;
+  // transform-origin: 0 0;
+  // font-family: 'Microsoft YaHei', sans-serif;
   font-size: 14px;
   color: #fff;
   user-select: none;

+ 38 - 3
src/layout/index.vue

@@ -2,7 +2,7 @@
   <div class="layout">
     <div class="mask"></div>
     <div class="header">
-      <img class="header-bg" src="@/assets/images/header.png" alt="">
+      <img class="header-bg" src="@/assets/images/header.png" alt="" />
       <div class="menu">
         <div class="menu-item" :class="{ active: route.path === '/home' }">
           <router-link to="/home"><span>项目看板</span></router-link>
@@ -20,20 +20,55 @@
           <router-link to="/process"><span>进度管理</span></router-link>
         </div>
       </div>
+      <div class="absolute right-20px z-99">
+        <el-cascader
+          v-model="projectCode"
+          effect="dark"
+          :show-all-levels="false"
+          :options="options"
+          :props="{ label: 'prj_name', value: 'prj_code' }"
+          :popper-style="{
+            maxWidth: '500px'
+          }"
+        />
+      </div>
+      <div class="absolute left-20px z-99">
+        <el-button :icon="Back" circle @click="$router.back()" >
+        </el-button>
+      </div>
     </div>
     <div class="content">
-      <router-view></router-view>
+      <router-view :key="projectCode?.[1]"></router-view>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
 import { useRoute } from 'vue-router';
-import { ref, onBeforeUnmount } from 'vue';
+import { ref, onBeforeUnmount, provide } from 'vue';
+import { Back } from '@element-plus/icons-vue';
 import dayjs from 'dayjs';
+import { invoke } from '@/api';
 
 const route = useRoute();
 const time = ref(dayjs().format('YYYY-MM-DD dddd HH:mm:ss'));
+const projectCode = ref<string[]>();
+const options = ref();
+
+invoke({
+  interfaceCode: 'BigScreen.projectList',
+}).then((res: any) => {
+  options.value = (res || []).map((item: any) => ({
+    prj_name: item.text,
+    prj_code: item.com_code,
+    children: item.children,
+  }));
+  if(options.value?.[0].children?.length) {
+    projectCode.value = [options.value?.[0].prj_code, options.value?.[0].children[0].prj_code];
+  }
+});
+
+provide('projectCode', projectCode);
 
 const timer = setInterval(() => {
   time.value = dayjs().format('YYYY-MM-DD dddd HH:mm:ss');

+ 245 - 154
src/views/home/index.vue

@@ -5,31 +5,182 @@
       <CardTitle>工程概况</CardTitle>
       <ul class="list-none m-0 p-0 px-20px py-10px flex flex-col gap-y-10px">
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目名称</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目名称</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prj_name }}</span>
         </li>
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目经理</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目经理</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prj_manager_name }}</span>
         </li>
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目类型</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目类型</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prjs_type_desc }}</span>
         </li>
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目地点</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目地点</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prjs_address }}</span>
         </li>
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目规模</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目规模</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prjs_scale }}</span>
         </li>
         <li class="flex">
-          <span class="text-20px font-bold inline-block w-180px">项目投资额(万元)</span>
+          <span class="text-20px font-bold inline-block w-180px shrink-0">项目投资额(万元)</span>
           <span class="text-#ccc text-16px truncate">{{ dataSource?.gckk?.prjs_amount }}</span>
         </li>
       </ul>
 
+      <CardTitle>技术指标</CardTitle>
+      <el-descriptions size="large" :column="2" class="mt-20px">
+        <el-descriptions-item label="用地面积(㎡)">{{
+          dataSource?.jszb?.prjs_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="建筑占地面积(㎡)">{{
+          dataSource?.jszb?.build_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="地上总建筑面积(㎡)">{{
+          dataSource?.jszb?.ongrd_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="地下总建筑面积(㎡)">{{
+          dataSource?.jszb?.ungrd_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="计容面积(㎡)">{{
+          dataSource?.jszb?.calc_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="建筑密度(%)">{{
+          dataSource?.jszb?.build_density
+        }}</el-descriptions-item>
+        <el-descriptions-item label="容积率">{{
+          dataSource?.jszb?.plot_ratio
+        }}</el-descriptions-item>
+        <el-descriptions-item label="机动车停车位(个)">{{
+          dataSource?.jszb?.park_space
+        }}</el-descriptions-item>
+        <el-descriptions-item label="绿化面积(㎡)">{{
+          dataSource?.jszb?.gree_area
+        }}</el-descriptions-item>
+        <el-descriptions-item label="绿化率(%)">{{
+          dataSource?.jszb?.gree_rate
+        }}</el-descriptions-item>
+      </el-descriptions>
+
+      <CardTitle>人员数据</CardTitle>
+      <div class="w-full box-border pt-30px px-10px">
+        <div class="w-full flex justify-between px-20px box-border">
+          <div class="text-center">
+            <div class="text-#ccc text-14px mb-8px">在册人数</div>
+            <div class="text-20px font-bold">{{ dataSource?.rysj.num }}</div>
+          </div>
+          <!-- <div class="text-center">
+            <div class="text-#ccc text-14px mb-8px">今日未出勤人数</div>
+            <div class="text-20px font-bold">2550</div>
+          </div>
+          <div class="text-center">
+            <div class="text-#ccc text-14px mb-8px">今日出勤人数</div>
+            <div class="text-20px font-bold">2550</div>
+          </div> -->
+        </div>
+        <div class="flex h-260px">
+          <div class="flex-1">
+            <Chart
+              :options="
+                getPieOptions(
+                  (dataSource?.rysj.data || []).map((item) => ({
+                    label: item.title,
+                    value: item.num,
+                  })),
+                )
+              "
+            />
+          </div>
+          <div class="flex-1 flex flex-col items-center justify-center gap-y-10px">
+            <div
+              class="w-full flex items-center justify-between text-16px"
+              v-for="item in dataSource?.rysj.data || []"
+              :key="item.title"
+            >
+              <span class="text-right"
+                ><span class="point" style="background: #6ec44e"></span>{{ item.title }}</span
+              >
+              <span class="text-#6ec44e"
+                ><span class="text-20px inline-block mr-8px">{{ item.num }}</span
+                >人</span
+              >
+            </div>
+          </div>
+        </div>
+      </div>
+    </Panel>
+
+    <!-- 中间区域 -->
+    <div class="h-full box-border px-10px middle-content flex-1 flex flex-col gap-10px">
+      <CardTitle>
+        <div class="w-full flex justify-between items-center">
+          <span>全景预览</span>
+          <span class="flex gap-8px">
+            <el-switch />
+            <el-button type="text" @click="setPanoUrl">
+              <el-icon size="26px" style="color: #fff"><Tools /></el-icon>
+            </el-button>
+          </span>
+        </div>
+      </CardTitle>
+      <iframe :src="dataSource?.drone" frameborder="0" class="w-full flex-1"></iframe>
+      <div class="flex gap-8px">
+        <div class="flex-1">
+          <Panel>
+            <CardTitle>管理目标</CardTitle>
+            <ul class="list-none m-0 p-0 px-20px py-10px flex flex-col gap-y-10px">
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">工期目标</span>
+                <span class="text-#ccc text-16px truncate">{{
+                  dataSource?.glmb?.prjs_duration
+                }}</span>
+              </li>
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">文明工地目标</span>
+                <span class="text-#ccc text-16px truncate">{{
+                  dataSource?.glmb?.prjs_worksite
+                }}</span>
+              </li>
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">创新目标</span>
+                <span class="text-#ccc text-16px truncate">{{
+                  dataSource?.glmb?.prjs_innovation
+                }}</span>
+              </li>
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">质量目标</span>
+                <span class="text-#ccc text-16px truncate">{{
+                  dataSource?.glmb?.prjs_quality
+                }}</span>
+              </li>
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">绿色施工目标</span>
+                <span class="text-#ccc text-16px truncate">{{
+                  dataSource?.glmb?.prjs_safety
+                }}</span>
+              </li>
+              <li class="flex">
+                <span class="text-20px font-bold inline-block w-200px shrink-0">安全目标</span>
+                <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_green }}</span>
+              </li>
+            </ul>
+          </Panel>
+        </div>
+        <div class="flex-1">
+          <Panel>
+            <CardTitle>参建单位</CardTitle>
+            <div class="w-full h-200px">
+              <ScrollBoard :config="cjdwConfig" />
+            </div>
+          </Panel>
+        </div>
+      </div>
+    </div>
+
+    <!-- 右侧面板 -->
+    <Panel>
       <CardTitle>安全管理</CardTitle>
       <div class="w-full h-300px flex gap-20px">
         <div class="flex-1 flex flex-col items-center justify-center gap-y-10px">
@@ -149,163 +300,34 @@
           </div>
         </div>
       </div>
-    </Panel>
-
-    <!-- 中间区域 -->
-    <div class="h-full box-border px-10px middle-content flex-1 flex flex-col gap-10px">
-      <CardTitle>
-        <div class="w-full flex justify-between items-center">
-          <span>全景预览</span>
-          <el-button type="text" @click="setPanoUrl">
-            <el-icon size="26px" style="color: #fff"><Tools /></el-icon>
-          </el-button>
-        </div>
-      </CardTitle>
-      <iframe :src="dataSource?.drone" frameborder="0" class="w-full flex-1"></iframe>
-      <div>
-        <CardTitle>参建单位</CardTitle>
-        <el-table height="200" :data="dataSource?.cjdw || []">
-          <el-table-column label="序号">
-            <template #default="scope">{{ scope.$index + 1 }}</template>
-          </el-table-column>
-          <el-table-column label="单位名称" prop="unit_name"> </el-table-column>
-          <el-table-column label="参建单位" prop="part_notes"> </el-table-column>
-        </el-table>
-      </div>
-    </div>
-
-    <!-- 右侧面板 -->
-    <Panel>
-      <CardTitle>管理目标</CardTitle>
-      <ul class="list-none m-0 p-0 px-20px py-10px flex flex-col gap-y-10px">
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">工期目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_duration }}</span>
-        </li>
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">文明工地目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_worksite }}</span>
-        </li>
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">创新目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_innovation }}</span>
-        </li>
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">质量目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_quality }}</span>
-        </li>
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">绿色施工目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_safety }}</span>
-        </li>
-        <li class="flex">
-          <span class="text-20px font-bold inline-block w-200px">安全目标</span>
-          <span class="text-#ccc text-16px truncate">{{ dataSource?.glmb?.prjs_green }}</span>
-        </li>
-      </ul>
 
-      <CardTitle>人员数据</CardTitle>
+      <CardTitle>进度管理</CardTitle>
       <div class="w-full box-border pt-30px px-10px">
-        <div class="w-full flex justify-between px-20px box-border">
-          <div class="text-center">
-            <div class="text-#ccc text-14px mb-8px">在册人数</div>
-            <div class="text-20px font-bold">{{ dataSource?.rysj.num }}</div>
-          </div>
-          <!-- <div class="text-center">
-            <div class="text-#ccc text-14px mb-8px">今日未出勤人数</div>
-            <div class="text-20px font-bold">2550</div>
-          </div>
-          <div class="text-center">
-            <div class="text-#ccc text-14px mb-8px">今日出勤人数</div>
-            <div class="text-20px font-bold">2550</div>
-          </div> -->
-        </div>
-        <div class="flex h-260px">
-          <div class="flex-1">
-            <Chart
-              :options="
-                getPieOptions(
-                  (dataSource?.rysj.data || []).map((item) => ({
-                    label: item.title,
-                    value: item.num,
-                  })),
-                )
-              "
-            />
-          </div>
-          <div class="flex-1 flex flex-col items-center justify-center gap-y-10px">
-            <div
-              class="w-full flex items-center justify-between text-16px"
-              v-for="item in dataSource?.rysj.data || []"
-              :key="item.title"
-            >
-              <span class="text-right"
-                ><span class="point" style="background: #6ec44e"></span>{{ item.title }}</span
-              >
-              <span class="text-#6ec44e"
-                ><span class="text-20px inline-block mr-8px">{{ item.num }}</span
-                >人</span
-              >
-            </div>
-          </div>
-        </div>
+        <ScrollBoard :config="processConfig" />
       </div>
-
-      <CardTitle>技术指标</CardTitle>
-      <el-descriptions size="large" :column="2" class="mt-20px">
-        <el-descriptions-item label="用地面积(㎡)">{{
-          dataSource?.jszb?.prjs_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="建筑占地面积(㎡)">{{
-          dataSource?.jszb?.build_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="地上总建筑面积(㎡)">{{
-          dataSource?.jszb?.ongrd_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="地下总建筑面积(㎡)">{{
-          dataSource?.jszb?.ungrd_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="计容面积(㎡)">{{
-          dataSource?.jszb?.calc_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="建筑密度(%)">{{
-          dataSource?.jszb?.build_density
-        }}</el-descriptions-item>
-        <el-descriptions-item label="容积率">{{
-          dataSource?.jszb?.plot_ratio
-        }}</el-descriptions-item>
-        <el-descriptions-item label="机动车停车位(个)">{{
-          dataSource?.jszb?.park_space
-        }}</el-descriptions-item>
-        <el-descriptions-item label="绿化面积(㎡)">{{
-          dataSource?.jszb?.gree_area
-        }}</el-descriptions-item>
-        <el-descriptions-item label="绿化率(%)">{{
-          dataSource?.jszb?.gree_rate
-        }}</el-descriptions-item>
-      </el-descriptions>
     </Panel>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue';
+import { ref, inject, type Ref, computed } from 'vue';
 import Panel from '@/components/Panel.vue';
 import CardTitle from '@/components/CardTitle.vue';
 import Chart from '@/components/Chart/index.vue';
 import type { EChartsOption } from 'echarts';
-import { useRoute } from 'vue-router';
 import { invoke } from '@/api';
 import { useRequest } from 'vue-hooks-plus';
 import { Tools } from '@element-plus/icons-vue';
 import { ElMessage, ElMessageBox } from 'element-plus';
+import { ScrollBoard } from '@kjgl77/datav-vue3';
 
 type DataItem = {
   label: string;
   value: number;
 };
 
-const route = useRoute();
+const projectCode = inject<Ref<string[]>>('projectCode');
+
 const dataSource = ref<{
   // 无人机数据
   drone: string;
@@ -418,13 +440,47 @@ useRequest(invoke, {
       // 固定值
       interfaceCode: 'BigScreen.project',
       // 编号代码
-      projectCode: route.query?.projectCode as string,
+      projectCode: projectCode?.value?.[1],
     },
   ],
   onSuccess(res: any) {
     dataSource.value = res;
   },
-  pollingInterval: 10000
+  pollingInterval: 10000,
+});
+
+// 进度管理配置
+const processConfig = computed(() => {
+  const list = [];
+  return {
+    header: ['单体', '当前状态', '所属分类'],
+    data: list.map((item) => [item.title, item.num]),
+    index: false,
+    headerBGC: 'rgba(29, 66, 110, 0.6)',
+    evenRowBGC: 'rgba(29, 66, 110, 0.6)',
+    oddRowBGC: 'rgba(52, 139, 199, 0.0980392156862745)',
+    align: ['center', 'center'],
+    headerHeight: 30,
+    rowNum: 5,
+    waitTime: 5000,
+  };
+});
+
+// 参建单位
+const cjdwConfig = computed(() => {
+  const list = dataSource.value?.cjdw || [];
+  return {
+    header: ['序号', '单位名称'],
+    data: list.map((item, index) => [index, item.unit_name]),
+    index: false,
+    headerBGC: 'rgba(29, 66, 110, 0.6)',
+    evenRowBGC: 'rgba(29, 66, 110, 0.6)',
+    oddRowBGC: 'rgba(52, 139, 199, 0.0980392156862745)',
+    align: ['center', 'center'],
+    headerHeight: 30,
+    rowNum: 5,
+    waitTime: 5000,
+  };
 });
 
 const getPieOptions = (data: DataItem[]): EChartsOption => {
@@ -454,35 +510,36 @@ const getPieOptions = (data: DataItem[]): EChartsOption => {
 };
 
 const setPanoUrl = () => {
-   ElMessageBox.prompt('请输入无人机链接', '提示', {
+  ElMessageBox.prompt('请输入无人机链接', '提示', {
     confirmButtonText: '提交',
     cancelButtonText: '取消',
-    inputPattern: /^(https?:\/\/(([a-zA-Z0-9]+-?)+[a-zA-Z0-9]+\.)+[a-zA-Z]+)(:\d+)?(\/.*)?(\?.*)?(#.*)?$/,  // 链接正则
+    inputPattern:
+      /^(https?:\/\/(([a-zA-Z0-9]+-?)+[a-zA-Z0-9]+\.)+[a-zA-Z]+)(:\d+)?(\/.*)?(\?.*)?(#.*)?$/, // 链接正则
     inputErrorMessage: '地址校验失败',
-    inputValue: dataSource.value?.drone
+    inputValue: dataSource.value?.drone,
   })
     .then(({ value }) => {
       invoke({
-        "interfaceCode": "BigScreen.drone",
-        "projectCode": route.query?.projectCode,
-        "droneUrl": value
+        interfaceCode: 'BigScreen.drone',
+        projectCode: projectCode?.value?.[1],
+        droneUrl: value,
       }).then(() => {
         ElMessage({
           type: 'success',
           message: '修改成功',
         });
-        if(dataSource.value) {
+        if (dataSource.value) {
           dataSource.value.drone = value;
         }
-      })
+      });
     })
     .catch(() => {
       ElMessage({
         type: 'info',
         message: '已取消',
-      })
-    })
-}
+      });
+    });
+};
 </script>
 
 <style lang="less" scoped>
@@ -505,4 +562,38 @@ const setPanoUrl = () => {
     color: #ccc;
   }
 }
+
+:deep(.left-bottom-board .dv-scroll-board .header) {
+  height: 35px;
+}
+:deep(.left-bottom-board .dv-scroll-board .header-item) {
+  font-size: 17px !important;
+  color: #31e4cf !important;
+}
+
+:deep(.dv-scroll-board .header) {
+  height: 30px !important;
+  color: #31e4cf;
+}
+:deep(.dv-scroll-board .rows .ceil) {
+  font-size: 17px;
+  font-weight: 400;
+}
+:deep(.center-board .dv-scroll-board .rows .ceil) {
+  font-size: 16px;
+  color: rgba(247, 247, 247, 0.698039215686274);
+}
+:deep(.dv-scroll-ranking-board .ranking-info .rank) {
+  width: auto !important;
+  margin-right: 10px;
+}
+:deep(.dv-scroll-ranking-board .ranking-column) {
+  height: 14px;
+  border: none;
+  background-color: rgba(232, 232, 232, 0.27843137254902);
+}
+:deep(.dv-scroll-ranking-board .ranking-column .inside-column) {
+  height: 100%;
+  background-color: rgba(115, 235, 233, 1);
+}
 </style>

+ 4 - 4
src/views/process/index.vue

@@ -72,17 +72,17 @@
 </template>
 
 <script setup lang="ts">
-import { ref, computed } from 'vue';
+import { ref, computed, inject } from 'vue';
 import { ScrollBoard, DigitalFlop } from '@kjgl77/datav-vue3';
 import Panel from '@/components/Panel.vue';
 import CardTitle from '@/components/CardTitle.vue';
 import Chart from '@/components/Chart/index.vue';
 import type { EChartsOption } from 'echarts';
-import { useRoute } from 'vue-router';
 import { invoke } from '@/api';
 import { useRequest } from 'vue-hooks-plus';
+import type { Ref } from 'vue';
 
-const route = useRoute();
+const projectCode = inject<Ref<string[]>>('projectCode');
 const dataSource = ref<{
   // ac
   ac: string;
@@ -145,7 +145,7 @@ useRequest(invoke, {
       // 固定值
       interfaceCode: 'BigScreen.progressManagement',
       // 编号代码
-      projectCode: route.query?.projectCode as string,
+      projectCode: projectCode?.value?.[1],
     },
   ],
   onSuccess(res: any) {

+ 153 - 28
src/views/quality/index.vue

@@ -60,37 +60,34 @@
           </div>
         </div>
         <div class="flex-1">
-          <el-table stripe :data="dataSource?.zlwtlx.data || []">
-            <el-table-column align="center" label="名称" prop="title"></el-table-column>
-            <el-table-column align="center" label="数量" prop="num"></el-table-column>
-          </el-table>
+          <ScrollBoard :config="zlwtlxConfig" />
         </div>
       </div>
 
-      <CardTitle>问题预期单位排名</CardTitle>
-      <ul class="quality-sort h-310px overflow-auto list-none p-10px m-0 flex flex-col gap-y-4px">
-        <li
-          v-for="(item, index) in dataSource?.zgyqdwpm || []"
-          class="w-full h-30px bg-#348bc730 flex justify-between pr-12px leading-30px"
-        >
-          <span class="no inline-block w-30px h-30px text-center bg-#348bc730 mr-10px">{{ index + 1 }}</span>
-          <span class="name flex-1">{{ item.title }}</span>
-          <span class="value text-#77bef9">{{ item.num }}</span>
-        </li>
-      </ul>
+      <CardTitle>施工问题数量排名</CardTitle>
+      <div class="w-full h-310px">
+        <ScrollBoard :config="zgyqdwpmConfig" />
+      </div>
     </Panel>
 
     <!-- 中间区域 -->
-    <div class="h-full box-border px-10px middle-content flex-1 flex flex-col justify-end">
+    <div class="h-full box-border px-10px middle-content flex-1 flex flex-col justify-end gap-20px">
+      <div class="w-full flex-1">
+        <Panel style="width: 100%; overflow: hidden; display: flex; flex-direction: column;">
+          <CardTitle>质量总览</CardTitle>
+          <div class="w-full flex-1" ref="barchart">
+            <Chart :options="chartOptions" />
+          </div>
+        </Panel>
+      </div>
       <div class="w-940px h-300px">
         <Panel style="width: 100%; overflow: hidden;">
           <CardTitle>现场问题图片</CardTitle>
           <el-scrollbar>
             <div class="img-list h-240px w-full flex items-center gap-12px overflow-auto">
-              <img class="h-200px" v-for="item in dataSource?.xcwttp || []" :src="`/api/File/Download?fileId=${item.che_upload_photo}`" :alt="item.che_problem_typename"></img>
+              <img class="h-200px" v-for="item in dataSource?.xcwttp || []" :src="item.che_upload_photo" :alt="item.che_problem_typename"></img>
             </div>
           </el-scrollbar>
-          
         </Panel>
       </div>
     </div>
@@ -98,13 +95,11 @@
     <!-- 右侧面板 -->
     <Panel>
       <CardTitle>质量问题通报</CardTitle>
-      <el-table height="400" stripe :data="dataSource?.zlwttb || []">
-        <el-table-column align="center" label="问题描述" prop="description"></el-table-column>
-        <el-table-column align="center" label="发起时间" prop="description"></el-table-column>
-        <el-table-column align="center" label="责任单位" prop="part_abbreviation"></el-table-column>
-      </el-table>
+      <div class="w-full h-400px">
+        <ScrollBoard :config="zlwttbConfig" />
+      </div>
 
-      <CardTitle>分包问题数量统计</CardTitle>
+      <CardTitle>责任问题单位排名</CardTitle>
       <ul class="quality-statistics h-420px overflow-auto list-none p-10px m-0 flex flex-col gap-y-8px">
         <li
           v-for="(item, index) in dataSource?.fbwtsltj || []"
@@ -124,21 +119,22 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue';
+import { ref, inject, computed } from 'vue';
 import Panel from '@/components/Panel.vue';
 import CardTitle from '@/components/CardTitle.vue';
 import Chart from '@/components/Chart/index.vue';
 import type { EChartsOption } from 'echarts';
 import { invoke } from '@/api';
-import { useRoute } from 'vue-router';
 import { useRequest } from 'vue-hooks-plus';
+import type { Ref } from 'vue';
+import { ScrollBoard } from '@kjgl77/datav-vue3';
 
 type DataItem = {
   label: string;
   value: number;
 };
 
-const route = useRoute();
+const projectCode = inject<Ref<string[]>>('projectCode');
 const dataSource = ref<{
     // 质量问题状态
     "zlwtzt": {
@@ -210,13 +206,108 @@ const dataSource = ref<{
     ]
   }>();
 
+// 质量问题
+const zlwtlxConfig = computed(() => {
+  const list = dataSource.value?.zlwtlx.data || [];
+
+  return {
+    header: ['名称', '数量'],
+    data: list.map((item) => [item.title, item.num]),
+    index: false,
+    headerBGC: 'rgba(29, 66, 110, 0.6)',
+    evenRowBGC: 'rgba(29, 66, 110, 0.6)',
+    oddRowBGC: 'rgba(52, 139, 199, 0.0980392156862745)',
+    align: ['center', 'center'],
+    headerHeight: 30,
+    rowNum: 5,
+    waitTime: 5000,
+  };
+})  
+
+// 施工问题排名
+const zgyqdwpmConfig = computed(() => {
+  const list = dataSource.value?.zgyqdwpm || [];
+
+  return {
+    header: ['问题', '数量'],
+    data: list.map((item) => [item.title, item.num]),
+    index: false,
+    headerBGC: 'rgba(29, 66, 110, 0.6)',
+    evenRowBGC: 'rgba(29, 66, 110, 0.6)',
+  }
+})
+
+// 质量问题通报
+const zlwttbConfig = computed(() => {
+  const list = dataSource.value?.zlwttb || [];
+
+  return {
+    header: ['问题描述', '发起事件',  '责任单位'],
+    data: list.map((item) => [item.description, item.creation_time, item.part_abbreviation]),
+    index: false,
+    headerBGC: 'rgba(29, 66, 110, 0.6)',
+    evenRowBGC: 'rgba(29, 66, 110, 0.6)',
+  }
+})
+
+const chartOptions = computed((): EChartsOption => {
+  const list = dataSource.value?.dtbfbl || [];
+  return {
+    tooltip: {
+      trigger: 'item',
+      textStyle: { color: '#000' },
+    },
+    xAxis: {
+      type: 'value',
+      axisLabel: { color: '#fff' },
+    },
+    yAxis: {
+      type: 'category',
+      data: list.map((item) => item.title),
+      axisLabel: { color: '#fff' },
+    },
+    series: [
+      {
+        name: '进度',
+        type: 'bar',
+        data: list.map((item) => item.value),
+        barWidth: 16,
+        itemStyle: {
+          color: 'rgba(42, 254, 255, 1)',
+          borderRadius: [4, 4, 4, 4],
+        },
+        label: {
+          show: true,
+          position: 'right',
+          color: '#fff',
+          fontSize: 10,
+        },
+      },
+    ],
+    grid: {
+      top: '5%',
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true,
+    },
+    dataZoom: [
+      {
+        show: false,
+        type: 'slider',
+        yAxisIndex: 0, 
+      },
+    ],
+  }
+});
+
 useRequest(invoke, {
   defaultParams: [
     {
       // 固定值
       interfaceCode: 'BigScreen.qualityManagement',
       // 编号代码
-      projectCode: route.query?.projectCode as string,
+      projectCode: projectCode?.value?.[1],
     },
   ],
   onSuccess(res: any) {
@@ -323,4 +414,38 @@ const getPieOptions = (data: DataItem[]): EChartsOption => {
     }
   }
 }
+
+:deep(.left-bottom-board .dv-scroll-board .header) {
+  height: 35px;
+}
+:deep(.left-bottom-board .dv-scroll-board .header-item) {
+  font-size: 17px !important;
+  color: #31e4cf !important;
+}
+
+:deep(.dv-scroll-board .header) {
+  height: 30px !important;
+  color: #31e4cf; 
+}
+:deep(.dv-scroll-board .rows .ceil) {
+  font-size: 17px;
+  font-weight: 400;
+}
+:deep(.center-board .dv-scroll-board .rows .ceil) {
+  font-size: 16px;
+  color: rgba(247, 247, 247, 0.698039215686274);
+}
+:deep(.dv-scroll-ranking-board .ranking-info .rank) {
+  width: auto !important;
+  margin-right: 10px;
+}
+:deep(.dv-scroll-ranking-board .ranking-column) {
+  height: 14px;
+  border: none;
+  background-color: rgba(232, 232, 232, 0.27843137254902);
+}
+:deep(.dv-scroll-ranking-board .ranking-column .inside-column) {
+  height: 100%;
+  background-color: rgba(115, 235, 233, 1);
+}
 </style>

+ 77 - 13
src/views/safety/index.vue

@@ -41,23 +41,35 @@
         </div>
       </div>
 
-      <CardTitle>整改逾期单位排名</CardTitle>
+      <CardTitle>施工问题数量排名</CardTitle>
       <div class="text-white h-350px w-full pt-10px center-board right-top-board">
         <ScrollBoard :config="config1" @mouseover="mouseoverHandler" @click="clickHandler" />
       </div>
     </Panel>
 
     <!-- 中间区域 -->
-    <!-- <div
+    <div
       class="h-full box-border pr-10px pl-10px middle-content flex-1 flex flex-col gap-10px justify-center"
     >
-      <div class="">
-        <CardTitle>安全教育培训</CardTitle>
-        <div class="text-white h-470px w-full center-board">
-          <ScrollBoard :config="config2" @mouseover="mouseoverHandler" @click="clickHandler" />
-        </div>
+      <div class="w-full flex-1">
+        <Panel style="width: 100%; overflow: hidden; display: flex; flex-direction: column;">
+          <CardTitle>安全总览</CardTitle>
+          <div class="w-full flex-1" ref="barchart">
+            <Chart :options="chartOptions" />
+          </div>
+        </Panel>
+      </div>
+      <div class="w-940px h-300px">
+        <Panel style="width: 100%; overflow: hidden;">
+          <CardTitle>现场问题图片</CardTitle>
+          <el-scrollbar>
+            <div class="img-list h-240px w-full flex items-center gap-12px overflow-auto">
+              <img class="h-200px" v-for="item in dataSource?.xcwttp || []" :src="item.che_upload_photo" :alt="item.che_problem_typename"></img>
+            </div>
+          </el-scrollbar>
+        </Panel>
       </div>
-    </div> -->
+    </div>
 
     <!-- 右侧面板 -->
     <Panel>
@@ -66,7 +78,7 @@
         <ScrollBoard :config="config3" @mouseover="mouseoverHandler" @click="clickHandler" />
       </div>
 
-      <CardTitle>分包问题数量统计</CardTitle>
+      <CardTitle>责任问题单位排名</CardTitle>
       <div class="w-full box-border p-10px h-450px">
         <ScrollRankingBoard :config="config4" />
       </div>
@@ -75,15 +87,15 @@
 </template>
 
 <script setup lang="ts">
-import { ref, computed } from 'vue';
+import { ref, computed, inject } from 'vue';
 import { ScrollBoard, ScrollRankingBoard, DigitalFlop } from '@kjgl77/datav-vue3';
 import Panel from '@/components/Panel.vue';
 import CardTitle from '@/components/CardTitle.vue';
 import Chart from '@/components/Chart/index.vue';
 import type { EChartsOption } from 'echarts';
-import { useRoute } from 'vue-router';
 import { invoke } from '@/api';
 import { useRequest } from 'vue-hooks-plus';
+import type { Ref } from 'vue';
 
 type DataItem = {
   name: string;
@@ -91,7 +103,7 @@ type DataItem = {
   color: string;
 };
 
-const route = useRoute();
+const projectCode = inject<Ref<string[]>>('projectCode');
 const dataSource = ref<{
     // 安全问题状态
     "aqwtzt": {
@@ -163,6 +175,58 @@ const dataSource = ref<{
     ]
   }>();
 
+  const chartOptions = computed((): EChartsOption => {
+  const list = dataSource.value?.dtbfbl || [];
+  return {
+    tooltip: {
+      trigger: 'item',
+      textStyle: { color: '#000' },
+    },
+    xAxis: {
+      type: 'value',
+      axisLabel: { color: '#fff' },
+    },
+    yAxis: {
+      type: 'category',
+      data: list.map((item) => item.title),
+      axisLabel: { color: '#fff' },
+    },
+    series: [
+      {
+        name: '进度',
+        type: 'bar',
+        data: list.map((item) => item.value),
+        barWidth: 16,
+        itemStyle: {
+          color: 'rgba(42, 254, 255, 1)',
+          borderRadius: [4, 4, 4, 4],
+        },
+        label: {
+          show: true,
+          position: 'right',
+          color: '#fff',
+          fontSize: 10,
+        },
+      },
+    ],
+    grid: {
+      top: '5%',
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true,
+    },
+    dataZoom: [
+      {
+        show: false,
+        type: 'slider',
+        yAxisIndex: 0, 
+      },
+    ],
+  }
+});
+
+
 const data = computed(() => {
   const data = dataSource.value?.aqwtzt;
 
@@ -179,7 +243,7 @@ useRequest(invoke, {
       // 固定值
       interfaceCode: 'BigScreen.securityManagement',
       // 编号代码
-      projectCode: route.query?.projectCode as string,
+      projectCode: projectCode?.value?.[1],
     },
   ],
   onSuccess(res: any) {