gaoluyang
20 小时以前 4c6f9bcc9b3f8bdf5298d73d1035bad529f86d69
src/views/basicData/product/index.vue
@@ -1,385 +1,632 @@
<template>
  <div class="app-container product-view">
    <div class="left">
      <div>
        <el-input
            v-model="search"
            style="width: 240px"
            placeholder="输入关键字进行搜索"
            @change="searchFilter"
            @clear="searchFilter"
    <div class="main-content">
      <div class="search-section">
        <el-form :inline="true" :model="queryForm" class="search-form">
          <el-form-item label="产品名称">
            <el-input
              v-model="queryForm.productName"
              placeholder="请输入产品名称"
              clearable
              style="width: 200px"
              @keyup.enter="handleSearch"
            />
          </el-form-item>
          <el-form-item label="图纸编号">
            <el-input
              v-model="queryForm.model"
              placeholder="请输入图纸编号"
              clearable
              style="width: 200px"
              @keyup.enter="handleSearch"
            />
          </el-form-item>
          <el-form-item label="产品属性">
            <el-select
              v-model="queryForm.productType"
              placeholder="请选择产品属性"
              clearable
              style="width: 150px"
            >
              <el-option label="自制" :value="1" />
              <el-option label="外购" :value="2" />
              <el-option label="委外" :value="3" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch" icon="Search">
              搜索
            </el-button>
            <el-button @click="handleReset" icon="Refresh">
              重置
            </el-button>
          </el-form-item>
        </el-form>
        <div class="action-buttons">
          <el-button type="primary" @click="openModelDia('add')" icon="Plus">
            新增产品
          </el-button>
          <el-button type="success" @click="handleImport" icon="Upload">
            导入
          </el-button>
          <el-button type="danger" @click="handleDelete" icon="Delete" plain>
            删除
          </el-button>
        </div>
      </div>
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
      ></PIMTable>
    </div>
    <FormDialog
      v-model="modelDia"
      title="产品信息"
      width="500px"
      @close="closeModelDia"
      @confirm="submitModelForm"
    >
      <el-form
        :model="modelForm"
        label-width="100px"
        :rules="modelRules"
        ref="modelFormRef"
      >
        <el-form-item label="产品名称" prop="productName">
          <el-input
            v-model="modelForm.productName"
            placeholder="请输入产品名称"
            clearable
            prefix-icon="Search"
        />
        <el-button type="primary" @click="openProDia('add')" style="margin-left: 10px">新增产品</el-button>
      </div>
      <div>
        <el-tree ref="tree" v-loading="treeLoad" :data="list" @node-click="handleNodeClick"
                 :expand-on-click-node="false"
                 :default-expanded-keys="expandedKeys" :draggable="true" :filter-node-method="filterNode"
                 :props="{ children: 'children', label: 'label' }" highlight-current node-key="id"
                 style="height: calc(100vh - 190px);overflow-y: scroll;scrollbar-width: none;">
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span>{{ node.label }}</span>
              <div>
                <el-button type="primary" link @click="openProDia('edit', data)">
                  编辑
                </el-button>
                <!-- 修改此处 -->
                <el-button
                    v-if="!node.childNodes.length"
                    style="margin-left: 4px"
                    type="danger"
                    link
                    @click="remove(node, data)"
                >
                  删除
                </el-button>
            maxlength="50"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="图纸编号" prop="model">
          <el-input
            v-model="modelForm.model"
            placeholder="请输入图纸编号"
            clearable
          />
        </el-form-item>
        <el-form-item label="单位" prop="unit">
          <el-select
            v-model="modelForm.unit"
            placeholder="请选择单位"
            clearable
            style="width: 100%"
          >
            <el-option label="件" value="件" />
            <el-option label="套" value="套" />
            <el-option label="台" value="台" />
          </el-select>
        </el-form-item>
        <el-form-item label="产品属性" prop="productType">
          <el-select
            v-model="modelForm.productType"
            placeholder="请选择产品属性"
            clearable
            style="width: 100%"
          >
            <el-option label="自制" :value="1" />
            <el-option label="外购" :value="2" />
            <el-option label="委外" :value="3" />
          </el-select>
        </el-form-item>
        <el-form-item label="工艺路线" prop="routeId">
          <el-select
            v-model="modelForm.routeId"
            placeholder="请选择工艺路线"
            clearable
            style="width: 100%"
            filterable
          >
            <el-option
              v-for="item in processRouteList"
              :key="item.id"
              :label="item.processRouteName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="上传图纸" prop="drawingFile">
          <el-upload
            v-model:file-list="drawingFileList"
            :action="upload.url"
            :headers="upload.headers"
            :data="upload.data"
            :on-success="handleDrawingUploadSuccess"
            :on-remove="handleDrawingRemove"
            :before-upload="handleDrawingBeforeUpload"
            :limit="1"
            accept=".pdf,.jpg,.jpeg,.png,.dwg"
            list-type="picture-card"
          >
            <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
            <template #tip>
              <div class="el-upload__tip">
                支持 pdf、jpg、jpeg、png、dwg 格式,大小不超过 10MB
              </div>
            </div>
          </template>
        </el-tree>
      </div>
    </div>
    <div class="right">
      <div style="margin-bottom: 10px">
        <el-button type="primary" @click="openModelDia('add')">新增规格型号</el-button>
        <el-button type="danger" @click="handleDelete" style="margin-left: 10px" plain>删除</el-button>
      </div>
      <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange"
                :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
    </div>
    <el-dialog v-model="productDia" title="产品" width="400px">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="产品名称:" prop="productName">
              <el-input v-model="form.productName" placeholder="请输入产品名称" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeProDia">取消</el-button>
    </FormDialog>
    <FormDialog
      v-model="importDia"
      title="产品导入"
      width="600px"
      @cancel="importDia = false"
      @confirm="submitImport"
    >
      <el-upload
        ref="importUploadRef"
        :limit="1"
        accept=".xlsx,.xls"
        :action="importUpload.url"
        :headers="importUpload.headers"
        :before-upload="importUpload.beforeUpload"
        :on-success="importUpload.onSuccess"
        :on-error="importUpload.onError"
        :on-progress="importUpload.onProgress"
        :on-change="importUpload.onChange"
        :auto-upload="false"
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处,或<em>点击上传</em>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="modelDia" title="产品" width="400px">
      <el-form :model="modelForm" label-width="140px" label-position="top" :rules="modelRules" ref="modelFormRef">
        <el-row>
          <el-col :span="24">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="modelForm.model" placeholder="请输入规格型号" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="modelForm.unit" placeholder="请输入单位" clearable/>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitModelForm">确认</el-button>
          <el-button @click="closeProDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
        <template #tip>
          <div class="el-upload__tip">
            仅支持 xls/xlsx,大小不超过 10MB。
            <el-button link type="primary" @click="importTemplate">下载导入模板</el-button>
          </div>
        </template>
      </el-upload>
    </FormDialog>
  </div>
</template>
<script setup>
import {ref} from "vue";
import {ElMessageBox} from "element-plus";
import { ref, reactive, onMounted } from "vue";
import { ElMessageBox } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import { getToken } from "@/utils/auth.js";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
  addOrEditProduct,
  addOrEditProductModel,
  delProduct, delProductModel,
  modelList,
  productTreeList
  delProduct,
  productListPage,
  downloadTemplate,
} from "@/api/basicData/product.js";
const { proxy } = getCurrentInstance()
import { listPage as getProcessRouteList } from "@/api/productionManagement/processRoute.js";
import ImportExcel from "./ImportExcel/index.vue";
const productDia = ref(false)
const modelDia = ref(false)
const modelOperationType = ref('')
const search = ref('')
const currentId = ref('')
const currentParentId = ref('')
const operationType = ref('')
const treeLoad = ref(false)
const list = ref([])
const expandedKeys = ref([])
const { proxy } = getCurrentInstance();
const importUploadRef = ref(null);
const modelDia = ref(false);
const importDia = ref(false);
const modelOperationType = ref("");
const tableData = ref([]);
const tableLoading = ref(false);
const selectedRows = ref([]);
const modelFormRef = ref();
const processRouteList = ref([]);
const drawingFileList = ref([]);
const upload = reactive({
  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
  headers: { Authorization: "Bearer " + getToken() },
  data: { type: 13 },
});
const queryForm = reactive({
  productName: "",
  model: "",
  productType: null,
});
const page = reactive({
  current: 1,
  size: 50,
  total: 0,
});
const tableColumn = ref([
  {
    label: '规格型号',
    prop: 'model',
    label: "产品名称",
    prop: "productName",
    minWidth: 200,
  },
  {
    label: '单位',
    prop: 'unit',
    label: "图纸编号",
    prop: "model",
    minWidth: 150,
  },
  {
    label: "单位",
    prop: "unit",
    minWidth: 100,
  },
  {
    label: "产品属性",
    prop: "productType",
    width: 100,
    dataType: "tag",
    formatData: (v) => ({ "1": "自制", "2": "外购", "3": "委外" }[String(v)] ?? v),
    formatType: (v) => {
      const typeMap = { "1": "success", "2": "warning", "3": "info" };
      return typeMap[String(v)] || "info";
    },
  },
  {
    dataType: "action",
    label: "操作",
    align: 'center',
    align: "center",
    width: 100,
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openModelDia('edit', row);
          openModelDia("edit", row);
        },
      },
    ],
  },
])
const tableData = ref([])
const tableLoading = ref(false)
const total = ref(0)
const selectedRows = ref([])
const page = reactive({
  current: 1,
  size: 10,
})
]);
const data = reactive({
  form: {
    productName: '',
  },
  rules: {
    productName: [{ required: true, message: "请输入", trigger: "blur" }],
  },
  modelForm: {
    model: '',
    unit: '',
    productName: "",
    model: "",
    unit: "",
    productType: null,
    routeId: null,
    drawingFile: "",
    tempFileIds: [],
    salesLedgerFiles: [],
  },
  modelRules: {
    model: [{ required: true, message: "请输入", trigger: "blur" }],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    productName: [
      { required: true, message: "请输入产品名称", trigger: "blur" },
      { max: 50, message: "产品名称不能超过50个字符", trigger: "blur" },
    ],
    model: [{ required: true, message: "请输入图纸编号", trigger: "blur" }],
    unit: [{ required: true, message: "请选择单位", trigger: "change" }],
    productType: [{ required: true, message: "请选择产品属性", trigger: "change" }],
  },
});
const { modelForm, modelRules } = toRefs(data);
const importUpload = reactive({
  title: "产品导入",
  open: false,
  url: import.meta.env.VITE_APP_BASE_API + "/basic/product/import",
  headers: { Authorization: "Bearer " + getToken() },
  isUploading: false,
  beforeUpload: (file) => {
    const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
    const isLt10M = file.size / 1024 / 1024 < 10;
    if (!isExcel) {
      proxy.$modal.msgError("上传文件只能是 xlsx/xls 格式!");
      return false;
    }
    if (!isLt10M) {
      proxy.$modal.msgError("上传文件大小不能超过 10MB!");
      return false;
    }
    return true;
  },
  onChange: (file, fileList) => {
    console.log('文件状态改变', file, fileList);
  },
  onProgress: (event, file, fileList) => {
    console.log('上传中...', event.percent);
  },
  onSuccess: (response, file, fileList) => {
    console.log('上传成功', response, file, fileList);
    importUpload.isUploading = false;
    if (response.code === 200) {
      proxy.$modal.msgSuccess("导入成功");
      importDia.value = false;
      if (importUploadRef.value) {
        importUploadRef.value.clearFiles();
      }
      getModelList();
    } else {
      proxy.$modal.msgError(response.msg || "导入失败");
    }
  },
  onError: (error, file, fileList) => {
    console.log('上传失败', error, file, fileList);
    importUpload.isUploading = false;
    proxy.$modal.msgError("导入失败");
  }
})
const { form, rules, modelForm, modelRules } = toRefs(data)
// 查询产品树
const getProductTreeList = () => {
  treeLoad.value = true;
  productTreeList().then(res => {
    list.value = res
    list.value.forEach((a) => {
      expandedKeys.value.push(a.label);
    });
    treeLoad.value = false;
  }).catch(err => {
    treeLoad.value = false;
  })
}
// 过滤产品树
const searchFilter = () => {
  proxy.$refs.tree.filter(search.value);
}
// 打开产品弹框
const openProDia = (type, data) => {
  operationType.value = type;
  productDia.value = true
  form.value.productName = ''
  if (type === 'edit') {
    form.value.productName = data.productName
  }
}
// 打开规格型号弹框
});
const handleSearch = () => {
  page.current = 1;
  getModelList();
};
const handleReset = () => {
  queryForm.productName = "";
  queryForm.model = "";
  queryForm.productType = null;
  page.current = 1;
  getModelList();
};
const openModelDia = (type, data) => {
  modelOperationType.value = type;
  modelDia.value = true
  modelForm.value.model = ''
  modelForm.value.model = ''
  modelForm.value.id = ''
  if (type === 'edit') {
    modelForm.value = {...data}
  }
}
// 提交产品名称修改
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      if (operationType.value === 'add') {
        form.value.parentId = currentId.value
        form.value.id = ''
      } else {
        form.value.id = currentId.value
        form.value.parentId = ''
      }
      addOrEditProduct(form.value).then(res => {
        proxy.$modal.msgSuccess("提交成功")
        closeProDia()
        getProductTreeList()
      })
  modelDia.value = true;
  modelForm.value.productName = "";
  modelForm.value.model = "";
  modelForm.value.id = "";
  modelForm.value.unit = "";
  modelForm.value.productType = null;
  modelForm.value.routeId = null;
  modelForm.value.drawingFile = "";
  modelForm.value.tempFileIds = [];
  modelForm.value.salesLedgerFiles = [];
  drawingFileList.value = [];
  if (type === "edit") {
    modelForm.value = { ...data };
    modelForm.value.tempFileIds = data.tempFileIds || [];
    modelForm.value.salesLedgerFiles = data.salesLedgerFiles || [];
    if (data.drawingFile) {
      drawingFileList.value = [{
        name: data.drawingFile.split('/').pop(),
        url: data.drawingFile
      }];
    }
  })
}
// 关闭产品弹框
const closeProDia = () => {
  proxy.$refs.formRef.resetFields();
  productDia.value = false;
}
// 删除产品
const remove = (node, data) => {
  let ids = []
  ids.push(data.id)
  ElMessageBox.confirm(
      '选中的内容将被删除,是否确认删除?',
      '删除提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    tableLoading.value = true
    delProduct(ids).then(res => {
      proxy.$modal.msgSuccess("删除成功")
      getProductTreeList()
    }).finally(() => {
      tableLoading.value = false
    })
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
}
// 选择产品
const handleNodeClick = (val, node, el) => {
  currentId.value = val.id
  currentParentId.value = val.parentId
  getModelList()
}
  }
};
// 提交规格型号修改
const submitModelForm = () => {
  proxy.$refs.modelFormRef.validate(valid => {
  modelFormRef.value.validate((valid) => {
    if (valid) {
      modelForm.value.productId = currentId.value
      addOrEditProductModel(modelForm.value).then(res => {
        proxy.$modal.msgSuccess("提交成功")
        closeModelDia()
        getModelList()
      })
      addOrEditProductModel(modelForm.value).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeModelDia();
        getModelList();
      });
    }
  })
}
// 关闭产品弹框
const closeModelDia = () => {
  proxy.$refs.modelFormRef.resetFields();
  modelDia.value = false;
}
// 表格选择数据
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
  });
};
// 查询规格型号
const pagination = ({ current, limit }) => {
  page.current = current;
  page.size = limit;
  getModelList()
}
const closeModelDia = () => {
  modelFormRef.value.resetFields();
  modelDia.value = false;
};
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getModelList();
};
const getModelList = () => {
  tableLoading.value = true
  modelList({id: currentId.value}).then(res => {
    tableLoading.value = false
    tableData.value = res
  })
}
// 删除规格型号
const handleDelete = () => {
  let ids = []
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map(item => item.id);
  } else {
    proxy.$modal.msgWarning('请选择数据')
    return
  }
  ElMessageBox.confirm(
      '选中的内容将被删除,是否确认删除?',
      '删除提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    tableLoading.value = true
    delProductModel(ids).then(res => {
      proxy.$modal.msgSuccess("删除成功")
      getModelList()
    }).finally(() => {
      tableLoading.value = false
    })
  tableLoading.value = true;
  productListPage({
    productName: queryForm.productName.trim(),
    model: queryForm.model.trim(),
    productType: queryForm.productType,
    current: page.current,
    size: page.size,
  }).then((res) => {
    tableData.value = res.data.records;
    page.total = res.data.total;
    tableLoading.value = false;
  }).catch(() => {
    proxy.$modal.msg("已取消")
    tableLoading.value = false;
  });
};
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
}
// 调用tree过滤方法 中文英过滤
const filterNode = (value, data, node) => {
  if (!value) {    //如果数据为空,则返回true,显示所有的数据项
    return true
    .then(() => {
      tableLoading.value = true;
      delProduct(ids)
        .then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getModelList();
        })
        .finally(() => {
          tableLoading.value = false;
        });
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
const handleImport = () => {
  importDia.value = true;
  if (importUploadRef.value) {
    importUploadRef.value.clearFiles();
  }
  // 查询列表是否有匹配数据,将值小写,匹配英文数据
  let val = value.toLowerCase()
  return chooseNode(val, data, node) // 调用过滤二层方法
}
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。name是中文字符,enName是英文字符.
const chooseNode = (value, data, node) => {
  if (data.label.indexOf(value) !== -1) {
    return true
};
const submitImport = () => {
  importUploadRef.value.submit();
};
const importTemplate = () => {
  proxy.download("/basic/product/downloadTemplate", {}, "产品导入模板.xlsx");
};
const getProcessRouteListData = () => {
  getProcessRouteList({ current: 1, size: 1000 }).then((res) => {
    processRouteList.value = res.data.records || [];
  }).catch(() => {
    processRouteList.value = [];
  });
};
const handleDrawingBeforeUpload = (file) => {
  const isAllowed = [
    'application/pdf',
    'image/jpeg',
    'image/jpg',
    'image/png',
    'application/dwg'
  ].includes(file.type) || file.name.endsWith('.dwg');
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isAllowed) {
    proxy.$modal.msgError("只能上传 pdf、jpg、jpeg、png、dwg 格式的文件!");
    return false;
  }
  const level = node.level
  // 如果传入的节点本身就是一级节点就不用校验了
  if (level === 1) {
    return false
  if (!isLt10M) {
    proxy.$modal.msgError("上传文件大小不能超过 10MB!");
    return false;
  }
  // 先取当前节点的父节点
  let parentData = node.parent
  // 遍历当前节点的父节点
  let index = 0
  while (index < level - 1) {
    // 如果匹配到直接返回,此处name值是中文字符,enName是英文字符。判断匹配中英文过滤
    if (parentData.data.label.indexOf(value) !== -1) {
      return true
    }
    // 否则的话再往上一层做匹配
    parentData = parentData.parent
    index++
  return true;
};
const handleDrawingUploadSuccess = (response, file, fileList) => {
  console.log('上传成功响应', response);
  console.log('response.data', response.data);
  if (response.code === 200) {
    modelForm.value.tempFileIds = [response.data?.tempId];
    modelForm.value.salesLedgerFiles = [{
      tempId: response.data?.tempId,
      originalName: response.data?.originalName || file.name,
      tempPath: response.data?.tempPath,
      type: response.data?.type || 13
    }];
    proxy.$modal.msgSuccess("上传成功");
  } else {
    proxy.$modal.msgError(response.msg || "上传失败");
  }
  // 没匹配到返回false
  return false
}
getProductTreeList()
};
const handleDrawingRemove = (file) => {
  modelForm.value.tempFileIds = [];
  modelForm.value.salesLedgerFiles = [];
};
onMounted(() => {
  getModelList();
  getProcessRouteListData();
});
</script>
<style scoped>
.product-view {
  display: flex;
  padding: 20px;
  background: #f5f7fa;
  min-height: 100vh;
}
.left {
  width: 380px;
  padding: 16px;
.main-content {
  background: #ffffff;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.right {
  width: calc(100% - 380px);
  padding: 16px;
  margin-left: 20px;
  background: #ffffff;
.search-section {
  margin-bottom: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid #e4e7ed;
}
.custom-tree-node {
  flex: 1;
.search-form {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
.search-form :deep(.el-form-item) {
  margin-bottom: 12px;
}
.action-buttons {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 148px;
  height: 148px;
  text-align: center;
  line-height: 148px;
}
:deep(.el-upload--picture-card) {
  width: 148px;
  height: 148px;
}
:deep(.el-upload-list__item) {
  width: 148px;
  height: 148px;
}
:deep(.el-upload__tip) {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
}
:deep(.el-dialog__body) {
  padding: 20px 24px;
}
:deep(.el-form-item__label) {
  font-weight: 500;
  color: #303133;
}
:deep(.el-input__inner) {
  border-radius: 4px;
}
:deep(.el-button) {
  border-radius: 4px;
  font-weight: 500;
}
:deep(.el-upload-dragger) {
  border-radius: 8px;
  border: 2px dashed #dcdfe6;
  transition: all 0.3s;
}
:deep(.el-upload-dragger:hover) {
  border-color: #409eff;
  background-color: #f5f7fa;
}
</style>