啊鑫
2025-07-17 eaa506e57403d1b8502f16ca5dd6e82c347724d0
pages/QC/LLJ/Add.vue
@@ -89,11 +89,15 @@
         </select>
      </view>
      <view class="info-block" style="margin-top: 10px;">
               <view class="info-block" style="margin-top: 10px;">
          <view class="info-label">备注:</view>
          <input type="text" id="lotNo1" v-model="formData.lotNo1" 
                             placeholder="请输入备注信息" 
                             style="color: red; font-weight: bold;"/> 
      </view>
      <view class="info-block" style="margin-top: 10px;">
          <view class="info-label">破坏实验数量:</view>
          <view class="info-value highlight">{{formData.phsy}}</view>
      </view>
      
@@ -145,8 +149,10 @@
      <!-- 操作按钮区 -->
      <view class="action-buttons">
         <button class="secondary-btn" @click="addDestruction" v-if="this.current">破坏实验</button>
         <button class="secondary-btn" @click="uploadImages">上传/查看图片</button>
         <button class="secondary-btn" @click="fetchDrawingNumber">调取PLM图纸</button>
         <button class="secondary-btn" @click="viewAttachmentInfo">查看附件信息</button>
         <button class="secondary-btn" @click="addDefectDescription" v-if="this.current">添加不良描述</button>
         <button class="primary-btn" @click="submitInspection" v-if="this.current">检验提交</button>
      </view>
@@ -165,6 +171,21 @@
         </view>
      </view>
      
      <view v-if="destructionPopup" class="overlay">
         <view class="popup">
            <h3>破坏实验数量</h3>
            <form>
               <view class="form-group">
                  <label class="form-label">破坏实验数量:</label>
                  <input class="form-input" type="text" v-model="PHSY" placeholder="留空表示清除数量" />
               </view>
            </form>
            <div v-if="!isInteger" class="error-message">请输入整数值或留空</div>
            <button class="updateBut" @click="editDestruction">修改</button>
            <button @click="clearDestruction">清除</button>
            <button @click="destructionPopup = !destructionPopup">取消</button>
         </view>
      </view>
      
      <view class="barcode">
         <u-modal :show="drawingShow" title="图纸明细" @confirm="drawingConfirm" @cancel="drawingCancel"
@@ -192,6 +213,58 @@
               </uni-tr>
            </uni-table>
         </u-modal>
      </view>
      <!-- 附件详情弹窗 -->
      <view v-if="showAttachmentDetail" class="overlay">
         <view class="popup attachment-detail-popup">
            <h3 class="attachment-popup-title">附件详情</h3>
            <div class="attachment-popup-divider"></div>
            <div v-if="selectedAttachment" class="attachment-detail-content">
               <div class="attachment-detail-row"><span class="attachment-label">ID:</span><span>{{ Math.trunc(selectedAttachment.id) }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">附件名:</span><span>{{ selectedAttachment.fattach }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">类型:</span><span>{{ selectedAttachment.ftype }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">版本:</span><span>{{ selectedAttachment.fversion }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">受控日期:</span><span>{{ selectedAttachment.fdate }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">上传人:</span><span>{{ selectedAttachment.createBy }}</span></div>
               <div class="attachment-detail-row"><span class="attachment-label">上传时间:</span><span>{{ selectedAttachment.createDate }}</span></div>
               <div v-if="isPreviewable(selectedAttachment.fattach)" class="attachment-preview-area">
                  <div v-if="['pdf','jpg','jpeg','png','gif'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())">
                     <iframe :src="getAttachmentUrl(selectedAttachment)" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe>
                  </div>
                  <div v-else-if="['txt'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())">
                     <iframe :src="getAttachmentUrl(selectedAttachment)" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe>
                  </div>
                  <div v-else-if="['doc','docx','xls','xlsx'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())">
                     <iframe :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(getAttachmentUrl(selectedAttachment))" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe>
                  </div>
               </div>
               <div v-else class="attachment-download-area">
                  <button class="attachment-download-link" @click="downloadAttachment(selectedAttachment)">下载附件</button>
               </div>
            </div>
            <div v-else class="attachment-detail-empty">暂无附件信息</div>
            <button class="attachment-popup-close" @click="closeAttachmentDetail">返回附件列表</button>
         </view>
      </view>
      <!-- 附件列表弹窗 -->
      <view v-if="showAttachmentPopup" class="overlay">
         <view class="popup" style="width: 60vw; max-width: 500px;">
            <h3>附件列表</h3>
            <div v-if="attachmentsLoading">加载中...</div>
            <div v-else-if="attachments.length === 0">暂无附件</div>
            <ul class="attachment-list" v-else>
               <li v-for="item in attachments" :key="item.id">
                  <span class="attachment-name" @click="showAttachmentDetailDialog(item)">
                     {{ item.fattach }}
                  </span>
                  <div class="attachment-actions">
                     <button class="secondary-btn" @click="showAttachmentDetailDialog(item)">详情</button>
                     <button class="secondary-btn" @click="downloadAttachment(item)">下载</button>
                  </div>
               </li>
            </ul>
            <button class="attachment-popup-close" @click="closeAttachmentPopup">关闭</button>
         </view>
      </view>
   </view>
   
@@ -225,6 +298,8 @@
               permissionAccount: '',
               hasEmergencyPermission: false,
               showPopup: false,
               PHSY:'',
               EMERGENCY: '0',
               
            },
            tableData: [],
@@ -242,6 +317,14 @@
            fileName:'',
            originalRemarks: '',
            hasEmergencyPermission: false,
            destructionPopup: false,
            PHSY: '',
            isInteger: true,
            attachments: [],
            showAttachmentPopup: false,
            attachmentsLoading: false,
            selectedAttachment: null,
            showAttachmentDetail: false,
            
         }
      },
@@ -282,6 +365,10 @@
         }
          if (this.$loginInfo.account === 'PL017') {this.hasEmergencyPermission = true;}
          // 测试附件服务器连接
      },
      methods: {
         getStatusText(status) {
@@ -306,7 +393,8 @@
               data: {
                  itemNo: this.formData.itemId,
                  quantity: this.formData.fcovertQty,
                  releaseNo: this.formData.releaseNo
                  releaseNo: this.formData.releaseNo,
                  PHSY: this.formData.PHSY
               }
            }).then(res => {
               if (res.status == 0) {
@@ -402,7 +490,8 @@
                              staffNo: 'HMCS',
                              // staffNo: this.$loginInfo.account,
                              iqcStatus: this.PSTYPE,
                              department: this.DEPARTMENT
                              department: this.DEPARTMENT,
                              EMERGENCY: this.formData.emergencyStatus ? "1" : "0" // 确保紧急放行状态正确传递
                           };
                        }
                        else{
@@ -419,14 +508,16 @@
                              // staffNo: 'HMCS',
                              staffNo: this.$loginInfo.account,
                              iqcStatus: this.PSTYPE,
                              department: this.DEPARTMENT
                              department: this.DEPARTMENT,
                              EMERGENCY: this.formData.emergencyStatus ? "1" : "0" // 确保紧急放行状态正确传递
                           };
                        }
                        console.log(this.QcIssueResultDetailes)
                        console.log("提交的紧急放行状态:", this.formData.emergencyStatus ? "1" : "0");
                        console.log("完整的提交数据:", this.QcIssueResultDetailes);
                        const url = this.$store.state.serverInfo.serverAPI+`/QcIssueResult/GetProcessNo`;
                        // 发送 POST 请求
                        if (this.PSTYPE === '特采/让步使用') {// 发送 POST 请求
                        uni.request({
                           url: url, // 请求地址
                           method: 'POST', // 请求方法
@@ -443,7 +534,10 @@
                              // 如果有页面跳转,需要用定时器延迟
                              setTimeout(() => {
                                 uni.navigateTo({
                                 // 设置一个标记,告诉List页面需要刷新
                                 getApp().globalData = getApp().globalData || {};
                                 getApp().globalData.needRefreshList = true;
                                 uni.redirectTo({
                                    url: 'List'
                                 });
                              }, 2000); // 保持与 duration 相同的时长
@@ -458,7 +552,7 @@
                              });
                           }
                        });
                     }
                        uni.showToast({
                           title: res.message.toString(),
                           icon: 'success',
@@ -497,11 +591,11 @@
                     })
                     // 如果有页面跳转,需要用定时器延迟
                     setTimeout(() => {
                        uni.navigateTo({
                           url: 'List'
                        });
                        // 设置一个标记,告诉List页面需要刷新
                        getApp().globalData = getApp().globalData || {};
                        getApp().globalData.needRefreshList = true;
                        uni.navigateBack();
                     }, 2000); // 保持与 duration 相同的时长
                  } else {
                     uni.showModal({
                        title: "提示",
@@ -538,9 +632,14 @@
               if (data) {
                  this.formData = {
                     ...data,
                     emergencyStatus: data.emergency
                     emergencyStatus: data.emergency === 1 || data.emergency === "1" || data.emergency === true
                  };
                  // 确保PHSY字段被正确设置
                  this.formData.PHSY = data.PHSY;
                  console.log("加载的紧急放行状态:", this.formData.emergencyStatus);
                  this.$post({
                     url: "/LLJ/getJYItem",
                     data: {
@@ -593,58 +692,25 @@
            });
         },
         editRemarks() {
            if (this.remarks) {
               //saveRemarksGid
               this.$post({
                  url: "/LLJ/saveRemarksGid",
                  data: {
                     gid: this.formData.id,
                     remarks: this.remarks,
                     releaseNo: this.formData.releaseNo,
                  }
               }).then(res => {
                  if (res.data.tbBillList > 0) {
                     this.formData.remarks = this.remarks;
                     this.remarksPopup = !this.remarksPopup;
                     this.$showMessage("保存成功");
                     setTimeout(() => {
                        let pages = getCurrentPages();
                        let beforePage = pages[pages.length - 2];
                        uni.navigateBack({
                           delta: 1, //返回的页面数,如果为1表示返回上一页
                           success: (event) => {
                              beforePage.$vm.reload()
                           }
                        });
                     }, 2000);
                  }
               })
            } else {
               this.$post({
                  url: "/LLJ/saveRemarksGid",
                  data: {
                     gid: this.formData.id,
                     remarks: '',
                     releaseNo: this.formData.releaseNo,
                  }
               }).then(res => {
                  if (res.data.tbBillList > 0) {
                     this.formData.remarks = this.remarks;
                     this.remarksPopup = !this.remarksPopup;
                     this.$showMessage("保存成功");
                     setTimeout(() => {
                        let pages = getCurrentPages();
                        let beforePage = pages[pages.length - 2];
                        uni.navigateBack({
                           delta: 1, //返回的页面数,如果为1表示返回上一页
                           success: (event) => {
                              beforePage.$vm.reload()
                           }
                        });
                     }, 2000);
                  }
               })
            }
            // 保存不良描述
            this.$post({
               url: "/LLJ/saveRemarksGid",
               data: {
                  gid: this.formData.id,
                  remarks: this.remarks || '',
                  releaseNo: this.formData.releaseNo
                  // 不再包含PHSY字段
               }
            }).then(res => {
               if (res.data.tbBillList > 0) {
                  this.formData.remarks = this.remarks;
                  this.remarksPopup = !this.remarksPopup;
                  this.$showMessage("保存成功");
                  setTimeout(() => {
                     this.init();
                  }, 2000);
               }
            })
         },
         drawingConfirm() {
@@ -1050,6 +1116,9 @@
                                             this.formData.emergencyStatus = true;
                                    this.originalLotNo1 = lotNo1; 
                                    this.formData.lotNo1 = lotNo1;
                                    // 更新紧急放行状态,确保提交时能正确传递
                                    this.formData.EMERGENCY = "1";
                                             uni.showToast({
                                                 title: message || '紧急放行成功',
                                                 icon: 'success',
@@ -1096,6 +1165,9 @@
         
                                         if (result === "0") {
                                             this.formData.emergencyStatus = false;
                                    // 更新紧急放行状态,确保提交时能正确传递
                                    this.formData.EMERGENCY = "0";
                                             uni.showToast({
                                                 title: message || '撤回成功',
                                                 icon: 'success',
@@ -1122,64 +1194,170 @@
                     });
                 },
               editRemarks() {
                           if (this.remarks) {
                               // 只保存修改的部分
                               const modifiedRemarks = this.remarks !== this.originalRemarks ? this.remarks : '';
                               this.$post({
                                   url: "/LLJ/saveRemarksGid",
                                   data: {
                                       gid: this.formData.id,
                                       remarks: modifiedRemarks,
                                       releaseNo: this.formData.releaseNo,
                                   }
                               }).then(res => {
                                   if (res.data.tbBillList > 0) {
                                       this.formData.remarks = this.remarks;
                                       this.originalRemarks = this.remarks; // 更新原始备注值
                                       this.remarksPopup = !this.remarksPopup;
                                       this.$showMessage("保存成功");
                                       setTimeout(() => {
                                           let pages = getCurrentPages();
                                           let beforePage = pages[pages.length - 2];
                                           uni.navigateBack({
                                               delta: 1, //返回的页面数,如果为1表示返回上一页
                                               success: (event) => {
                                                   beforePage.$vm.reload()
                                               }
                                           });
                                       }, 2000);
                                   }
                               })
                           } else {
                               this.$post({
                                   url: "/LLJ/saveRemarksGid",
                                   data: {
                                       gid: this.formData.id,
                                       remarks: '',
                                       releaseNo: this.formData.releaseNo,
                                   }
                               }).then(res => {
                                   if (res.data.tbBillList > 0) {
                                       this.formData.remarks = this.remarks;
                                       this.originalRemarks = this.remarks; // 更新原始备注值
                                       this.remarksPopup = !this.remarksPopup;
                                       this.$showMessage("保存成功");
                                       setTimeout(() => {
                                           let pages = getCurrentPages();
                                           let beforePage = pages[pages.length - 2];
                                           uni.navigateBack({
                                               delta: 1, //返回的页面数,如果为1表示返回上一页
                                               success: (event) => {
                                                   beforePage.$vm.reload()
                                               }
                                           });
                                       }, 2000);
                                   }
                               })
                           }
                       },
                  // 保存不良描述
                  this.$post({
                     url: "/LLJ/saveRemarksGid",
                     data: {
                        gid: this.formData.id,
                        remarks: this.remarks || '',
                        releaseNo: this.formData.releaseNo
                        // 不再包含PHSY字段
                     }
                  }).then(res => {
                     if (res.data.tbBillList > 0) {
                        this.formData.remarks = this.remarks;
                        this.remarksPopup = !this.remarksPopup;
                        this.$showMessage("保存成功");
                        setTimeout(() => {
                           this.init();
                        }, 2000);
                     }
                  })
               },
         addDestruction() {
            // 添加破坏实验的逻辑
            this.destructionPopup = !this.destructionPopup;
            this.PHSY = this.formData.PHSY || '';
            this.isInteger = true;
         },
         editDestruction() {
            // 验证输入是否为整数
            if(this.PHSY === '') {
               this.isInteger = true;
               // 如果为空,传递空字符串,后端会处理为null
            } else {
               const isInteger = /^-?\d+$/.test(this.PHSY);
               this.isInteger = isInteger;
               if (!isInteger) {
                  return;
               }
            }
            // 保存破坏实验数量
            this.$post({
               url: "/LLJ/saveRemarksGid",
               data: {
                  gid: this.formData.id,
                  releaseNo: this.formData.releaseNo,
                  PHSY: this.PHSY // 可以是空字符串或有效整数
                  // 不再包含remarks字段
               }
            }).then(res => {
               if (res.data.tbBillList > 0) {
                  // 如果输入为空,设置为null以便不显示
                  this.formData.PHSY = this.PHSY === '' ? null : this.PHSY;
                  this.destructionPopup = false;
                  this.$showMessage("保存成功");
                  setTimeout(() => {
                     this.init();
                  }, 2000);
               }
            })
         },
         clearDestruction() {
            // 清除破坏实验数量
            this.PHSY = '';
            this.$post({
               url: "/LLJ/saveRemarksGid",
               data: {
                  gid: this.formData.id,
                  releaseNo: this.formData.releaseNo,
                  PHSY: '' // 空字符串,后端会处理为null
               }
            }).then(res => {
               if (res.data.tbBillList > 0) {
                  this.formData.PHSY = null; // 确保前端也为null,不显示
                  this.destructionPopup = false;
                  this.$showMessage("清除成功");
                  setTimeout(() => {
                     this.init();
                  }, 2000);
               }
            })
         },
         viewAttachmentInfo() {
            this.showAttachmentPopup = true; // 先弹窗
            this.attachmentsLoading = true;
            this.attachments = [];
            this.$post({
               url: "/LLJ/getAttachments",
               data: { releaseNo: this.formData.releaseNo }
            }).then(res => {
               this.attachmentsLoading = false;
               if (res.status === 0) {
                  this.attachments = res.data.tbBillList;
               } else if (res.status === 1 && res.message === "该检验单未上传附件信息!") {
                  uni.showToast({ title: res.message, icon: "none" });
               } else {
                  uni.showToast({ title: "获取附件失败", icon: "none" });
               }
            });
         },
         closeAttachmentPopup() {
            this.showAttachmentPopup = false;
         },
         getAttachmentUrl(item) {
            const baseUrl = "http://192.168.1.22:10054";
            // 去除所有空白字符(包括中英文空格、制表符等)
            let fileName = item.fattach.replace(/[\s\u3000]+/g, '').trim();
            return baseUrl + "/api/LLJ/DownloadAttachment?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName);
         },
         showAttachmentDetailDialog(item) {
            console.log('查看详情', item);
            this.selectedAttachment = item;
            this.showAttachmentPopup = false;
            this.showAttachmentDetail = true;
            console.log('showAttachmentDetail:', this.showAttachmentDetail);
         },
         closeAttachmentDetail() {
            this.showAttachmentDetail = false;
            this.selectedAttachment = null;
            this.showAttachmentPopup = true;
         },
         isPreviewable(filename) {
            if (!filename) return false;
            const ext = filename.trim().split('.').pop().toLowerCase();
            // 支持在线预览的文件类型
            return [
               'pdf', 'jpg', 'jpeg', 'png', 'gif', 'txt', 'doc', 'docx', 'xls', 'xlsx'
            ].includes(ext);
         },
         // 处理附件下载错误
         handleAttachmentError(item) {
            uni.showModal({
               title: '下载失败',
               content: `无法下载附件:${item.fattach}\n请检查网络连接或联系管理员`,
               showCancel: false
            });
         },
         downloadAttachment(item) {
            const baseUrl = "http://192.168.1.22:10054"; // 如有需要请改为你的后端实际地址
            // 去除所有空格、全角空格、回车、换行
            const fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim();
            const url = baseUrl + "/api/Llj/DownloadFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName);
            uni.downloadFile({
               url: url,
               success: (res) => {
                  if (res.statusCode === 200) {
                     if (typeof plus !== 'undefined' && plus.runtime && plus.runtime.openFile) {
                        plus.runtime.openFile({ path: res.tempFilePath }, () => {
                           uni.showToast({ title: '打开成功', icon: 'success' });
                        }, (e) => {
                           uni.showModal({ title: '提示', content: '文件下载成功,但无法自动打开。请在文件管理中手动查找并打开。', showCancel: false });
                        });
                     } else {
                        uni.showModal({ title: '提示', content: '文件下载成功,但当前环境无法自动打开。请在文件管理中手动查找并打开。', showCancel: false });
                     }
                  } else {
                     uni.showModal({ title: '下载失败', content: `下载失败,状态码:${res.statusCode}`, showCancel: false });
                  }
               },
               fail: (error) => {
                  uni.showModal({ title: '下载失败', content: `下载失败,请检查网络连接。${error.errMsg}`, showCancel: false });
               }
            });
         },
      }
   }
</script>
@@ -1425,56 +1603,149 @@
      z-index: 10;
   }
   .popup {
      background-color: #fff;
      padding: 20px;
      border: 1px solid #ccc;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      width: 68vw;
      /* 设置宽度为视口宽度的80% */
      height: 25vh;
      /* 设置高度为视口高度的80% */
   /* 弹窗整体美化 */
   .popup, .attachment-detail-popup {
      background: #fff;
      border-radius: 16px;
      box-shadow: 0 8px 32px rgba(60,60,60,0.18);
      padding: 28px 28px 18px 28px;
      border: none;
      position: relative;
      min-width: 260px;
   }
   .form-group {
   .attachment-popup-title {
      font-size: 22px;
      font-weight: 700;
      color: #222;
      margin-bottom: 8px;
      letter-spacing: 1px;
      text-align: center;
   }
   .attachment-popup-divider {
      height: 1px;
      background: linear-gradient(90deg,#e0e7ef 0%,#f5f7fa 100%);
      margin-bottom: 18px;
   }
   .attachment-detail-content {
      margin-bottom: 18px;
   }
   .attachment-detail-row {
      display: flex;
      align-items: center;
      border-bottom: 1px solid #c9c9c9;
      margin-bottom: 8px;
      font-size: 15px;
   }
   .updateBut {
      background-color: #3498db;
      color: white;
   .attachment-label {
      min-width: 80px;
      color: #1976d2;
      font-weight: 500;
      margin-right: 8px;
   }
   /* 响应式设计 */
   @media (max-width: 500px) {
      .info-row,
      .info-block {
         flex-direction: column;
         align-items: flex-start;
      }
      .doc-links {
         margin-left: 0;
         margin-top: 10px;
      }
      .action-buttons {
         flex-direction: column;
      }
      .inspection-table table {
         display: block;
         overflow-x: auto;
      }
      .click-wd {
         color: #056cba;
         font-size: 1.25rem;
         text-decoration: underline;
      }
   .attachment-preview-area {
      margin: 18px 0 8px 0;
      border-radius: 10px;
      background: #f8fafc;
      padding: 10px;
      box-shadow: 0 2px 8px rgba(60,60,60,0.06);
   }
   .attachment-download-area {
      margin: 18px 0 8px 0;
      text-align: center;
   }
   .attachment-download-link {
      display: inline-block;
      padding: 7px 18px;
      background: linear-gradient(90deg,#4f8cff 0%,#1976d2 100%);
      color: #fff;
      border-radius: 6px;
      font-weight: 500;
      text-decoration: none;
      transition: background 0.2s;
      box-shadow: 0 2px 8px rgba(60,60,60,0.08);
   }
   .attachment-download-link:hover {
      background: linear-gradient(90deg,#1976d2 0%,#4f8cff 100%);
   }
   .attachment-detail-empty {
      color: #888;
      text-align: center;
      margin: 30px 0;
      font-size: 16px;
   }
   .attachment-popup-close {
      margin-top: 18px;
      width: 100%;
      background: linear-gradient(90deg,#e0e0e0 0%,#f5f7fa 100%);
      color: #444;
      border-radius: 8px;
      font-size: 16px;
      padding: 10px 0;
      border: none;
      font-weight: 600;
      letter-spacing: 1px;
      transition: background 0.2s, color 0.2s;
      box-shadow: 0 2px 8px rgba(60,60,60,0.06);
   }
   .attachment-popup-close:hover {
      background: linear-gradient(90deg,#bdbdbd 0%,#e0e0e0 100%);
      color: #1976d2;
   }
   /* 列表弹窗美化(保留原有) */
   .attachment-list {
      padding: 0;
      margin: 0;
      list-style: none;
      max-height: 300px;
      overflow-y: auto;
   }
   .attachment-list li {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 8px 0;
      border-bottom: 1px solid #f0f0f0;
   }
   .attachment-name {
      flex: 1;
      color: #3498db;
      cursor: pointer;
      font-weight: 500;
      transition: color 0.2s;
      margin-right: 10px;
   }
   .attachment-name:hover {
      color: #217dbb;
      text-decoration: underline;
   }
   .attachment-actions {
      display: flex;
      gap: 8px;
   }
   .attachment-list .secondary-btn {
      padding: 4px 10px;
      font-size: 13px;
      border-radius: 3px;
      background: #f5f7fa;
      color: #333;
      border: 1px solid #dbe2ea;
      transition: background 0.2s, color 0.2s;
   }
   .attachment-list .secondary-btn:hover {
      background: #e6f0fa;
      color: #1976d2;
   }
   .attachment-popup-close {
      margin-top: 18px;
      width: 100%;
      background: #e0e0e0;
      color: #444;
      border-radius: 4px;
      font-size: 15px;
      padding: 8px 0;
      border: none;
      transition: background 0.2s;
   }
   .attachment-popup-close:hover {
      background: #bdbdbd;
   }
</style>