<template>
  <div class="product-module">
    <div class="header-tools">
      <div class="left-tools">
        <el-select
            v-model="queryParams.company"
            placeholder="所属公司"
            class="filter-item-select"
            clearable
            filterable
            @change="fetchData"
            style="width: 160px;"
        >
          <el-option v-for="item in companyOptions" :key="item" :label="item" :value="item" />
        </el-select>

        <el-input
            v-model="queryParams.keyword"
            placeholder="请输入名称或规格"
            class="filter-item-input"
            clearable
            @clear="fetchData"
            @keyup.enter="fetchData"
            style="width: 240px;"
        >
          <template #prefix><el-icon><Search /></el-icon></template>
        </el-input>

        <el-select
            v-model="queryParams.category"
            placeholder="类别"
            class="filter-item-select"
            clearable
            filterable
            @change="fetchData"
            style="width: 160px;"
        >
          <el-option v-for="item in categoryOptions" :key="item" :label="item" :value="item" />
        </el-select>

        <el-select
            v-model="queryParams.material_type"
            placeholder="类型"
            class="filter-item-select"
            clearable
            filterable
            @change="fetchData"
            style="width: 160px;"
        >
          <el-option v-for="item in typeOptions" :key="item" :label="item" :value="item" />
        </el-select>

        <el-button type="primary" plain class="search-btn" @click="fetchData">搜索</el-button>
        <el-button class="reset-btn" @click="resetQuery">重置</el-button>

        <el-popover
            placement="bottom"
            width="600"
            trigger="click"
            v-model:visible="advancedFilterVisible"
        >
          <template #reference>
            <el-button type="primary" plain>高级筛选</el-button>
          </template>
          <div style="padding: 10px;">
            <div v-for="(cond, idx) in advancedConditions" :key="idx" style="display: flex; gap: 10px; margin-bottom: 10px; align-items: center;">
              <el-select v-model="cond.field" placeholder="字段" style="width: 150px;">
                <el-option v-for="opt in fieldOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
              </el-select>
              <el-select v-model="cond.operator" placeholder="操作符" style="width: 120px;">
                <el-option v-for="opt in operatorOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
              </el-select>
              <el-input v-model="cond.value" placeholder="值" style="flex: 1;" />
              <el-button type="danger" size="small" @click="removeCondition(idx)" :disabled="advancedConditions.length === 1">删除</el-button>
            </div>
            <div style="display: flex; justify-content: space-between; margin-top: 10px;">
              <el-button type="primary" size="small" @click="addCondition">添加条件</el-button>
              <div>
                <el-button size="small" @click="resetAdvancedFilter">重置</el-button>
                <el-button type="primary" size="small" @click="applyAdvancedFilter">应用</el-button>
              </div>
            </div>
          </div>
        </el-popover>

        <el-select
            v-model="queryParams.statuses"
            multiple
            collapse-tags
            placeholder="状态筛选"
            style="width: 200px; margin-left: 10px;"
            @change="fetchData"
        >
          <el-option label="在库" value="在库" />
          <el-option label="借库" value="借库" />
          <el-option label="已出库" value="已出库" />
        </el-select>
      </div>

      <div class="right-tools">
        <el-button v-if="userStore.hasPermission('inbound_product:operation')" type="primary" :icon="Plus" @click="handleCreate" class="action-btn">成品入库登记</el-button>
        <el-button :icon="Refresh" @click="fetchData" class="action-btn">刷新</el-button>
        <el-popover placement="bottom-end" title="列配置" :width="500" trigger="click">
          <template #reference><el-button :icon="Setting" class="action-btn">表头</el-button></template>
          <el-checkbox-group v-model="visibleColumnProps" class="column-selector">
            <el-row :gutter="10">
              <el-col :span="8" v-for="c in allColumns" :key="c.prop"><el-checkbox :label="c.prop">{{ c.label }}</el-checkbox></el-col>
            </el-row>
          </el-checkbox-group>
        </el-popover>
      </div>
    </div>

    <el-table
        v-loading="loading"
        :data="tableData"
        border
        stripe
        style="width: 100%"
        class="modern-table"
        highlight-current-row
        header-cell-class-name="table-header-gray"
        @sort-change="handleSortChange"
    >
      <template v-for="col in allColumns" :key="col.prop">
        <el-table-column
            v-if="visibleColumnProps.includes(col.prop)"
            :prop="col.prop"
            :label="col.label"
            :min-width="col.minWidth || '110'"
            :sortable="col.sortable ? 'custom' : false"
            show-overflow-tooltip
        >

          <template #default="scope" v-if="col.prop === 'material_name'">
            <span class="clickable-text" @click="handleUpdate(scope.row)">
              {{ scope.row.material_name }}
            </span>
          </template>

          <template #default="scope" v-else-if="col.prop === 'company_name'">
            <span>{{ scope.row.company_name || '-' }}</span>
          </template>

          <template #default="scope" v-else-if="['serial_number'].includes(col.prop)">
            <div v-if="scope.row.serial_number" class="id-cell">
              <span class="prefix-tag sn">SN</span>
              <span class="id-text">{{ scope.row.serial_number }}</span>
            </div>
            <span v-else class="text-placeholder">-</span>
          </template>

          <template #default="scope" v-else-if="col.prop === 'qty_stock'">
            <span class="stock-num">{{ scope.row.qty_stock }}</span>
          </template>

          <template #default="scope" v-else-if="col.prop === 'status'">
            <el-tag :type="getStatusType(scope.row.status)" effect="light" round>{{ scope.row.status }}</el-tag>
          </template>

          <template #default="scope" v-else-if="col.prop === 'quality_status'">
            <el-tag :type="getQualityType(scope.row.quality_status)" effect="dark" size="small">{{ scope.row.quality_status }}</el-tag>
          </template>

          <template #default="scope" v-else-if="['product_photo', 'quality_report_link', 'inspection_report_link'].includes(col.prop)">
            <div v-if="getImagesOnly(scope.row[col.prop]).length > 0" style="display: flex; align-items: center; justify-content: center;">
              <el-image
                  style="width: 40px; height: 40px; border-radius: 4px; border: 1px solid #dcdfe6; cursor: zoom-in;"
                  :src="getImageUrl(getImagesOnly(scope.row[col.prop])[0])"
                  :preview-src-list="getImagesOnly(scope.row[col.prop]).map(u => getImageUrl(u))"
                  preview-teleported
                  fit="cover"
              >
                <template #error>
                  <div class="image-slot"><el-icon><Picture /></el-icon></div>
                </template>
              </el-image>
              <span v-if="getImagesOnly(scope.row[col.prop]).length > 1" class="more-images-badge">+{{getImagesOnly(scope.row[col.prop]).length}}</span>
            </div>
            <div v-else-if="hasExternalLink(scope.row[col.prop])" style="text-align: center;">
              <el-tag size="small" type="info"><el-icon><Link /></el-icon> 链接</el-tag>
            </div>
            <span v-else class="text-placeholder">-</span>
          </template>

          <template #default="scope" v-else-if="['detail_link'].includes(col.prop)">
            <el-link v-if="scope.row[col.prop]" type="primary" :href="scope.row[col.prop]" target="_blank" :underline="false">
              <el-icon><Link /></el-icon> 查看
            </el-link>
          </template>

          <template #default="scope" v-else-if="['sale_price', 'raw_material_cost', 'unit_total_cost', 'total_price'].includes(col.prop)">
            <span class="money-text">{{ formatMoney(scope.row[col.prop]) }}</span>
          </template>

        </el-table-column>
      </template>

      <el-table-column v-if="userStore.hasPermission('inbound_product:operation')" label="操作" width="180" fixed="right" align="center">
        <template #default="{ row }">
          <el-button link type="warning" size="default" @click="handlePrint(row)">
            <el-icon><Printer/></el-icon>
          </el-button>
          <el-button link type="primary" @click="handleUpdate(row)">编辑</el-button>
          <el-popconfirm title="确定删除？" @confirm="handleDelete(row)"><template #reference><el-button link type="danger">删除</el-button></template></el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination class="pagination-bar" v-model:current-page="queryParams.page" v-model:page-size="queryParams.pageSize" :total="total" layout="total, sizes, prev, pager, next" background @change="fetchData" />

    <el-dialog v-model="visible" :title="dialogStatus === 'create' ? '成品入库' : '编辑成品'" width="min(1000px, 95vw)" top="5vh" :close-on-click-modal="false" class="stylish-dialog compact-layout">
      <div class="dialog-scroll-container">
        <el-form :model="form" label-width="110px" ref="formRef" :rules="rules" size="default" class="stylish-form">

          <div class="form-card basic-card">
            <div class="card-title">
              <div style="display: flex; align-items: center;">
                <el-icon class="icon"><Box /></el-icon>
                <span>1. 基础信息</span>
              </div>
            </div>
            <div class="card-content">
              <el-row :gutter="24" v-if="dialogStatus === 'create'" style="margin-bottom: 20px;">
                <el-col :span="12">
                  <el-form-item label="物料搜索" prop="base_id" class="highlight-label">
                    <el-select
                        v-model="form.base_id"
                        filterable
                        remote
                        reserve-keyword
                        clearable
                        placeholder="请输入名称或规格进行检索..."
                        :remote-method="handleSearchMaterial"
                        @visible-change="handleMaterialDropdownVisible"
                        :loading="searchLoading"
                        style="width: 100%"
                        @change="onMaterialSelected"
                        default-first-option
                        v-loadmore="loadMoreMaterials"
                        popper-class="product-dropdown"
                    >
                      <template #prefix><el-icon><Search /></el-icon></template>
                      <el-option v-for="item in materialOptions" :key="item.id" :label="item.name" :value="item.id">
                        <div class="option-item">
                          <div class="opt-main">
                            <span class="opt-name" :title="item.name">{{ item.name }}</span>
                          </div>
                          <div class="opt-meta">
                            <span class="opt-spec" :title="item.spec">{{ item.spec || '-' }}</span>
                          </div>
                          <div class="opt-tags">
                            <el-tag size="small" type="info" effect="light" class="company-tag">{{ item.company_name }}</el-tag>
                            <el-tag v-if="item.isHistory" size="small" type="info" effect="plain">历史</el-tag>
                            <el-tag v-else size="small" type="success" effect="plain">系统</el-tag>
                          </div>
                        </div>
                      </el-option>
                      <div v-if="loadingMore" style="text-align: center; color: #999; font-size: 12px; padding: 8px; background: #f9f9f9;">
                        <el-icon class="is-loading"><Refresh /></el-icon> 加载更多中...
                      </div>
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col :span="12" style="display: flex; align-items: center;">
                  <span class="search-tip">
                    <el-icon><InfoFilled /></el-icon> 支持名称、规格型号、公司名称模糊搜索
                  </span>
                </el-col>
              </el-row>
              <div class="read-only-grid">
                <el-row :gutter="24">
                  <el-col :span="8"><el-form-item label="所属公司" v-if="hasFormFieldPermission('company_name')"><el-input v-model="form.company_name" readonly class="is-text-view" /></el-form-item></el-col>
                  <el-col :span="8"><el-form-item label="名称" v-if="hasFormFieldPermission('material_name')"><el-input v-model="form.material_name" readonly class="is-text-view" /></el-form-item></el-col>
                  <el-col :span="8"><el-form-item label="规格" v-if="hasFormFieldPermission('spec_model')"><el-input v-model="form.spec_model" readonly class="is-text-view" /></el-form-item></el-col>
                  <el-col :span="8"><el-form-item label="单位" v-if="hasFormFieldPermission('unit')"><el-input v-model="form.unit" readonly class="is-text-view" /></el-form-item></el-col>
                  <el-col :span="8"><el-form-item label="类型" v-if="hasFormFieldPermission('material_type')"><el-input v-model="form.material_type" readonly class="is-text-view" /></el-form-item></el-col>
                  <el-col :span="8"><el-form-item label="类别" v-if="hasFormFieldPermission('category')"><el-input v-model="form.category" readonly class="is-text-view" /></el-form-item></el-col>
                </el-row>
              </div>
            </div>
          </div>

          <div class="form-card inbound-card">
            <div class="card-title"><el-icon class="icon"><House /></el-icon><span>2. 入库详情</span></div>
            <div class="card-content">
              <el-row :gutter="24">
                <el-col :span="6"><el-form-item label="SKU" prop="sku"><el-input v-model="form.sku" placeholder="自动生成" disabled /></el-form-item></el-col>
                <el-col :span="6"><el-form-item label="库位" prop="warehouse_location">
                  <el-tree-select
                    v-model="form.warehouse_location"
                    :data="warehouseOptions"
                    :props="{ label: 'full_path', value: 'full_path', children: 'children' }"
                    placeholder="请选择库位"
                    style="width: 100%"
                    clearable
                    filterable
                    check-strictly
                    :render-after-expand="false"
                  >
                    <template #default="{ data }">
                      <span>{{ data.name }}</span>
                    </template>
                  </el-tree-select>
                </el-form-item></el-col>
                <el-col :span="6"><el-form-item label="入库日期"><el-date-picker v-model="form.in_date" type="date" value-format="YYYY-MM-DD" style="width:100%" disabled /></el-form-item></el-col>
              </el-row>

              <div class="identity-panel">
                <el-row :gutter="24">
                  <el-col :span="12">
                    <el-form-item label="序列号(SN)" prop="serial_number">
                      <el-input v-model="form.serial_number" placeholder="必填: 唯一序列号" clearable><template #prefix><span class="prefix-tag sn">SN</span></template></el-input>
                    </el-form-item>
                  </el-col>
                  <el-col :span="12">
                    <el-form-item label="入库数量" prop="in_quantity">
                      <el-input-number v-model="form.in_quantity" :min="1" style="width:100%" />
                    </el-form-item>
                  </el-col>
                </el-row>
              </div>

              <el-row :gutter="24" style="margin-top:15px">
                <template v-if="dialogStatus === 'update'">
                  <el-col :span="6">
                    <el-form-item label="库存状态" prop="status">
                      <el-select v-model="form.status" style="width:100%">
                        <el-option label="在库" value="在库"/>
                        <el-option label="借库" value="借库"/>
                        <el-option label="已出库" value="已出库"/>
                      </el-select>
                    </el-form-item>
                  </el-col>
                </template>
                <el-col :span="6">
                  <el-form-item label="质量状态">
                    <el-select v-model="form.quality_status" style="width:100%">
                      <el-option label="合格" value="合格" /><el-option label="不合格" value="不合格" /><el-option label="待检" value="待检" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col :span="dialogStatus === 'update' ? 12 : 18">
                  <el-form-item label="成品实拍" prop="product_photo">
                    <div class="upload-container">
                      <el-upload v-model:file-list="productPhotoList" action="#" list-type="picture-card" multiple :http-request="(opts) => customUpload(opts, 'product_photo')" :on-preview="handlePreviewPicture" :on-remove="(file) => handleRemoveImage(file, 'product_photo')" :before-upload="beforeAvatarUpload">
                        <el-icon><Plus /></el-icon>
                      </el-upload>
                      <div class="camera-card" @click="triggerCamera('product_photo')"><el-icon><Camera /></el-icon><span class="text">拍照</span></div>
                    </div>
                    <el-input v-model="form.product_photo" style="display:none" />
                  </el-form-item>
                </el-col>
              </el-row>

              <el-row :gutter="24">
                <el-col :span="12">
                  <el-form-item label="质量报告" prop="quality_report_link">
                    <div class="upload-container">
                      <el-upload v-model:file-list="qualityFileList" action="#" list-type="picture-card" multiple :http-request="(opts) => customUpload(opts, 'quality_report_link')" :on-preview="handlePreviewPicture" :on-remove="(file) => handleRemoveImage(file, 'quality_report_link')" :before-upload="beforeAvatarUpload">
                        <el-icon><Plus /></el-icon>
                      </el-upload>
                      <div class="camera-card" @click="triggerCamera('quality_report_link')"><el-icon><Camera /></el-icon><span class="text">拍照</span></div>
                    </div>
                    <el-input v-model="quality_url" placeholder="外部链接..." style="margin-top:8px" clearable><template #prefix><el-icon><Link /></el-icon></template></el-input>
                    <el-input v-model="form.quality_report_link" style="display:none" />
                  </el-form-item>
                </el-col>

                <el-col :span="12">
                  <el-form-item label="检测报告" prop="inspection_report_link">
                    <div class="upload-container">
                      <el-upload v-model:file-list="inspectionFileList" action="#" list-type="picture-card" multiple :http-request="(opts) => customUpload(opts, 'inspection_report_link')" :on-preview="handlePreviewPicture" :on-remove="(file) => handleRemoveImage(file, 'inspection_report_link')" :before-upload="beforeAvatarUpload">
                        <el-icon><Plus /></el-icon>
                      </el-upload>
                      <div class="camera-card" @click="triggerCamera('inspection_report_link')"><el-icon><Camera /></el-icon><span class="text">拍照</span></div>
                    </div>
                    <el-input v-model="inspection_url" placeholder="外部链接..." style="margin-top:8px" clearable><template #prefix><el-icon><Link /></el-icon></template></el-input>
                    <el-input v-model="form.inspection_report_link" style="display:none" />
                  </el-form-item>
                </el-col>
              </el-row>
            </div>
          </div>

          <div class="form-card production-card">
            <div class="card-title"><el-icon class="icon"><Setting /></el-icon><span>3. 生产与销售信息</span></div>
            <div class="card-content">
              <el-row :gutter="24">

                <el-col :span="8">
                  <el-form-item label="BOM编号">
                    <el-select
                        v-model="form.bom_code"
                        filterable
                        remote
                        clearable
                        placeholder="搜规格/编号"
                        :remote-method="handleSearchBom"
                        :loading="bomSearchLoading"
                        @change="handleBomSelect"
                        style="width: 100%"
                    >
                      <el-option
                          v-for="item in bomOptions"
                          :key="`${item.bom_no}_${item.version}`"
                          :label="item.bom_no"
                          :value="`${item.bom_no}###${item.version}`"
                      >
                        <span style="float: left; font-weight: bold;">{{ item.bom_no }}</span>
                        <span style="float: right; color: #8492a6; font-size: 13px; margin-left: 10px;">
                          {{ item.version }} <span v-if="item.parent_spec">({{ item.parent_spec }})</span>
                        </span>
                      </el-option>
                    </el-select>
                  </el-form-item>
                </el-col>

                <el-col :span="8"><el-form-item label="BOM版本"><el-input v-model="form.bom_version" placeholder="自动填充" readonly/></el-form-item></el-col>
                <el-col :span="8"><el-form-item label="工单号"><el-input v-model="form.work_order_code" /></el-form-item></el-col>
              </el-row>
              <el-row :gutter="24">
                <el-col :span="8"><el-form-item label="订单号"><el-input v-model="form.order_id" placeholder="关联销售订单" /></el-form-item></el-col>
                <el-col :span="8">
                  <el-form-item label="负责人">
                    <el-autocomplete v-model="form.production_manager" :fetch-suggestions="querySearchManager" placeholder="输入或选择负责人" style="width: 100%" clearable :trigger-on-focus="true" @select="handleManagerSelect"/>
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="产品定价">
                    <el-input-number v-model="form.sale_price" :precision="2" :controls="false" style="width:100%" placeholder="请输入">
                      <template #prefix>¥</template>
                    </el-input-number>
                  </el-form-item>
                </el-col>
              </el-row>

              <el-row :gutter="24">
                <el-col :span="12">
                  <el-form-item label="生产时间">
                    <el-date-picker v-model="form.production_time_range" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="24">
                <el-col :span="8">
                  <el-form-item label="原料成本">
                    <el-input-number v-model="form.raw_material_cost" :precision="2" :controls="false" style="width:100%" placeholder="请输入"/>
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="单件成本">
                    <el-input-number v-model="form.unit_total_cost" :precision="2" :controls="false" style="width:100%" placeholder="请输入"/>
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="总成本">
                    <el-input-number v-model="form.total_price" :precision="2" :controls="false" style="width:100%" placeholder="自动计算" disabled/>
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="24" style="margin-top:10px">
                <el-col :span="24"><el-form-item label="详情链接"><el-input v-model="form.detail_link" /></el-form-item></el-col>
              </el-row>
            </div>
          </div>
        </el-form>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="visible = false" size="large">取消</el-button>
          <el-button type="primary" :loading="submitting" @click="submitForm" size="large" class="confirm-btn">
            {{ dialogStatus === 'create' ? '提交并打印' : '保存修改' }}
          </el-button>
        </div>
      </template>
    </el-dialog>


    <el-dialog v-model="dialogVisibleImage" append-to-body width="50%">
      <img style="width: 100%" :src="dialogImageUrl" alt="Preview Image" />
    </el-dialog>
    <el-dialog v-model="cameraDialogVisible" title="拍照上传" width="500px" append-to-body destroy-on-close :close-on-click-modal="false">
      <WebRtcCamera
          ref="cameraRef"
          @photo-submit="handleCameraConfirm"
          @cancel="cameraDialogVisible = false"
      />
    </el-dialog>

    <el-dialog v-model="printVisible" title="标签打印预览" width="400px" destroy-on-close append-to-body>
      <div style="text-align: center;">
        <div v-loading="printLoading" class="preview-box">
          <img v-if="previewUrl" :src="previewUrl" alt="Label Preview" style="width: 100%; border: 1px solid #ccc;"/>
          <div v-else class="empty-preview">正在生成预览...</div>
        </div>
        <div style="margin-top: 20px; font-size: 14px; color: #666;"><p>打印机 IP: 192.168.9.205</p><p>尺寸: 40mm x 30mm</p></div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="printVisible = false">取消</el-button>
          <el-button type="primary" :loading="printing" @click="confirmPrint">
            <el-icon><Printer/></el-icon> 确认打印
          </el-button>
        </div>
      </template>
    </el-dialog>

  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch, computed } from 'vue'
import { Plus, Setting, Refresh, Search, Box, House, Link, InfoFilled, Printer, Camera, Picture } from '@element-plus/icons-vue'
import { ElMessage, ElLoading } from 'element-plus'
import dayjs from 'dayjs'
import {
  getProductList,
  createProductInbound,
  updateProductInbound,
  deleteProductInbound,
  searchMaterialBase,
  searchBom,
  getFilterOptions,
  getManagerHistory, // [新增]
  calculateBomCost
} from '@/api/inbound/product'
import { uploadFile, deleteFile } from '@/api/inbound/buy'
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue'
import { getLabelPreview, executePrint } from '@/api/common/print'
import { getWarehouseTree } from '@/api/common/warehouse'
import { useUserStore } from '@/stores/user'

// ------------------------------------
// v-loadmore
// ------------------------------------
const vLoadmore = {
  mounted(el: any, binding: any) {
    const checkAndBind = () => {
      // 这里的 .product-dropdown 是唯一标识，防止和采购/半成品页面冲突
      const dropDownWrap = document.querySelector('.product-dropdown .el-select-dropdown__wrap')
      if (dropDownWrap && !dropDownWrap.getAttribute('data-loadmore-bound')) {
        dropDownWrap.setAttribute('data-loadmore-bound', 'true')
        dropDownWrap.addEventListener('scroll', function (this: any) {
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 1
          if (condition) {
            binding.value()
          }
        })
      }
    }
    setTimeout(checkAndBind, 500)
    el.addEventListener('click', () => setTimeout(checkAndBind, 300))
  }
}

const userStore = useUserStore()
const loading = ref(false)
const submitting = ref(false)
const visible = ref(false)
const searchLoading = ref(false)
const loadingMore = ref(false)
const dialogStatus = ref<'create' | 'update'>('create')
const tableData = ref([])
const total = ref(0)
const formRef = ref()
const queryParams = reactive({ page: 1, pageSize: 100, keyword: '', category: '', material_type: '', statuses: ['在库', '借库'], company: '', orderByColumn: '', isAsc: '', advancedFilters: [] })
const categoryOptions = ref<string[]>([])
const typeOptions = ref<string[]>([])
const companyOptions = ref<string[]>([]) // [新增]
const advancedFilterVisible = ref(false)
const advancedConditions = ref([{ field: '', operator: '', value: '' }])
const fieldOptions = computed(() => {
  const allFields = [
    { value: 'id', label: 'ID', perm: 'inbound_product:id' },
    { value: 'base_id', label: 'BaseID', perm: 'inbound_product:base_id' },
    { value: 'company_name', label: '所属公司', perm: 'inbound_product:company_name' },
    { value: 'material_name', label: '名称', perm: 'inbound_product:material_name' },
    { value: 'spec_model', label: '规格', perm: 'inbound_product:spec_model' },
    { value: 'category', label: '类别', perm: 'inbound_product:category' },
    { value: 'material_type', label: '类型', perm: 'inbound_product:material_type' },
    { value: 'unit', label: '单位', perm: 'inbound_product:unit' },
    { value: 'sku', label: 'SKU', perm: 'inbound_product:sku' },
    { value: 'inbound_date', label: '入库日期', perm: 'inbound_product:inbound_date' },
    { value: 'barcode', label: '条码', perm: 'inbound_product:barcode' },
    { value: 'serial_number', label: '序列号(SN)', perm: 'inbound_product:serial_number' },
    { value: 'batch_number', label: '批号', perm: 'inbound_product:serial_number' },
    { value: 'status', label: '库存状态', perm: 'inbound_product:status' },
    { value: 'quality_status', label: '质量状态', perm: 'inbound_product:quality_status' },
    { value: 'in_quantity', label: '入库数量', perm: 'inbound_product:in_quantity' },
    { value: 'stock_quantity', label: '库存数', perm: 'inbound_product:stock_quantity' },
    { value: 'available_quantity', label: '可用数', perm: 'inbound_product:available_quantity' },
    { value: 'warehouse_location', label: '库位', perm: 'inbound_product:warehouse_location' },
    { value: 'bom_code', label: 'BOM编号', perm: 'inbound_product:bom_code' },
    { value: 'bom_version', label: 'BOM版本', perm: 'inbound_product:bom_version' },
    { value: 'work_order_code', label: '工单号', perm: 'inbound_product:work_order_code' },
    { value: 'raw_material_cost', label: '原料成本', perm: 'inbound_product:raw_material_cost' },
    { value: 'unit_total_cost', label: '单件成本', perm: 'inbound_product:unit_total_cost' },
    { value: 'total_price', label: '总成本', perm: 'inbound_product:total_price' },
    { value: 'order_id', label: '订单号', perm: 'inbound_product:order_id' },
    { value: 'sale_price', label: '产品定价', perm: 'inbound_product:sale_price' },
    { value: 'production_manager', label: '负责人', perm: 'inbound_product:production_manager' }
  ]
  // 根据用户权限过滤
  return allFields.filter(item => userStore.hasPermission(item.perm))
})
const operatorOptions = ref([
  { label: '等于', value: '=' },
  { label: '不等于', value: '!=' },
  { label: '包含', value: 'like' },
  { label: '不包含', value: 'not_like' },
  { label: '大于', value: '>' },
  { label: '小于', value: '<' },
  { label: '大于等于', value: '>=' },
  { label: '小于等于', value: '<=' },
])
const materialOptions = ref<any[]>([])
const searchPage = ref(1)
const searchKeyword = ref('')
const hasNextPage = ref(true)
let searchTimer: any = null

// BOM 搜索相关
const bomSearchLoading = ref(false)
const bomOptions = ref<any[]>([])

// 打印相关变量
const printVisible = ref(false)
const printLoading = ref(false)
const printing = ref(false)
const previewUrl = ref('')
const currentPrintData = ref<any>({})

// 图片/拍照相关
const dialogImageUrl = ref('')
const dialogVisibleImage = ref(false)
const productPhotoList = ref<any[]>([]) // 成品实拍
const qualityFileList = ref<any[]>([])  // 质量报告
const inspectionFileList = ref<any[]>([]) // 检测报告

const cameraDialogVisible = ref(false)
const cameraRef = ref<InstanceType<typeof WebRtcCamera> | null>(null)
const currentCameraField = ref<'product_photo' | 'quality_report_link' | 'inspection_report_link'>('product_photo')
const quality_url = ref('')
const inspection_url = ref('')

// 库位级联选择器数据
const warehouseOptions = ref<any[]>([])

// [核心优化] 所有列定义
const allColumns = [
  { prop: 'company_name', label: '所属公司', minWidth: '100', sortable: true }, // [新增]
  { prop: 'material_name', label: '名称', minWidth: '140', sortable: true },
  { prop: 'sku', label: 'SKU', minWidth: '110', sortable: true },
  { prop: 'serial_number', label: '序列号', minWidth: '130', sortable: true },
  { prop: 'qty_stock', label: '库存', minWidth: '90', sortable: true },
  { prop: 'status', label: '状态', minWidth: '90', sortable: true },
  { prop: 'quality_status', label: '质量', minWidth: '90', sortable: true },
  { prop: 'spec_model', label: '规格', minWidth: '120', sortable: true },
  { prop: 'unit', label: '单位', minWidth: '80', sortable: true },
  { prop: 'product_photo', label: '实拍图', minWidth: '100', sortable: false },
  { prop: 'sale_price', label: '售价', minWidth: '100', sortable: true },
  { prop: 'order_id', label: '订单号', minWidth: '120', sortable: true },
  { prop: 'work_order_code', label: '工单号', minWidth: '120', sortable: true },
  { prop: 'quality_report_link', label: '质量报告', minWidth: '100', sortable: false },
  { prop: 'inspection_report_link', label: '检测报告', minWidth: '100', sortable: false },
  { prop: 'bom_code', label: 'BOM', minWidth: '100', sortable: true },
  { prop: 'production_manager', label: '负责人', minWidth: '100', sortable: true },
  { prop: 'raw_material_cost', label: '原料成本', minWidth: '100', sortable: true },
  { prop: 'unit_total_cost', label: '单件成本', minWidth: '100', sortable: true },
  { prop: 'total_price', label: '总成本', minWidth: '100', sortable: true },
  { prop: 'inbound_date', label: '生产日期', minWidth: '120', sortable: true },
  { prop: 'detail_link', label: '详情', minWidth: '100', sortable: false }
]

// 列与权限Code的映射关系（数据库中的code）
const permissionMap: Record<string, string> = {
  id: 'inbound_product:id',
  base_id: 'inbound_product:base_id',
  company_name: 'inbound_product:company_name',
  material_name: 'inbound_product:material_name',
  spec_model: 'inbound_product:spec_model',
  category: 'inbound_product:category',
  material_type: 'inbound_product:material_type',
  unit: 'inbound_product:unit',
  sku: 'inbound_product:sku',
  inbound_date: 'inbound_product:inbound_date',
  barcode: 'inbound_product:barcode',
  serial_number: 'inbound_product:serial_number',
  batch_number: 'inbound_product:serial_number',
  status: 'inbound_product:status',
  quality_status: 'inbound_product:quality_status',
  in_quantity: 'inbound_product:in_quantity',
  stock_quantity: 'inbound_product:stock_quantity',
  available_quantity: 'inbound_product:available_quantity',
  warehouse_location: 'inbound_product:warehouse_location',
  bom_code: 'inbound_product:bom_code',
  bom_version: 'inbound_product:bom_version',
  work_order_code: 'inbound_product:work_order_code',
  raw_material_cost: 'inbound_product:raw_material_cost',
  unit_total_cost: 'inbound_product:unit_total_cost',
  total_price: 'inbound_product:total_price',
  order_id: 'inbound_product:order_id',
  sale_price: 'inbound_product:sale_price',
  production_manager: 'inbound_product:production_manager',
  product_photo: 'inbound_product:product_photo',
  quality_report_link: 'inbound_product:quality_report_link',
  inspection_report_link: 'inbound_product:inspection_report_link',
  detail_link: 'inbound_product:detail_link',
}

// 根据用户权限初始化列显示状态
// 初始化列显示状态（移除权限限制，添加 localStorage 支持）
const initColumnPermissions = () => {
  // 生成存储键：使用用户ID或用户名，如果没有则使用浏览器唯一标识
  const userId = userStore.user?.id || userStore.username || 'anonymous'
  const storageKey = `inbound_product_columns_${userId}`
  
  // 尝试从 localStorage 读取保存的列配置
  const savedColumns = localStorage.getItem(storageKey)
  if (savedColumns) {
    try {
      const parsed = JSON.parse(savedColumns)
      // 验证保存的列是否有效（存在于 allColumns 中）
      const validColumns = parsed.filter((prop: string) => 
        allColumns.some(col => col.prop === prop)
      )
      if (validColumns.length > 0) {
        visibleColumnProps.value = validColumns
        return
      }
    } catch (e) {
      console.warn('Failed to parse saved columns:', e)
    }
  }
  
  // 如果没有保存的配置，使用默认列
  visibleColumnProps.value = defaultVisibleCols
}

// 检查列权限（移除权限限制，始终返回 true）
const hasColumnPermission = (prop: string) => {
  return true
}

const defaultVisibleCols = ['company_name', 'material_name', 'sku', 'serial_number', 'qty_stock', 'status', 'quality_status', 'product_photo', 'sale_price', 'order_id']
const visibleColumnProps = ref(defaultVisibleCols)

// 监听列配置变化并保存到 localStorage
watch(visibleColumnProps, (newVal) => {
  const userId = userStore.user?.id || userStore.username || 'anonymous'
  const storageKey = `inbound_product_columns_${userId}`
  try {
    localStorage.setItem(storageKey, JSON.stringify(newVal))
  } catch (e) {
    console.warn('Failed to save columns to localStorage:', e)
  }
}, { deep: true })

const form = reactive({
  id: undefined, base_id: undefined as number | undefined,
  company_name: '', // [新增]
  material_name: '', spec_model: '', material_type: '', category: '', unit: '',
  sku: '', barcode: '', serial_number: '', in_date: '',
  in_quantity: 1, stock_quantity: 1, available_quantity: 1,
  warehouse_location: '', status: '在库', quality_status: '合格',
  bom_code: '', bom_version: '', work_order_code: '', order_id: '',
  production_manager: '', production_time_range: [] as string[],
  raw_material_cost: undefined as number | undefined,
  unit_total_cost: undefined as number | undefined,
  total_price: undefined as number | undefined,
  sale_price: undefined as number | undefined,
  quality_report_link: [] as string[], inspection_report_link: [] as string[], product_photo: [] as string[], detail_link: ''
})

// ------------------------------------
// BOM Search Logic
// ------------------------------------
const handleSearchBom = async (query: string) => {
  bomSearchLoading.value = true
  try {
    const res: any = await searchBom(query)
    bomOptions.value = res.data || []
  } finally { bomSearchLoading.value = false }
}
const handleBomSelect = async (val: string) => {
  if (!val) {
    form.bom_code = ''
    form.bom_version = ''
    return
  }
  const [code, version] = val.split('###')
  form.bom_code = code
  form.bom_version = version
  // 自动计算 BOM 成本并填入 raw_material_cost 和 unit_total_cost
  try {
    const res: any = await calculateBomCost({ bom_code: code, bom_version: version })
    if (res.code === 200 && typeof res.data === 'number') {
      form.raw_material_cost = res.data
      form.unit_total_cost = res.data
    }
  } catch (e) {
    // 计算失败不影响现有输入
    console.warn('BOM 成本计算失败', e)
  }
}

// ------------------------------------
// 表单字段权限检查
// ------------------------------------
const hasFormFieldPermission = (fieldName: string) => {
  // 超级管理员直接返回true
  if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
    return true
  }
  // 根据字段名映射到权限码
  const map: Record<string, string> = {
    company_name: 'inbound_product:company_name',
    material_name: 'inbound_product:material_name',
    spec_model: 'inbound_product:spec_model',
    material_type: 'inbound_product:material_type',
    category: 'inbound_product:category',
    unit: 'inbound_product:unit',
    sku: 'inbound_product:sku',
    barcode: 'inbound_product:barcode',
    serial_number: 'inbound_product:serial_number',
    in_date: 'inbound_product:inbound_date',
    in_quantity: 'inbound_product:in_quantity',
    stock_quantity: 'inbound_product:stock_quantity',
    available_quantity: 'inbound_product:available_quantity',
    warehouse_location: 'inbound_product:warehouse_location',
    status: 'inbound_product:status',
    quality_status: 'inbound_product:quality_status',
    bom_code: 'inbound_product:bom_code',
    bom_version: 'inbound_product:bom_version',
    work_order_code: 'inbound_product:work_order_code',
    order_id: 'inbound_product:order_id',
    production_manager: 'inbound_product:production_manager',
    production_time_range: 'inbound_product:production_start_time',
    raw_material_cost: 'inbound_product:raw_material_cost',
    manual_cost: 'inbound_product:manual_cost',
    sale_price: 'inbound_product:sale_price',
    quality_report_link: 'inbound_product:quality_report_link',
    inspection_report_link: 'inbound_product:inspection_report_link',
    product_photo: 'inbound_product:product_photo',
    detail_link: 'inbound_product:detail_link',
  }
  const code = map[fieldName]
  if (!code) {
    // 没有映射的字段默认显示
    return true
  }
  return userStore.hasPermission(code)
}

// ------------------------------------
// Validation Logic
// ------------------------------------
const validateUnique = (rule: any, value: string, callback: any) => {
  if (!value) return callback()
  const isDuplicate = tableData.value.some((row: any) => {
    if (dialogStatus.value === 'update' && row.id === form.id) return false
    if (rule.field === 'serial_number' && row.serial_number === value) return true
    return false
  })
  if (isDuplicate) callback(new Error('当前列表页存在相同SN(后端将进行全局校验)'))
  else callback()
}

const rules = {
  base_id: [{ required: true, message: '必选', trigger: 'change' }],
  serial_number: [{ required: true, message: '必填', trigger: 'blur' }, { validator: validateUnique, trigger: 'blur' }],
  in_quantity: [{ required: true, message: '必填', trigger: 'blur' }]
}


// ------------------------------------
// Material Search & Population Logic (已修改)
// ------------------------------------
const handleMaterialDropdownVisible = (visible: boolean) => { if (visible && materialOptions.value.length === 0) handleSearchMaterialDebounced('') }

const handleSearchMaterialDebounced = (query: string) => {
  if (searchTimer) clearTimeout(searchTimer)
  searchTimer = setTimeout(() => {
    handleSearchMaterial(query)
  }, 300)
}

const handleSearchMaterial = async (query: string) => {
  searchLoading.value = true
  searchKeyword.value = query
  searchPage.value = 1
  materialOptions.value = []

  try {
    const res: any = await searchMaterialBase(query, 1)
    const apiResults = (res.data?.items || []).map((i: any) => ({ ...i, isHistory: false }))
    materialOptions.value = apiResults
    hasNextPage.value = res.data?.has_next ?? false
  } finally { searchLoading.value = false }
}

const loadMoreMaterials = async () => {
  if (searchLoading.value || loadingMore.value || !hasNextPage.value) return
  loadingMore.value = true
  searchPage.value += 1
  try {
    const res: any = await searchMaterialBase(searchKeyword.value, searchPage.value)
    if (res.data && res.data.items && res.data.items.length > 0) {
      const newItems = res.data.items.map((i: any) => ({...i, isHistory: false}))
      materialOptions.value.push(...newItems)
      hasNextPage.value = res.data.has_next
    } else {
      hasNextPage.value = false
    }
  } catch (e) {
    searchPage.value -= 1
  } finally {
    loadingMore.value = false
  }
}

const onMaterialSelected = (val: number) => {
  const item = materialOptions.value.find(i => i.id === val)
  if (item) {
    form.company_name = item.company_name // [新增]
    form.material_name = item.name
    form.spec_model = item.spec
    form.material_type = item.type
    form.category = item.category
    form.unit = item.unit
  }
}

// ------------------------------------
// Autocomplete (Manager) - 后端历史记录驱动 (已修改为全局)
// ------------------------------------
const querySearchManager = async (query: string, cb: any) => {
  try {
    const res: any = await getManagerHistory({ keyword: query })
    if (res.code === 200) {
      const managers = (res.data || []).map((name: string) => ({ value: name }))
      cb(managers)
    } else { cb([]) }
  } catch (e) { cb([]) }
}
const handleManagerSelect = (item: any) => {
  form.production_manager = item.value
}

const fetchData = async () => {
  loading.value = true
  try {
    const params = { 
      ...queryParams, 
      statuses: queryParams.statuses.join(','),
      orderByColumn: queryParams.orderByColumn,
      isAsc: queryParams.isAsc,
      advancedFilters: queryParams.advancedFilters.length > 0 ? JSON.stringify(queryParams.advancedFilters) : ''
    }
    const res: any = await getProductList(params)
    tableData.value = res.data.items || []
    total.value = res.data.total || 0
  } finally { loading.value = false }
}

const fetchOptions = async () => {
  try {
    const res: any = await getFilterOptions()
    if (res.code === 200) {
      categoryOptions.value = res.data.categories
      typeOptions.value = res.data.types
      companyOptions.value = res.data.companies // [新增]
    }
  } catch (e) {
    console.error("Fetch options failed", e)
  }
}

// 加载库位树数据
const loadWarehouseTree = async () => {
  try {
    const res = await getWarehouseTree()
    if (res.code === 200) {
      warehouseOptions.value = res.data || []
    }
  } catch (e) {
    console.error('加载库位树失败', e)
  }
}

const resetQuery = () => {
  queryParams.keyword = ''
  queryParams.category = ''
  queryParams.material_type = ''
  queryParams.company = ''
  queryParams.page = 1
  queryParams.orderByColumn = ''
  queryParams.isAsc = ''
  queryParams.advancedFilters = []
  fetchData()
}

const handleSortChange = ({ column, prop, order }: any) => {
  if (order === 'ascending') {
    queryParams.orderByColumn = prop
    queryParams.isAsc = 'true'
  } else if (order === 'descending') {
    queryParams.orderByColumn = prop
    queryParams.isAsc = 'false'
  } else {
    queryParams.orderByColumn = ''
    queryParams.isAsc = ''
  }
  queryParams.page = 1
  fetchData()
}

const addCondition = () => {
  advancedConditions.value.push({ field: '', operator: '', value: '' })
}
const removeCondition = (index: number) => {
  advancedConditions.value.splice(index, 1)
}
const applyAdvancedFilter = () => {
  const validConditions = advancedConditions.value.filter(c => c.field && c.operator && c.value !== '')
  queryParams.advancedFilters = validConditions
  advancedFilterVisible.value = false
  queryParams.page = 1
  fetchData()
}
const resetAdvancedFilter = () => {
  advancedConditions.value = [{ field: '', operator: '', value: '' }]
  queryParams.advancedFilters = []
  advancedFilterVisible.value = false
  queryParams.page = 1
  fetchData()
}

const handleCreate = () => {
  dialogStatus.value = 'create'
  resetForm()
  form.in_date = dayjs().format('YYYY-MM-DD')
  visible.value = true
  materialOptions.value = []
}

const handleUpdate = (row: any) => {
  dialogStatus.value = 'update'
  Object.assign(form, {
    ...row,
    product_photo: row.product_photo || [],
    quality_report_link: row.quality_report_link || [],
    inspection_report_link: row.inspection_report_link || [],
    in_quantity: Number(row.qty_inbound),
    raw_material_cost: (row.raw_material_cost !== null && row.raw_material_cost !== undefined) ? Number(row.raw_material_cost) : undefined,
    unit_total_cost: (row.unit_total_cost !== null && row.unit_total_cost !== undefined) ? Number(row.unit_total_cost) : undefined,
    sale_price: (row.sale_price !== null && row.sale_price !== undefined) ? Number(row.sale_price) : undefined
  })
  // 计算总成本
  const u = Number(form.unit_total_cost || 0)
  const q = Number(form.in_quantity || 1)
  form.total_price = Number((u * q).toFixed(2))
  if(row.production_start_time && row.production_end_time) { form.production_time_range = [row.production_start_time, row.production_end_time] } else { form.production_time_range = [] }
  productPhotoList.value = form.product_photo.map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }))
  const qReports = form.quality_report_link || []
  qualityFileList.value = qReports.filter(r => !isExternalLink(r)).map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }))
  const qLinks = qReports.filter(r => isExternalLink(r))
  quality_url.value = qLinks.length > 0 ? qLinks[0] : ''
  const iReports = form.inspection_report_link || []
  inspectionFileList.value = iReports.filter(r => !isExternalLink(r)).map(url => ({ name: url.split('/').pop(), url: getImageUrl(url) }))
  const iLinks = iReports.filter(r => isExternalLink(r))
  inspection_url.value = iLinks.length > 0 ? iLinks[0] : ''
  materialOptions.value = [{ id: row.base_id, name: row.material_name, spec: row.spec_model, category: row.category, company_name: row.company_name, isHistory: false }]
  // 回显BOM
  if (form.bom_code) {
    bomOptions.value = [{ bom_no: form.bom_code, version: form.bom_version }]
  }
  visible.value = true
}

const getImageUrl = (url: string) => { if (!url) return ''; if (url.startsWith('http')) return url; return url }
const isExternalLink = (str: string) => { return str && (str.startsWith('http://') || str.startsWith('https://')) && !str.includes('/api/v1/common/files') }
const getImagesOnly = (list: string[]) => { if (!list) return []; return list.filter(item => !isExternalLink(item)) }
const hasExternalLink = (list: string[]) => { if (!list) return false; return list.some(item => isExternalLink(item)) }
const beforeAvatarUpload = (rawFile: any) => { if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') { ElMessage.error('仅支持 JPG/PNG'); return false } if (rawFile.size / 1024 / 1024 > 5) { ElMessage.error('图片不能超过 5MB'); return false } return true }
const customUpload = async (options: any, targetField: 'product_photo' | 'quality_report_link' | 'inspection_report_link') => {
  const { file, onSuccess, onError } = options
  const formData = new FormData(); formData.append('file', file)
  try {
    const res: any = await uploadFile(formData)
    if (res.code === 200) {
      const newUrl = res.data.url; form[targetField].push(newUrl); ElMessage.success('上传成功'); onSuccess(res)
    } else { ElMessage.error(res.msg || '上传失败'); onError(new Error(res.msg)) }
  } catch (e) { ElMessage.error('网络错误'); onError(e) }
}
const handleRemoveImage = async (uploadFile: any, targetField: 'product_photo' | 'quality_report_link' | 'inspection_report_link') => {
  try {
    const urlToRemove = form[targetField].find(u => getImageUrl(u) === uploadFile.url) || uploadFile.url
    form[targetField] = form[targetField].filter(u => u !== urlToRemove)
    if (!isExternalLink(urlToRemove)) { const filename = urlToRemove.split('/').pop(); if (filename) await deleteFile(filename) }
    ElMessage.success('已删除')
  } catch (e) { console.error(e) }
}
const handlePreviewPicture = (uploadFile: any) => { dialogImageUrl.value = uploadFile.url!; dialogVisibleImage.value = true }

const triggerCamera = (field: any) => {
  currentCameraField.value = field;
  cameraDialogVisible.value = true;
}

const handleCameraConfirm = async (file: File) => {
  if (!beforeAvatarUpload(file)) {
    cameraDialogVisible.value = false;
    return;
  }
  const formData = new FormData();
  formData.append('file', file);
  const loadingMsg = ElLoading.service({
    lock: true,
    text: '照片处理中...',
    background: 'rgba(0, 0, 0, 0.7)'
  });
  let success = false;
  try {
    const res: any = await uploadFile(formData);
    if (res.code === 200) {
      const newUrl = res.data.url;
      const field = currentCameraField.value;
      form[field].push(newUrl);
      const previewItem = { name: newUrl.split('/').pop(), url: getImageUrl(newUrl) };
      if (field === 'product_photo') {
        productPhotoList.value.push(previewItem);
      } else if (field === 'quality_report_link') {
        qualityFileList.value.push(previewItem);
      } else if (field === 'inspection_report_link') {
        inspectionFileList.value.push(previewItem);
      }
      ElMessage.success('拍照上传成功');
      success = true;
    } else {
      ElMessage.error(res.msg || '上传失败');
    }
  } catch (e) {
    ElMessage.error('网络错误，上传失败');
  } finally {
    loadingMsg.close();
    if (success) {
      cameraDialogVisible.value = false;
    }
  }
};

const submitForm = async () => {
  await formRef.value.validate(async (valid: boolean) => {
    if(valid) {
      submitting.value = true
      const qList = [...form.quality_report_link]
      const qImages = qList.filter(item => !isExternalLink(item))
      if (quality_url.value && !qList.includes(quality_url.value)) qImages.push(quality_url.value)
      else if (quality_url.value) qImages.push(quality_url.value)
      const iList = [...form.inspection_report_link]
      const iImages = iList.filter(item => !isExternalLink(item))
      if (inspection_url.value && !iList.includes(inspection_url.value)) iImages.push(inspection_url.value)
      else if (inspection_url.value) iImages.push(inspection_url.value)
      const payload = {
        ...form,
        quality_report_link: qImages,
        inspection_report_link: iImages,
        raw_material_cost: Number(form.raw_material_cost || 0),
        unit_total_cost: Number(form.unit_total_cost || 0),
        total_price: Number(form.total_price || 0),
        sale_price: Number(form.sale_price || 0),
        production_start_time: form.production_time_range?.[0],
        production_end_time: form.production_time_range?.[1]
      }
      delete payload.production_time_range
      try {
        if(dialogStatus.value === 'create') {
          const res: any = await createProductInbound(payload)
          ElMessage.success('入库成功')
          const newItem = res.data
          if (newItem) { ElMessage.info('发送打印...'); try { await executePrint(newItem); ElMessage.success('指令已发送') } catch (e: any) { ElMessage.warning('打印失败') } }
        } else { await updateProductInbound(form.id!, payload); ElMessage.success('更新成功') }
        visible.value = false; fetchData()
      } catch(e:any) {
        ElMessage.error(e.msg || '操作失败')
      } finally { submitting.value = false }
    }
  })
}

const handleDelete = async (row: any) => { try { await deleteProductInbound(row.id); ElMessage.success('删除成功'); fetchData() } catch(e) { ElMessage.error('删除失败') } }
const handlePrint = async (row: any) => {
  printVisible.value = true; printLoading.value = true; previewUrl.value = ''
  currentPrintData.value = { global_print_id: row.global_print_id, material_name: row.material_name, spec_model: row.spec_model, category: row.category, material_type: row.material_type, warehouse_loc: row.warehouse_loc, serial_number: row.serial_number, sku: row.sku }
  try { const res: any = await getLabelPreview(currentPrintData.value); previewUrl.value = res.data } catch (e) { ElMessage.error('预览失败') } finally { printLoading.value = false }
}
const confirmPrint = async () => { printing.value = true; try { await executePrint(currentPrintData.value); ElMessage.success('已发送'); printVisible.value = false } catch (e: any) { ElMessage.error('打印失败') } finally { printing.value = false } }
const resetForm = () => {
  materialOptions.value = []; bomOptions.value = []; productPhotoList.value = []; qualityFileList.value = []; inspectionFileList.value = []; quality_url.value = ''; inspection_url.value = ''
  Object.assign(form, { id: undefined, base_id: undefined, material_name: '', spec_model: '', material_type: '', category: '', unit: '', sku: '', barcode: '', serial_number: '', in_date: '', in_quantity: 1, stock_quantity: 1, available_quantity: 1, warehouse_location: '', status: '在库', quality_status: '合格', bom_code: '', bom_version: '', work_order_code: '', order_id: '', production_manager: '', production_time_range: [], raw_material_cost: undefined, unit_total_cost: undefined, total_price: undefined, sale_price: undefined, quality_report_link: [], inspection_report_link: [], product_photo: [], detail_link: '' })
}
const getStatusType = (s:string) => ({'在库':'success','出库':'info','借库':'warning','损耗':'danger'}[s]||'warning')
const getQualityType = (s:string) => ({'合格':'success','不合格':'danger','待检':'info'}[s]||'info')
const formatMoney = (val:any) => isNaN(Number(val)) ? '-' : `¥ ${Number(val).toFixed(2)}`
onMounted(() => {
  // 先根据权限初始化列显示状态
  initColumnPermissions()
  fetchData()
  fetchOptions()
  loadWarehouseTree()
})

// 成本计算监听
watch([() => form.unit_total_cost, () => form.in_quantity], ([unit, qty]) => {
  const unitNum = Number(unit || 0)
  const qtyNum = Number(qty || 1)
  form.total_price = Number((unitNum * qtyNum).toFixed(2))
})
</script>

<style scoped>
.product-module { background: #f5f7fa; padding: 20px; min-height: 100vh; }
.header-tools { display: flex; justify-content: space-between; margin-bottom: 20px; background: #fff; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05); flex-wrap: wrap; }
.left-tools { display: flex; gap: 10px; align-items: center; flex: 1; flex-wrap: wrap; }
.right-tools { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.modern-table { border-radius: 8px; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05); }
:deep(.table-header-gray th) { background-color: #f8f9fb !important; color: #606266; }
.tag-sn { color: #409EFF; font-weight: bold; font-family: monospace; }
.stock-num { font-weight: bold; font-size: 15px; }
.form-card { background: #fff; border-radius: 8px; margin-bottom: 20px; border: 1px solid #e4e7ed; overflow: hidden; }
.card-title { background: #fcfcfc; padding: 10px 20px; border-bottom: 1px solid #ebeef5; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.card-title .icon { font-size: 18px; }
.card-content { padding: 20px; }
.basic-card { border-left: 4px solid #409EFF; } .basic-card .icon { color: #409EFF; }
.inbound-card { border-left: 4px solid #67C23A; } .inbound-card .icon { color: #67C23A; }
.production-card { border-left: 4px solid #E6A23C; } .production-card .icon { color: #E6A23C; }
.identity-panel { background: #fffbf0; border: 1px dashed #e6a23c; padding: 15px; margin: 10px 0; border-radius: 6px; }
.prefix-tag.sn { color: #409EFF; background: #ecf5ff; padding: 0 5px; font-weight: bold; border-radius: 4px; }
.option-item { display: flex; justify-content: space-between; width: 100%; align-items: center; }
.opt-name { font-weight: bold; }
.opt-spec { color: #8492a6; font-size: 12px; margin-right: 10px; }
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background: #f5f7fa; border-bottom: 1px solid #dcdfe6; padding-left: 0; }
.search-tip { color: #909399; font-size: 12px; margin-left: 10px; display: flex; align-items: center; gap: 4px; }
.dialog-scroll-container { padding: 20px; max-height: 70vh; overflow-y: auto; }
.dialog-footer { display: flex; justify-content: flex-end; gap: 15px; padding: 20px; border-top: 1px solid #ebeef5; }
.money-text { font-family: 'Consolas', monospace; color: #303133; }
.preview-box { min-height: 150px; display: flex; justify-content: center; align-items: center; background: #f5f7fa; border-radius: 4px; }
.empty-preview { color: #909399; }
.more-images-badge { margin-left: 5px; background: #909399; color: #fff; border-radius: 10px; padding: 0 6px; font-size: 12px; }
.clickable-text { color: #409EFF; cursor: pointer; font-weight: 500; text-decoration: underline; }
.id-cell { display: flex; align-items: center; }
.id-text { font-family: monospace; color: #606266; }
.upload-container { display: flex; flex-wrap: wrap; gap: 8px; }
:deep(.el-upload--picture-card) { width: 100px; height: 100px; line-height: 100px; }
:deep(.el-upload-list--picture-card .el-upload-list__item) { width: 100px; height: 100px; }
.camera-card { width: 100px; height: 100px; background-color: #fbfdff; border: 1px dashed #c0ccda; border-radius: 6px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; align-items: center; cursor: pointer; transition: all 0.3s; color: #8c939d; }
.camera-card:hover { border-color: #409EFF; color: #409EFF; }
.camera-card .text { font-size: 12px; margin-top: 5px; }
.camera-card .el-icon { font-size: 24px; }

/* [重点] 下拉框 Flex 布局 */
.option-item { display: flex; align-items: center; padding: 8px 0; width: 100%; }
.opt-main { flex: 1; min-width: 0; margin-right: 10px; }
.opt-name { font-weight: 600; font-size: 14px; color: #333; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.opt-meta { width: 100px; text-align: right; flex-shrink: 0; margin-right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.opt-spec { color: #999; font-size: 12px; }
.opt-tags { display: flex; gap: 5px; flex-shrink: 0; }
.company-tag { font-weight: bold; }

/* [新增] 修复 filter-item-select/input 样式 */
.filter-item-select { /* 宽度已在行内样式控制 */ }
.filter-item-input { /* 宽度已在行内样式控制 */ }
.action-btn { font-weight: 500; }

.search-btn { background-color: #E6F1FC; border-color: #A3D0FD; color: #409EFF; }
.search-btn:hover { background-color: #409EFF; border-color: #409EFF; color: #fff; }
.reset-btn { background-color: #fff; border: 1px solid #dcdfe6; }
.reset-btn:hover { border-color: #c0c4cc; color: #606266; }

/* [新增] 修复弹窗最小高度 */
.dialog-scroll-container { min-height: 450px; }

/* [新增] 纯文本样式 */
.is-text-view :deep(.el-input__wrapper) { box-shadow: none !important; background-color: transparent !important; border-bottom: 1px dashed #dcdfe6; border-radius: 0; padding-left: 0; }
.is-text-view :deep(.el-input__inner) { color: #303133; font-weight: 600; font-size: 14px; cursor: text; }

/* 左对齐数字框 */
:deep(.el-input-number .el-input__inner) { text-align: left; }
</style>

<style>
.product-dropdown { width: 580px !important; }
.product-dropdown .el-select-dropdown__wrap { max-height: 320px !important; }
.product-dropdown .el-input__suffix { z-index: 10; }
</style>
