From 0ce559e6195a189ccc777b0fa439906bffb12b55 Mon Sep 17 00:00:00 2001
From: zhang_12370 <z2864490065@outlook.com>
Date: 星期三, 25 六月 2025 17:58:31 +0800
Subject: [PATCH] 多页面添加查看功能

---
 src/components/dialog/Descriptions.vue |  256 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 256 insertions(+), 0 deletions(-)

diff --git a/src/components/dialog/Descriptions.vue b/src/components/dialog/Descriptions.vue
new file mode 100644
index 0000000..dd53b35
--- /dev/null
+++ b/src/components/dialog/Descriptions.vue
@@ -0,0 +1,256 @@
+<template>
+  <el-dialog v-model="descriptionsVisible" :title="title" width="60%" :close-on-click-modal="false">
+    <el-card>
+      <el-descriptions
+        class="margin-top"
+        :title="descriptionsTitle"
+        :column="column"
+        :size="size"
+        :border="border"
+      >
+        <template v-if="showOperations" #extra>
+          <slot name="extra">
+            <el-button type="primary" @click="handleEdit" v-if="!isViewOnly">缂栬緫</el-button>
+          </slot>
+        </template>        <!-- 鍔ㄦ�佹覆鏌撴墍鏈夋暟鎹」 -->
+        <el-descriptions-item 
+          v-for="(item, key) in filteredData" 
+          :key="`desc-item-${key}`"
+          :label="getFieldLabel(key)"
+          :span="getFieldSpan(key)"
+        >
+          {{ formatValue(item, key) }}
+        </el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+    
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose">鍏抽棴</el-button>
+        <el-button v-if="!isViewOnly" type="primary" @click="handleEdit">缂栬緫</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { defineProps, computed } from "vue";
+
+const props = defineProps({
+  // 寮圭獥鏍囬
+  title: {
+    type: String,
+    default: "璇︽儏淇℃伅"
+  },
+  // 鏁版嵁瀵硅薄
+  formData: {
+    type: Object,
+    default: () => ({})
+  },
+  // 鏄惁涓烘煡鐪嬫ā寮�
+  isViewOnly: {
+    type: Boolean,
+    default: true
+  },
+  // 鎻忚堪缁勪欢鏍囬
+  descriptionsTitle: {
+    type: String,
+    default: ""
+  },
+  // 鍒楁暟
+  column: {
+    type: Number,
+    default: 2
+  },
+  // 灏哄
+  size: {
+    type: String,
+    default: "default",
+    validator: (value) => ["large", "default", "small"].includes(value)
+  },
+  // 鏄惁鏄剧ず杈规
+  border: {
+    type: Boolean,
+    default: true
+  },
+  // 鏄惁鏄剧ず鎿嶄綔鎸夐挳
+  showOperations: {
+    type: Boolean,
+    default: true
+  },
+  // 瀛楁鏄犲皠閰嶇疆 { key: { label: '鏄剧ず鍚嶇О', span?: 璺ㄥ垪鏁�, formatter?: 鏍煎紡鍖栧嚱鏁� } }
+  fieldConfig: {
+    type: Object,
+    default: () => ({})
+  },
+  // 闇�瑕佹帓闄ゆ樉绀虹殑瀛楁
+  excludeFields: {
+    type: Array,
+    default: () => ['id', 'createTime', 'updateTime', 'deleted']
+  },  // 闇�瑕佸寘鍚樉绀虹殑瀛楁锛堝鏋滆缃簡锛屽垯鍙樉绀鸿繖浜涘瓧娈碉級
+  includeFields: {
+    type: Array,
+    default: () => []
+  },
+  // 瀛楁鏍囩鏄犲皠琛� { key: '鏄剧ず鍚嶇О' }
+  fieldLabels: {
+    type: Object,
+    default: () => ({})
+  },
+  // 瀛楁鏄剧ず椤哄簭
+  fieldOrder: {
+    type: Array,
+    default: () => []
+  }
+});
+
+const descriptionsVisible = defineModel("descriptionsVisible", {
+  type: Boolean,
+  default: false,
+});
+
+const emit = defineEmits(["update:descriptionsVisible", "edit", "close"]);
+
+// 杩囨护鍚庣殑鏁版嵁
+const filteredData = computed(() => {
+  if (!props.formData || typeof props.formData !== 'object') {
+    return {};
+  }
+
+  const data = { ...props.formData };
+  let filteredResult = {};
+
+  // 濡傛灉鎸囧畾浜嗗寘鍚瓧娈碉紝鍒欏彧鏄剧ず杩欎簺瀛楁
+  if (props.includeFields.length > 0) {
+    props.includeFields.forEach(field => {
+      if (data.hasOwnProperty(field)) {
+        filteredResult[field] = data[field];
+      }
+    });
+  } else {
+    // 鍚﹀垯鎺掗櫎鎸囧畾瀛楁
+    Object.keys(data).forEach(key => {
+      if (!props.excludeFields.includes(key)) {
+        filteredResult[key] = data[key];
+      }
+    });
+  }
+
+  // 濡傛灉鎸囧畾浜嗗瓧娈甸『搴忥紝鍒欐寜椤哄簭閲嶆柊缁勭粐鏁版嵁
+  if (props.fieldOrder.length > 0) {
+    const orderedResult = {};
+    
+    // 鍏堟寜鎸囧畾椤哄簭娣诲姞瀛楁
+    props.fieldOrder.forEach(field => {
+      if (filteredResult.hasOwnProperty(field)) {
+        orderedResult[field] = filteredResult[field];
+      }
+    });
+    
+    // 鍐嶆坊鍔犳湭鍦ㄩ『搴忎腑鎸囧畾鐨勫叾浠栧瓧娈�
+    Object.keys(filteredResult).forEach(key => {
+      if (!props.fieldOrder.includes(key)) {
+        orderedResult[key] = filteredResult[key];
+      }
+    });
+    
+    return orderedResult;
+  }
+
+  return filteredResult;
+});
+
+// 鑾峰彇瀛楁鏄剧ず鏍囩
+const getFieldLabel = (key) => {
+  // 1. 浼樺厛浣跨敤 fieldConfig 涓殑鏍囩閰嶇疆
+  if (props.fieldConfig[key]?.label) {
+    return props.fieldConfig[key].label;
+  }
+  
+  // 2. 鍏舵浣跨敤浼犲叆鐨勫瓧娈垫槧灏勮〃
+  if (props.fieldLabels[key]) {
+    return props.fieldLabels[key];
+  }
+  
+  // 3. 鏈�鍚庝娇鐢ㄩ粯璁ょ殑瀛楁鍚嶈浆鎹紙椹煎嘲杞┖鏍硷級
+  return key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
+};
+
+// 鑾峰彇瀛楁璺ㄥ垪鏁�
+const getFieldSpan = (key) => {
+  return props.fieldConfig[key]?.span || 1;
+};
+
+// 鏍煎紡鍖栧��
+const formatValue = (value, key) => {
+  // 浼樺厛浣跨敤閰嶇疆鐨勬牸寮忓寲鍑芥暟
+  if (props.fieldConfig[key]?.formatter && typeof props.fieldConfig[key].formatter === 'function') {
+    return props.fieldConfig[key].formatter(value);
+  }
+
+  // 榛樿鏍煎紡鍖�
+  if (value === null || value === undefined || value === '') {
+    return '--';
+  }
+
+  // 鏁扮粍鏍煎紡鍖�
+  if (Array.isArray(value)) {
+    return value.join(', ');
+  }
+
+  // 瀵硅薄鏍煎紡鍖�
+  if (typeof value === 'object') {
+    return JSON.stringify(value);
+  }
+
+  // 鏃ユ湡鏍煎紡鍖�
+  if (key.toLowerCase().includes('time') || key.toLowerCase().includes('date')) {
+    try {
+      const date = new Date(value);
+      if (!isNaN(date.getTime())) {
+        return date.toLocaleString('zh-CN');
+      }
+    } catch (e) {
+      // 濡傛灉涓嶆槸鏈夋晥鏃ユ湡锛岃繑鍥炲師鍊�
+    }
+  }
+
+  return String(value);
+};
+
+// 澶勭悊缂栬緫鎸夐挳鐐瑰嚮
+const handleEdit = () => {
+  emit('edit', props.formData);
+};
+
+// 澶勭悊鍏抽棴
+const handleClose = () => {
+  descriptionsVisible.value = false;
+  emit('close');
+};
+</script>
+
+<style scoped>
+.margin-top {
+  margin-top: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 12px;
+}
+
+.cell-item {
+  display: flex;
+  align-items: center;
+}
+
+:deep(.el-descriptions__label) {
+  font-weight: 600;
+}
+
+:deep(.el-descriptions__content) {
+  word-break: break-word;
+}
+</style>

--
Gitblit v1.9.3