فهرست منبع

refactor(image-store-apply): 将业务逻辑提取为mixin并优化样式

yz 4 هفته پیش
والد
کامیت
26a0790187

+ 112 - 0
src/views/image-store-apply/index.scss

@@ -0,0 +1,112 @@
+.detail-container {
+  max-height: 70vh;
+  overflow-y: auto;
+}
+
+.detail-card {
+  margin-bottom: 20px;
+}
+
+.detail-card:last-child {
+  margin-bottom: 0;
+}
+
+.card-header {
+  font-weight: bold;
+  color: #303133;
+}
+
+.detail-item {
+  margin-bottom: 15px;
+  display: flex;
+  align-items: center;
+}
+
+.detail-item label {
+  font-weight: bold;
+  color: #606266;
+  min-width: 80px;
+  margin-right: 10px;
+}
+
+.detail-item span {
+  color: #303133;
+}
+
+.amount {
+  color: #E6A23C;
+  font-weight: bold;
+}
+
+.file-preview {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 40px;
+}
+
+.thumbnail-image {
+  cursor: pointer;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+  transition: all 0.3s;
+}
+
+.thumbnail-image:hover {
+  border-color: #409eff;
+  transform: scale(1.1);
+}
+
+.pdf-thumbnail,
+.file-thumbnail {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 40px;
+  height: 40px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  cursor: pointer;
+  transition: all 0.3s;
+  font-size: 12px;
+  color: #606266;
+}
+
+.pdf-thumbnail:hover,
+.file-thumbnail:hover {
+  border-color: #409eff;
+  color: #409eff;
+}
+
+.pdf-thumbnail i,
+.file-thumbnail i {
+  font-size: 16px;
+  margin-bottom: 2px;
+}
+
+.error-icon {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 40px;
+  height: 40px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  color: #c0c4cc;
+  font-size: 16px;
+}
+
+.preview-container {
+  text-align: center;
+}
+
+.preview-image {
+  max-width: 100%;
+  max-height: 60vh;
+  border-radius: 4px;
+}
+
+.dialog-footer {
+  text-align: right;
+}

+ 4 - 743
src/views/image-store-apply/index.vue

@@ -316,7 +316,6 @@
       :append-to-body="true"
       :lock-scroll="false"
     >
-
       <div slot="footer" class="dialog-footer">
         <el-button @click="auditVisible = false">取消</el-button>
         <el-button
@@ -396,752 +395,14 @@
 </template>
 
 <script>
-import { getList, getDetail, update, getAttachmentList } from '@/api/order/image-store-apply'
-import { formatFileSize } from '@/util/util'
-import { mapGetters } from 'vuex'
-
-/**
- * @typedef {import('@/api/order/image-store-apply').ImageStoreApplyRecord} ImageStoreApplyRecord
- * @typedef {import('@/api/order/image-store-apply').QualificationItem} QualificationItem
- * @typedef {import('@/api/order/image-store-apply').ApplyAttachmentRecord} ApplyAttachmentRecord
- * @typedef {import('@/api/order/image-store-apply').ImageStoreApplyQueryParams} ImageStoreApplyQueryParams
- */
+import imageStoreApplyMixin from './mixins/imageStoreApplyIndex'
 
 export default {
   name: 'ImageStoreApply',
-  data() {
-    return {
-      /** @type {ImageStoreApplyRecord[]} */
-      data: [],
-      /** @type {ImageStoreApplyRecord} */
-      form: {},
-      /** @type {ImageStoreApplyQueryParams} */
-      query: {},
-      loading: true,
-
-      // 分页信息
-      page: {
-        pageSize: 10,
-        currentPage: 1,
-        total: 0
-      },
-
-      // 详情对话框
-      detailVisible: false,
-      /** @type {ImageStoreApplyRecord|null} */
-      detailData: null,
-      /** @type {QualificationItem[]} */
-      qualificationList: [],
-      /** @type {ApplyAttachmentRecord[]} */
-      attachmentList: [],
-      attachmentLoading: false,
-
-      rejectVisible: false,
-      auditLoading: false,
-      /** @type {Object} */
-      rejectForm: {
-        id: '',
-        applyNo: '',
-        customerName: '',
-        auditRemark: ''
-      },
-      /** @type {Object} */
-      rejectRules: {
-        auditRemark: [
-          { required: true, message: '请输入拒绝原因', trigger: 'blur' },
-          { min: 5, max: 500, message: '拒绝原因长度在5到500个字符', trigger: 'blur' }
-        ]
-      },
-
-      // 图片预览
-      previewVisible: false,
-      previewUrl: '',
-
-      // 表格配置
-      option: {
-        height: 'auto',
-        calcHeight: 30,
-        tip: false,
-        searchShow: true,
-        searchMenuSpan: 6,
-        border: true,
-        index: true,
-        viewBtn: false,
-        editBtn: false,
-        delBtn: false,
-        addBtn: false,
-        column: [
-          {
-            label: '申请编号',
-            prop: 'applyNo',
-            minWidth: 140,
-            search: true,
-            searchPlaceholder: '请输入申请编号'
-          },
-          {
-            label: '客户编码',
-            prop: 'customerCode',
-            minWidth: 120,
-            search: true,
-            searchPlaceholder: '请输入客户编码'
-          },
-          {
-            label: '客户名称',
-            prop: 'customerName',
-            minWidth: 180,
-            search: true,
-            searchPlaceholder: '请输入客户名称'
-          },
-          {
-            label: '联系人',
-            prop: 'contactName',
-            minWidth: 100
-          },
-          {
-            label: '联系电话',
-            prop: 'contactPhone',
-            minWidth: 120
-          },
-          {
-            label: '品牌名称',
-            prop: 'brandName',
-            minWidth: 120,
-            search: true,
-            searchPlaceholder: '请输入品牌名称'
-          },
-          {
-            label: '申请金额',
-            prop: 'applyAmount',
-            minWidth: 120,
-            slot: true
-          },
-          {
-            label: '审核状态',
-            prop: 'auditStatus',
-            minWidth: 100,
-            slot: true,
-            search: true,
-            type: 'select',
-            dicData: [
-              { label: '未审核', value: 0 },
-              { label: '审核通过', value: 1 },
-              { label: '审核不通过', value: 2 }
-            ]
-          },
-          {
-            label: '审核金额',
-            prop: 'auditAmount',
-            minWidth: 120,
-            slot: true
-          },
-          {
-            label: '审核人',
-            prop: 'auditorName',
-            minWidth: 100
-          },
-          {
-            label: '审核时间',
-            prop: 'auditTime',
-            minWidth: 150
-          },
-          {
-            label: '提交时间',
-            prop: 'submitTime',
-            minWidth: 150,
-            search: true,
-            type: 'daterange',
-            searchPlaceholder: '请选择提交时间范围',
-            formatter: (row, column, cellValue) => {
-              if (!cellValue) return '-'
-              // 如果是数组格式,取第一个元素
-              if (Array.isArray(cellValue)) {
-                return cellValue[0] || '-'
-              }
-              return cellValue
-            }
-          }
-        ]
-      }
-    }
-  },
-
-  computed: {
-    ...mapGetters(['permission']),
-
-    /** @returns {string[]} */
-    permissionList() {
-      return {
-        // viewBtn: this.vaildData(this.permission.image_store_apply_view, false),
-        // editBtn: this.vaildData(this.permission.image_store_apply_edit, false),
-        // delBtn: this.vaildData(this.permission.image_store_apply_delete, false),
-        // addBtn: this.vaildData(this.permission.image_store_apply_add, false)
-        viewBtn: false,
-        editBtn: false,
-        delBtn: false,
-        addBtn: false,
-      }
-    },
-
-    /** @returns {string[]} */
-    ids() {
-      const ids = []
-      this.selectionList.forEach(ele => {
-        ids.push(ele.id)
-      })
-      return ids
-    }
-  },
-
-  methods: {
-    /**
-     * 判断是否为PDF文件
-     * @param {string} fileType - 文件类型
-     * @returns {boolean} 是否为PDF
-     */
-    isPdfFile(fileType) {
-      return fileType.toLowerCase() === 'pdf'
-    },
-
-    /**
-     * 处理图片加载错误
-     * @param {Event} event - 错误事件
-     */
-    handleImageError(event) {
-      // 图片加载失败时显示默认图标
-      event.target.style.display = 'none'
-      const parent = event.target.parentNode
-      if (parent && !parent.querySelector('.error-icon')) {
-        const errorIcon = document.createElement('div')
-        errorIcon.className = 'error-icon'
-        errorIcon.innerHTML = '<i class="el-icon-picture-outline"></i>'
-        parent.appendChild(errorIcon)
-      }
-    },
-
-    /**
-     * 预览PDF文件
-     * @param {ApplyAttachmentRecord} row - 附件数据
-     */
-    handlePdfPreview(row) {
-      if (!row.fileUrl) {
-        this.$message.warning('文件链接不存在')
-        return
-      }
-
-      // 在新窗口中打开PDF
-      window.open(row.fileUrl, '_blank')
-    },
-
-
-    /**
-     * 处理审核通过操作
-     * @param {ImageStoreApplyRecord} row - 行数据
-     */
-    handleApprove(row) {
-      this.$confirm('确定要审核通过该申请吗?', '确认审核', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'success'
-      }).then(async () => {
-        await this.submitAudit(row, 1, '审核通过')
-      }).catch(() => {
-        // 用户取消操作
-      })
-    },
-
-    /**
-     * 处理审核不通过操作
-     * @param {ImageStoreApplyRecord} row - 行数据
-     */
-    handleReject(row) {
-      this.rejectForm = {
-        id: row.id,
-        applyNo: row.applyNo,
-        customerName: row.customerName,
-        auditRemark: ''
-      }
-
-      // 重置表单验证
-      this.$nextTick(() => {
-        if (this.$refs.rejectFormRef) {
-          this.$refs.rejectFormRef.clearValidate()
-        }
-      })
-
-      this.rejectVisible = true
-    },
-
-    /**
-     * 提交拒绝审核
-     * @returns {Promise<void>}
-     */
-    async submitReject() {
-      try {
-        // 表单验证
-        await this.$refs.rejectFormRef.validate()
-
-        // 找到对应的行数据
-        const row = this.data.find(item => item.id === this.rejectForm.id)
-        if (!row) {
-          this.$message.error('数据不存在')
-          return
-        }
-
-        await this.submitAudit(row, 2, this.rejectForm.auditRemark)
-        this.rejectVisible = false
-      } catch (error) {
-        if (error.message) {
-          // 表单验证错误
-          return
-        }
-        console.error('审核操作失败:', error)
-        this.$message.error('审核操作失败')
-      }
-    },
-
-    /**
-     * 提交审核(通用方法)
-     * @param {ImageStoreApplyRecord} row - 行数据
-     * @param {number} auditStatus - 审核状态 1-通过 2-不通过
-     * @param {string} auditRemark - 审核备注
-     * @returns {Promise<void>}
-     */
-    async submitAudit(row, auditStatus, auditRemark) {
-      try {
-        this.auditLoading = true
-
-        // 构建更新数据
-        const updateData = {
-          ...row,
-          auditStatus: auditStatus,
-          auditAmount: auditStatus === 1 ? parseFloat(row.applyAmount) : 0,
-          auditRemark: auditRemark,
-          auditorId: this.$store.getters.userInfo.user_id,
-          auditorName: this.$store.getters.userInfo.real_name,
-          auditTime: new Date().toISOString().slice(0, 19).replace('T', ' ')
-        }
-
-        await update(updateData)
-
-        this.$message.success(`审核${auditStatus === 1 ? '通过' : '不通过'}操作成功`)
-
-        // 如果是在详情页面,关闭详情对话框
-        if (this.detailVisible) {
-          this.detailVisible = false
-        }
-
-        // 刷新列表
-        await this.onLoad(this.page)
-      } catch (error) {
-        console.error('审核操作失败:', error)
-        this.$message.error('审核操作失败')
-      } finally {
-        this.auditLoading = false
-      }
-    },
-    /**
-     * 获取审核状态文本
-     * @param {number} status - 审核状态
-     * @returns {string} 状态文本
-     */
-    getAuditStatusText(status) {
-      const statusMap = {
-        0: '未审核',
-        1: '审核通过',
-        2: '审核不通过'
-      }
-      return statusMap[status] || '未知状态'
-    },
-
-    /**
-     * 获取审核状态标签类型
-     * @param {number} status - 审核状态
-     * @returns {string} 标签类型
-     */
-    getAuditStatusType(status) {
-      const typeMap = {
-        0: 'warning',
-        1: 'success',
-        2: 'danger'
-      }
-      return typeMap[status] || 'info'
-    },
-
-    /**
-     * 格式化金额显示
-     * @param {string|number} amount - 金额
-     * @returns {string} 格式化后的金额
-     */
-    formatAmount(amount) {
-      if (!amount) return '0.00'
-      const num = parseFloat(amount)
-      return num.toLocaleString('zh-CN', {
-        minimumFractionDigits: 2,
-        maximumFractionDigits: 2
-      })
-    },
-
-    formatFileSize,
-
-    /**
-     * 判断是否为图片文件
-     * @param {string} fileType - 文件类型
-     * @returns {boolean} 是否为图片
-     */
-    isImageFile(fileType) {
-      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
-      return imageTypes.includes(fileType.toLowerCase())
-    },
-
-    /**
-     * 查看详情
-     * @param {ImageStoreApplyRecord} row - 行数据
-     * @returns {Promise<void>}
-     */
-    async handleView(row) {
-      try {
-        this.detailVisible = true
-        this.detailData = null
-        this.qualificationList = []
-        this.attachmentList = []
-
-        // 获取详情数据
-        const res = await getDetail(row.id)
-        this.detailData = res.data.data
-
-        // 解析资质信息
-        if (this.detailData.qualificationInfo) {
-          try {
-            this.qualificationList = JSON.parse(this.detailData.qualificationInfo)
-          } catch (error) {
-            console.warn('解析资质信息失败:', error)
-            this.qualificationList = []
-          }
-        }
-
-        // 加载附件列表
-        await this.loadAttachments(row.id)
-      } catch (error) {
-        console.error('获取详情失败:', error)
-        this.$message.error('获取详情失败')
-      }
-    },
-
-    /**
-     * 加载附件列表
-     * @param {string} applyId - 申请ID
-     * @returns {Promise<void>}
-     */
-    async loadAttachments(applyId) {
-      try {
-        this.attachmentLoading = true
-        const res = await getAttachmentList(1, 100, { applyId: applyId })
-        this.attachmentList = res.data.data.records || []
-      } catch (error) {
-        console.error('获取附件列表失败:', error)
-        this.$message.error('获取附件列表失败')
-      } finally {
-        this.attachmentLoading = false
-      }
-    },
-
-    /**
-     * 处理审核操作
-     * @param {ImageStoreApplyRecord} row - 行数据
-     * @param {number} auditStatus - 审核状态 1-通过 2-不通过
-     */
-    handleAudit(row, auditStatus) {
-      this.auditForm = {
-        id: row.id,
-        applyNo: row.applyNo,
-        customerName: row.customerName,
-        applyAmount: row.applyAmount,
-        auditStatus: auditStatus,
-        auditAmount: auditStatus === 1 ? parseFloat(row.applyAmount) : 0,
-        auditRemark: ''
-      }
-
-      // 重置表单验证
-      this.$nextTick(() => {
-        if (this.$refs.auditFormRef) {
-          this.$refs.auditFormRef.clearValidate()
-        }
-      })
-
-      this.auditVisible = true
-    },
-
-    /**
-     * 下载附件
-     * @param {ApplyAttachmentRecord} row - 附件数据
-     */
-    handleDownload(row) {
-      if (!row.fileUrl) {
-        this.$message.warning('文件链接不存在')
-        return
-      }
-
-      // 创建下载链接
-      const link = document.createElement('a')
-      link.href = row.fileUrl
-      link.download = row.fileName
-      link.target = '_blank'
-      document.body.appendChild(link)
-      link.click()
-      document.body.removeChild(link)
-    },
-
-    /**
-     * 预览图片
-     * @param {ApplyAttachmentRecord} row - 附件数据
-     */
-    handlePreview(row) {
-      if (!row.fileUrl) {
-        this.$message.warning('文件链接不存在')
-        return
-      }
-
-      this.previewUrl = row.fileUrl
-      this.previewVisible = true
-    },
-
-    /**
-     * 新增前的回调
-     * @param {Function} done - 完成回调
-     * @param {string} type - 操作类型
-     */
-    beforeOpen(done, type) {
-      // 此页面不支持新增和编辑
-      done()
-    },
-
-    /**
-     * 获取数据
-     * @param {Object} page - 分页信息
-     * @param {ImageStoreApplyQueryParams} [params] - 查询参数
-     * @returns {Promise<void>}
-     */
-    async onLoad(page, params = {}) {
-      this.loading = true
-
-      try {
-        // 处理时间范围查询
-        const queryParams = { ...params }
-        if (queryParams.submitTime && Array.isArray(queryParams.submitTime)) {
-          queryParams.submitTimeStart = queryParams.submitTime[0]
-          queryParams.submitTimeEnd = queryParams.submitTime[1]
-          delete queryParams.submitTime
-        }
-
-        const res = await getList(page.currentPage, page.pageSize, queryParams)
-        const data = res.data.data
-
-        this.data = data.records || []
-        this.page.total = data.total || 0
-      } catch (error) {
-        console.error('获取数据失败:', error)
-        this.$message.error('获取数据失败')
-      } finally {
-        this.loading = false
-      }
-    },
-
-    /**
-     * 搜索变更
-     * @param {ImageStoreApplyQueryParams} params - 查询参数
-     * @param {Function} done - 完成回调
-     */
-    searchChange(params, done) {
-      this.query = params
-      this.onLoad(this.page, params)
-      done()
-    },
-
-    /**
-     * 搜索重置
-     * @param {Function} done - 完成回调
-     */
-    searchReset(done) {
-      this.query = {}
-      this.onLoad(this.page)
-      done()
-    },
-
-    /**
-     * 选择变更
-     * @param {ImageStoreApplyRecord[]} list - 选中的数据
-     */
-    selectionChange(list) {
-      this.selectionList = list
-    },
-
-    /**
-     * 清空选择
-     */
-    selectionClear() {
-      this.selectionList = []
-    },
-
-    /**
-     * 当前页变更
-     * @param {number} currentPage - 当前页
-     */
-    currentChange(currentPage) {
-      this.page.currentPage = currentPage
-    },
-
-    /**
-     * 页大小变更
-     * @param {number} pageSize - 页大小
-     */
-    sizeChange(pageSize) {
-      this.page.pageSize = pageSize
-    },
-
-    /**
-     * 刷新变更
-     */
-    refreshChange() {
-      this.onLoad(this.page, this.query)
-    }
-  }
+  mixins: [imageStoreApplyMixin]
 }
-
 </script>
 
-<style lang="scss" scoped >
-.detail-container {
-  .detail-card {
-    margin-bottom: 20px;
-
-    &:last-child {
-      margin-bottom: 0;
-    }
-
-    .card-header {
-      font-weight: bold;
-      color: #303133;
-    }
-  }
-
-  .detail-item {
-    margin-bottom: 15px;
-
-    label {
-      font-weight: bold;
-      color: #606266;
-      margin-right: 8px;
-    }
-
-    .amount {
-      color: #E6A23C;
-      font-weight: bold;
-    }
-  }
-}
-
-.preview-container {
-  text-align: center;
-
-  .preview-image {
-    max-width: 100%;
-    max-height: 500px;
-    object-fit: contain;
-  }
-}
-
-.dialog-footer {
-  text-align: right;
-}
-
-// 表格中的金额样式
-::v-deep .el-table {
-  .amount {
-    color: #E6A23C;
-    font-weight: bold;
-  }
-}
-// 附件预览样式
-.file-preview {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  height: 50px;
-
-  .thumbnail-image {
-    max-width: 50px;
-    max-height: 50px;
-    object-fit: cover;
-    border-radius: 4px;
-    cursor: pointer;
-    border: 1px solid #dcdfe6;
-    transition: all 0.3s;
-
-    &:hover {
-      border-color: #409eff;
-      transform: scale(1.1);
-    }
-  }
-
-  .pdf-thumbnail {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    width: 50px;
-    height: 50px;
-    background-color: #f56c6c;
-    color: white;
-    border-radius: 4px;
-    cursor: pointer;
-    transition: all 0.3s;
-
-    &:hover {
-      background-color: #f78989;
-      transform: scale(1.1);
-    }
-
-    i {
-      font-size: 16px;
-      margin-bottom: 2px;
-    }
-
-    span {
-      font-size: 10px;
-      font-weight: bold;
-    }
-  }
-
-  .file-thumbnail {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 50px;
-    height: 50px;
-    background-color: #909399;
-    color: white;
-    border-radius: 4px;
-
-    i {
-      font-size: 20px;
-    }
-  }
-
-  .error-icon {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 50px;
-    height: 50px;
-    background-color: #f5f5f5;
-    color: #c0c4cc;
-    border-radius: 4px;
-    border: 1px solid #dcdfe6;
-
-    i {
-      font-size: 20px;
-    }
-  }
-}
+<style lang="=scss" scoped src="./index.scss">
 
-</style>
+</style>

+ 599 - 0
src/views/image-store-apply/mixins/imageStoreApplyIndex.js

@@ -0,0 +1,599 @@
+import { getList, getDetail, update, getAttachmentList } from '@/api/order/image-store-apply'
+import { formatFileSize } from '@/util/util'
+import { mapGetters } from 'vuex'
+
+/**
+ * @typedef {import('@/api/order/image-store-apply').ImageStoreApplyRecord} ImageStoreApplyRecord
+ * @typedef {import('@/api/order/image-store-apply').QualificationItem} QualificationItem
+ * @typedef {import('@/api/order/image-store-apply').ApplyAttachmentRecord} ApplyAttachmentRecord
+ * @typedef {import('@/api/order/image-store-apply').ImageStoreApplyQueryParams} ImageStoreApplyQueryParams
+ */
+
+/**
+ * 形象申请页面业务逻辑 Mixin
+ * @mixin
+ */
+export default {
+  data() {
+    return {
+      /** @type {ImageStoreApplyRecord[]} */
+      data: [],
+      /** @type {ImageStoreApplyRecord} */
+      form: {},
+      /** @type {ImageStoreApplyQueryParams} */
+      query: {},
+      loading: true,
+
+      // 分页信息
+      page: {
+        pageSize: 10,
+        currentPage: 1,
+        total: 0
+      },
+
+      // 详情对话框
+      detailVisible: false,
+      /** @type {ImageStoreApplyRecord|null} */
+      detailData: null,
+      /** @type {QualificationItem[]} */
+      qualificationList: [],
+      /** @type {ApplyAttachmentRecord[]} */
+      attachmentList: [],
+      attachmentLoading: false,
+
+      // 审核相关
+      auditVisible: false,
+      rejectVisible: false,
+      auditLoading: false,
+      /** @type {Object} */
+      rejectForm: {
+        id: '',
+        applyNo: '',
+        customerName: '',
+        auditRemark: ''
+      },
+      /** @type {Object} */
+      rejectRules: {
+        auditRemark: [
+          { required: true, message: '请输入拒绝原因', trigger: 'blur' },
+          { min: 5, max: 500, message: '拒绝原因长度在5到500个字符', trigger: 'blur' }
+        ]
+      },
+
+      // 图片预览
+      previewVisible: false,
+      previewUrl: '',
+
+      // 选择相关
+      selectionList: [],
+
+      // 表格配置
+      option: {
+        height: 'auto',
+        calcHeight: 30,
+        tip: false,
+        searchShow: true,
+        searchMenuSpan: 6,
+        border: true,
+        index: true,
+        viewBtn: false,
+        editBtn: false,
+        delBtn: false,
+        addBtn: false,
+        column: [
+          {
+            label: '申请编号',
+            prop: 'applyNo',
+            minWidth: 140,
+            search: true,
+            searchPlaceholder: '请输入申请编号'
+          },
+          {
+            label: '客户编码',
+            prop: 'customerCode',
+            minWidth: 120,
+            search: true,
+            searchPlaceholder: '请输入客户编码'
+          },
+          {
+            label: '客户名称',
+            prop: 'customerName',
+            minWidth: 180,
+            search: true,
+            searchPlaceholder: '请输入客户名称'
+          },
+          {
+            label: '联系人',
+            prop: 'contactName',
+            minWidth: 100
+          },
+          {
+            label: '联系电话',
+            prop: 'contactPhone',
+            minWidth: 120
+          },
+          {
+            label: '品牌名称',
+            prop: 'brandName',
+            minWidth: 120,
+            search: true,
+            searchPlaceholder: '请输入品牌名称'
+          },
+          {
+            label: '申请金额',
+            prop: 'applyAmount',
+            minWidth: 120,
+            slot: true
+          },
+          {
+            label: '审核状态',
+            prop: 'auditStatus',
+            minWidth: 100,
+            slot: true,
+            search: true,
+            type: 'select',
+            dicData: [
+              { label: '未审核', value: 0 },
+              { label: '审核通过', value: 1 },
+              { label: '审核不通过', value: 2 }
+            ]
+          },
+          {
+            label: '审核金额',
+            prop: 'auditAmount',
+            minWidth: 120,
+            slot: true
+          },
+          {
+            label: '审核人',
+            prop: 'auditorName',
+            minWidth: 100
+          },
+          {
+            label: '审核时间',
+            prop: 'auditTime',
+            minWidth: 150
+          },
+          {
+            label: '提交时间',
+            prop: 'submitTime',
+            minWidth: 150,
+            search: true,
+            type: 'daterange',
+            searchPlaceholder: '请选择提交时间范围',
+            formatter: (row, column, cellValue) => {
+              if (!cellValue) return '-'
+              // 如果是数组格式,取第一个元素
+              if (Array.isArray(cellValue)) {
+                return cellValue[0] || '-'
+              }
+              return cellValue
+            }
+          }
+        ]
+      }
+    }
+  },
+
+  computed: {
+    ...mapGetters(['permission']),
+
+    /** @returns {Object} */
+    permissionList() {
+      return {
+        viewBtn: false,
+        editBtn: false,
+        delBtn: false,
+        addBtn: false,
+      }
+    },
+
+    /** @returns {string[]} */
+    ids() {
+      const ids = []
+      this.selectionList.forEach(ele => {
+        ids.push(ele.id)
+      })
+      return ids
+    }
+  },
+
+  methods: {
+    /**
+     * 格式化金额显示
+     * @param {number|string} amount - 金额
+     * @returns {string} 格式化后的金额
+     */
+    formatAmount(amount) {
+      if (!amount || parseFloat(amount) === 0) return '0.00'
+      return parseFloat(amount).toFixed(2)
+    },
+
+    /**
+     * 获取审核状态类型
+     * @param {number} status - 审核状态
+     * @returns {string} 状态类型
+     */
+    getAuditStatusType(status) {
+      const statusMap = {
+        0: 'warning', // 未审核
+        1: 'success', // 审核通过
+        2: 'danger'   // 审核不通过
+      }
+      return statusMap[status] || 'info'
+    },
+
+    /**
+     * 获取审核状态文本
+     * @param {number} status - 审核状态
+     * @returns {string} 状态文本
+     */
+    getAuditStatusText(status) {
+      const statusMap = {
+        0: '未审核',
+        1: '审核通过',
+        2: '审核不通过'
+      }
+      return statusMap[status] || '未知状态'
+    },
+
+    /**
+     * 判断是否为图片文件
+     * @param {string} fileType - 文件类型
+     * @returns {boolean} 是否为图片
+     */
+    isImageFile(fileType) {
+      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
+      return imageTypes.includes(fileType.toLowerCase())
+    },
+
+    /**
+     * 判断是否为PDF文件
+     * @param {string} fileType - 文件类型
+     * @returns {boolean} 是否为PDF
+     */
+    isPdfFile(fileType) {
+      return fileType.toLowerCase() === 'pdf'
+    },
+
+    /**
+     * 格式化文件大小
+     * @param {number} size - 文件大小(字节)
+     * @returns {string} 格式化后的文件大小
+     */
+    formatFileSize(size) {
+      return formatFileSize(size)
+    },
+
+    /**
+     * 处理图片加载错误
+     * @param {Event} event - 错误事件
+     */
+    handleImageError(event) {
+      // 图片加载失败时显示默认图标
+      event.target.style.display = 'none'
+      const parent = event.target.parentNode
+      if (parent && !parent.querySelector('.error-icon')) {
+        const errorIcon = document.createElement('div')
+        errorIcon.className = 'error-icon'
+        errorIcon.innerHTML = '<i class="el-icon-picture-outline"></i>'
+        parent.appendChild(errorIcon)
+      }
+    },
+
+    /**
+     * 预览PDF文件
+     * @param {ApplyAttachmentRecord} row - 附件数据
+     */
+    handlePdfPreview(row) {
+      if (!row.fileUrl) {
+        this.$message.warning('文件链接不存在')
+        return
+      }
+
+      // 在新窗口中打开PDF
+      window.open(row.fileUrl, '_blank')
+    },
+
+    /**
+     * 查看详情
+     * @param {ImageStoreApplyRecord} row - 行数据
+     * @returns {Promise<void>}
+     */
+    async handleView(row) {
+      try {
+        this.loading = true
+        
+        // 获取详情数据
+        const detailRes = await getDetail(row.id)
+        if (detailRes.data.success) {
+          this.detailData = detailRes.data.data
+          this.qualificationList = detailRes.data.data.qualificationList || []
+          
+          // 获取附件列表
+          await this.loadAttachmentList(row.id)
+          
+          this.detailVisible = true
+        } else {
+          this.$message.error(detailRes.data.msg || '获取详情失败')
+        }
+      } catch (error) {
+        console.error('获取详情失败:', error)
+        this.$message.error('获取详情失败')
+      } finally {
+        this.loading = false
+      }
+    },
+
+    /**
+     * 加载附件列表
+     * @param {string} applyId - 申请ID
+     * @returns {Promise<void>}
+     */
+    async loadAttachmentList(applyId) {
+      try {
+        this.attachmentLoading = true
+        const attachmentRes = await getAttachmentList(1, 100 ,{
+            applyId
+        })
+        if (attachmentRes.data.success) {
+          this.attachmentList = attachmentRes.data.data.records || []
+        } else {
+          this.$message.error(attachmentRes.data.msg || '获取附件列表失败')
+        }
+      } catch (error) {
+        console.error('获取附件列表失败:', error)
+        this.$message.error('获取附件列表失败')
+      } finally {
+        this.attachmentLoading = false
+      }
+    },
+
+    /**
+     * 处理审核通过操作
+     * @param {ImageStoreApplyRecord} row - 行数据
+     */
+    handleApprove(row) {
+      this.$confirm('确定要审核通过该申请吗?', '确认审核', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'success'
+      }).then(async () => {
+        await this.submitAudit(row, 1, '审核通过')
+      }).catch(() => {
+        // 用户取消操作
+      })
+    },
+
+    /**
+     * 处理审核不通过操作
+     * @param {ImageStoreApplyRecord} row - 行数据
+     */
+    handleReject(row) {
+      this.rejectForm = {
+        id: row.id,
+        applyNo: row.applyNo,
+        customerName: row.customerName,
+        auditRemark: ''
+      }
+
+      // 重置表单验证
+      this.$nextTick(() => {
+        if (this.$refs.rejectFormRef) {
+          this.$refs.rejectFormRef.clearValidate()
+        }
+      })
+
+      this.rejectVisible = true
+    },
+
+    /**
+     * 提交拒绝审核
+     * @returns {Promise<void>}
+     */
+    async submitReject() {
+      try {
+        // 表单验证
+        await this.$refs.rejectFormRef.validate()
+
+        // 找到对应的行数据
+        const row = this.data.find(item => item.id === this.rejectForm.id)
+        if (!row) {
+          this.$message.error('数据不存在')
+          return
+        }
+
+        await this.submitAudit(row, 2, this.rejectForm.auditRemark)
+        this.rejectVisible = false
+      } catch (error) {
+        if (error.message) {
+          // 表单验证错误
+          return
+        }
+        console.error('审核操作失败:', error)
+        this.$message.error('审核操作失败')
+      }
+    },
+
+    /**
+     * 提交审核(通用方法)
+     * @param {ImageStoreApplyRecord} row - 行数据
+     * @param {number} auditStatus - 审核状态 1-通过 2-不通过
+     * @param {string} auditRemark - 审核备注
+     * @returns {Promise<void>}
+     */
+    async submitAudit(row, auditStatus, auditRemark) {
+      try {
+        this.auditLoading = true
+
+        const params = {
+          id: row.id,
+          auditStatus,
+          auditRemark
+        }
+
+        const res = await update(params)
+        if (res.data.success) {
+          this.$message.success('审核操作成功')
+          
+          // 更新列表数据
+          const index = this.data.findIndex(item => item.id === row.id)
+          if (index !== -1) {
+            this.data[index].auditStatus = auditStatus
+            this.data[index].auditRemark = auditRemark
+            this.data[index].auditTime = new Date().toLocaleString()
+          }
+          
+          // 如果详情对话框打开,也更新详情数据
+          if (this.detailVisible && this.detailData && this.detailData.id === row.id) {
+            this.detailData.auditStatus = auditStatus
+            this.detailData.auditRemark = auditRemark
+            this.detailData.auditTime = new Date().toLocaleString()
+          }
+        } else {
+          this.$message.error(res.data.msg || '审核操作失败')
+        }
+      } catch (error) {
+        console.error('审核操作失败:', error)
+        this.$message.error('审核操作失败')
+      } finally {
+        this.auditLoading = false
+      }
+    },
+
+    /**
+     * 预览图片
+     * @param {ApplyAttachmentRecord} row - 附件数据
+     */
+    handlePreview(row) {
+      if (!row.fileUrl) {
+        this.$message.warning('文件链接不存在')
+        return
+      }
+      
+      this.previewUrl = row.fileUrl
+      this.previewVisible = true
+    },
+
+    /**
+     * 下载文件
+     * @param {ApplyAttachmentRecord} row - 附件数据
+     */
+    handleDownload(row) {
+      if (!row.fileUrl) {
+        this.$message.warning('文件链接不存在')
+        return
+      }
+      
+      // 创建下载链接
+      const link = document.createElement('a')
+      link.href = row.fileUrl
+      link.download = row.fileName || '下载文件'
+      link.target = '_blank'
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+    },
+
+    /**
+     * 搜索变化事件
+     * @param {Object} params - 搜索参数
+     * @param {Function} done - 完成回调
+     */
+    searchChange(params, done) {
+      this.query = params
+      this.onLoad(this.page, params)
+      done()
+    },
+
+    /**
+     * 搜索重置事件
+     */
+    searchReset() {
+      this.query = {}
+      this.onLoad(this.page)
+    },
+
+    /**
+     * 选择变化事件
+     * @param {Array} selection - 选中的数据
+     */
+    selectionChange(selection) {
+      this.selectionList = selection
+    },
+
+    /**
+     * 清空选择事件
+     */
+    selectionClear() {
+      this.selectionList = []
+    },
+
+    /**
+     * 当前页变化事件
+     * @param {number} currentPage - 当前页
+     */
+    currentChange(currentPage) {
+      this.page.currentPage = currentPage
+    },
+
+    /**
+     * 页大小变化事件
+     * @param {number} pageSize - 页大小
+     */
+    sizeChange(pageSize) {
+      this.page.pageSize = pageSize
+    },
+
+    /**
+     * 刷新事件
+     */
+    refreshChange() {
+      this.onLoad(this.page, this.query)
+    },
+
+    /**
+     * 打开前事件
+     * @param {Function} done - 完成回调
+     * @param {string} type - 操作类型
+     */
+    beforeOpen(done, type) {
+      done()
+    },
+
+    /**
+     * 加载数据
+     * @param {Object} page - 分页参数
+     * @param {Object} params - 查询参数
+     * @returns {Promise<void>}
+     */
+    async onLoad(page, params = {}) {
+      try {
+        this.loading = true
+        
+        const queryParams = {
+          ...params,
+          current: page.currentPage,
+          size: page.pageSize
+        }
+
+        const res = await getList(
+            queryParams.current,
+            queryParams.size,
+            queryParams
+        )
+        if (res.data.success) {
+          this.data = res.data.data.records || []
+          this.page.total = res.data.data.total || 0
+        } else {
+          this.$message.error(res.data.msg || '获取数据失败')
+        }
+      } catch (error) {
+        console.error('获取数据失败:', error)
+        this.$message.error('获取数据失败')
+      } finally {
+        this.loading = false
+      }
+    }
+  }
+}