已修改9个文件
已添加7个文件
1543 ■■■■■ 文件已修改
src/api/equipment/management/index.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/PIMTable.vue 432 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/Pagination.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/table.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/useFormData.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/useModal.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/usePaginationApi.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/index.js 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/archiveManagement/index.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicInformation/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipment/management/index.vue 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipment/management/mould/managementDialog.vue 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspectionManagement/index.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesOutbound/components/formDia.vue 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesOutbound/index.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/index.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/equipment/management/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
// è®¾å¤‡ç®¡ç†
import request from '@/utils/request'
// /equipmentManagement/list
// æŸ¥è¯¢è®¾å¤‡ç®¡ç†åˆ—表
export function getManagementList(query) {
  return request({
    url: '/equipmentManagement/list',
    method: 'get',
    params: query
  })
}
// /equipmentManagement/addOrEditEquipment
// æ·»åŠ æˆ–ç¼–è¾‘è®¾å¤‡
export function addOrEditEquipment(data) {
  return request({
    url: '/equipmentManagement/addOrEditEquipment',
    method: 'post',
    data
  })
}
// /equipmentManagement/delEquipment
// åˆ é™¤è®¾å¤‡
export function delEquipment(data) {
  return request({
    url: '/equipmentManagement/delEquipment',
    method: 'delete',
    data
  })
}
src/components/Table/PIMTable.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,432 @@
<template>
  <el-table
    ref="multipleTable"
    v-loading="tableLoading"
    :border="border"
    :data="tableData"
    :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
    :height="height"
    :highlight-current-row="highlightCurrentRow"
    :row-class-name="rowClassName"
    :row-style="rowStyle"
    :row-key="rowKey"
    style="width: 100%"
    tooltip-effect="dark"
    :expand-row-keys="expandRowKeys"
    :show-summary="isShowSummary"
    :summary-method="summaryMethod"
    @row-click="rowClick"
    @current-change="currentChange"
    @selection-change="handleSelectionChange"
    @expand-change="expandChange"
    class="lims-table"
  >
    <el-table-column
      align="center"
      type="selection"
      width="55"
      v-if="isSelection"
    />
    <el-table-column align="center" label="序号" type="index" width="60" />
    <el-table-column
      v-for="(item, index) in column"
      :key="index"
      :column-key="item.columnKey"
      :filter-method="item.filterHandler"
      :filter-multiple="item.filterMultiple"
      :filtered-value="item.filteredValue"
      :filters="item.filters"
      :fixed="item.fixed"
      :label="item.label"
      :prop="item.prop"
      show-overflow-tooltip
      :align="item.align"
      :sortable="!!item.sortable"
      :type="item.type"
      :width="item.width"
    >
      <template
        v-if="item.hasOwnProperty('colunmTemplate')"
        #[item.colunmTemplate]="scope"
      >
        <slot
          v-if="item.theadSlot"
          :name="item.theadSlot"
          :index="scope.$index"
          :row="scope.row"
        />
      </template>
      <template #default="scope">
        <!-- æ’æ§½ -->
        <div v-if="item.dataType == 'slot'">
          <slot
            v-if="item.slot"
            :index="scope.$index"
            :name="item.slot"
            :row="scope.row"
          />
        </div>
        <!-- è¿›åº¦æ¡ -->
        <div v-else-if="item.dataType == 'progress'">
          <el-progress :percentage="Number(scope.row[item.prop])" />
        </div>
        <!-- å›¾ç‰‡ -->
        <div v-else-if="item.dataType == 'image'">
          <img
            :src="javaApi + '/img/' + scope.row[item.prop]"
            alt=""
            style="width: 40px; height: 40px; margin-top: 10px"
          />
        </div>
        <!-- tag -->
        <div v-else-if="item.dataType == 'tag'">
          <el-tag
            v-if="
              typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
              'string'
            "
            :title="formatters(scope.row[item.prop], item.formatData)"
            :type="formatType(scope.row[item.prop], item.formatType)"
          >
            {{ formatters(scope.row[item.prop], item.formatData) }}
          </el-tag>
          <el-tag
            v-for="(tag, index) in dataTypeFn(
              scope.row[item.prop],
              item.formatData
            )"
            v-else-if="
              typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
              'object'
            "
            :key="index"
            :title="formatters(scope.row[item.prop], item.formatData)"
            :type="formatType(tag, item.formatType)"
          >
            {{ item.tagGroup ? tag[item.tagGroup.label] ?? tag : tag }}
          </el-tag>
          <el-tag
            v-else
            :title="formatters(scope.row[item.prop], item.formatData)"
            :type="formatType(scope.row[item.prop], item.formatType)"
          >
            {{ formatters(scope.row[item.prop], item.formatData) }}
          </el-tag>
        </div>
        <!-- æŒ‰é’® -->
        <div v-else-if="item.dataType == 'action'">
          <template v-for="(o, key) in item.operation" :key="key">
            <el-button
              v-show="o.type != 'upload'"
              size="small"
              v-if="o.showHide ? o.showHide(scope.row) : true"
              :disabled="o.disabled ? o.disabled(scope.row) : false"
              :plain="o.plain"
              type="primary"
              :style="{
                color:
                  o.name === '删除' || o.name === 'delete'
                    ? '#f56c6c'
                    : o.color,
              }"
              link
              @click="o.clickFun(scope.row)"
              :key="key"
            >
              {{ o.name }}
            </el-button>
            <el-upload
              :action="
                javaApi +
                o.url +
                '?id=' +
                (o.uploadIdFun ? o.uploadIdFun(scope.row) : scope.row.id)
              "
              ref="uploadRef"
              size="small"
              :multiple="o.multiple ? o.multiple : false"
              :limit="1"
              :disabled="o.disabled ? o.disabled(scope.row) : false"
              :accept="
                o.accept
                  ? o.accept
                  : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
              "
              v-if="o.type == 'upload'"
              style="display: inline-block; width: 50px"
              v-show="o.showHide ? o.showHide(scope.row) : true"
              :headers="uploadHeader"
              :before-upload="(file) => beforeUpload(file, scope.$index)"
              :on-change="
                (file, fileList) => handleChange(file, fileList, scope.$index)
              "
              :on-error="
                (error, file, fileList) =>
                  onError(error, file, fileList, scope.$index)
              "
              :on-success="
                (response, file, fileList) =>
                  handleSuccessUp(response, file, fileList, scope.$index)
              "
              :on-exceed="onExceed"
              :show-file-list="false"
            >
              <el-button
                :size="o.size ? o.size : 'small'"
                link
                type="primary"
                :disabled="o.disabled ? o.disabled(scope.row) : false"
                >{{ o.name }}</el-button
              >
            </el-upload>
          </template>
        </div>
        <!-- å¯ç‚¹å‡»çš„æ–‡å­— -->
        <div
          v-else-if="item.dataType == 'link'"
          class="cell link"
          style="width: 100%"
          @click="goLink(scope.row, item.linkMethod)"
        >
          <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
        </div>
        <!-- é»˜è®¤çº¯å±•示数据 -->
        <div v-else class="cell" style="width: 100%">
          <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
          <span v-else>{{
            formatters(scope.row[item.prop], item.formatData)
          }}</span>
        </div>
      </template>
    </el-table-column>
  </el-table>
  <pagination
    v-if="page.total > 0"
    :total="page.total"
    :layout="page.layout"
    :page="page.current"
    :limit="page.size"
    @pagination="paginationSearch"
  />
</template>
<script setup>
import pagination from "./Pagination.vue";
import { ref, inject, getCurrentInstance } from "vue";
import { ElMessage } from "element-plus";
// èŽ·å–å…¨å±€çš„ uploadHeader
const { proxy } = getCurrentInstance();
const uploadHeader = proxy.uploadHeader;
const javaApi = proxy.javaApi;
const emit = defineEmits(["pagination", "expand-change", "selection-change"]);
// Filters
const typeFn = (val, row) => {
  return typeof val === "function" ? val(row) : val;
};
const formatters = (val, format) => {
  return typeof format === "function" ? format(val) : val;
};
// Props(使用 defineProps çš„非 TS å½¢å¼ï¼‰
const props = defineProps({
  tableLoading: {
    type: Boolean,
    default: false,
  },
  height: {
    type: [Number, String],
    default: "calc(100vh - 22em)",
  },
  expandRowKeys: {
    type: Array,
    default: () => [],
  },
  summaryMethod: {
    type: Function,
    default: () => {},
  },
  rowClick: {
    type: Function,
    default: () => {},
  },
  currentChange: {
    type: Function,
    default: () => {},
  },
  border: {
    type: Boolean,
    default: true,
  },
  isSelection: {
    type: Boolean,
    default: false,
  },
  isShowSummary: {
    type: Boolean,
    default: false,
  },
  highlightCurrentRow: {
    type: Boolean,
    default: false,
  },
  headerCellStyle: {
    type: Object,
    default: () => ({}),
  },
  column: {
    type: Array,
    default: () => [],
  },
  rowClassName: {
    type: Function,
    default: () => "",
  },
  rowStyle: {
    type: [Object, Function],
    default: () => ({}),
  },
  tableData: {
    type: Array,
    default: () => [],
  },
  rowKey: {
    type: String,
    default: undefined,
  },
  page: {
    type: Object,
    default: () => ({
      total: 0,
      current: 0,
      size: 10,
      layout: "total, sizes, prev, pager, next, jumper",
    }),
  },
  total: {
    type: Number,
    default: 0,
  },
});
// Data
const uploadRefs = ref([]);
const currentFiles = ref({});
const uploadKeys = ref({});
const indexMethod = (index) => {
  return (props.page.current - 1) * props.page.size + index + 1;
};
// ç‚¹å‡» link äº‹ä»¶
const goLink = (row, linkMethod) => {
  if (!linkMethod) {
    return ElMessage.warning("请配置 link äº‹ä»¶");
  }
  const parentMethod = getParentMethod(linkMethod);
  if (typeof parentMethod === "function") {
    parentMethod(row);
  } else {
    console.warn(`父组件中未找到方法: ${linkMethod}`);
  }
};
// èŽ·å–çˆ¶ç»„ä»¶æ–¹æ³•ï¼ˆç¤ºä¾‹å®žçŽ°ï¼‰
const getParentMethod = (methodName) => {
  const parentMethods = inject("parentMethods", {});
  return parentMethods[methodName];
};
const dataTypeFn = (val, format) => {
  if (typeof format === "function") {
    return format(val);
  } else return val;
};
const formatType = (val, format) => {
  if (typeof format === "function") {
    return format(val);
  } else return "";
};
// æ–‡ä»¶å˜åŒ–处理
const handleChange = (file, fileList, index) => {
  if (fileList.length > 1) {
    const earliestFile = fileList[0];
    uploadRefs.value[index]?.handleRemove(earliestFile);
  }
  currentFiles.value[index] = file;
};
// æ–‡ä»¶ä¸Šä¼ å‰æ ¡éªŒ
const beforeUpload = (rawFile, index) => {
  currentFiles.value[index] = {};
  if (rawfile.size > 1024 * 1024 * 10 * 10) {
    ElMessage.error("上传文件不超过10M");
    return false;
  }
  return true;
};
// ä¸Šä¼ æˆåŠŸ
const handleSuccessUp = (response, file, fileList, index) => {
  if (response.code == 200) {
    if (uploadRefs[index]) {
      uploadRefs[index].clearFiles();
    }
    currentFiles[index] = file;
    ElMessage.success("上传成功");
    resetUploadComponent(index);
  } else {
    ElMessage.error(response.message);
  }
};
const resetUploadComponent = (index) => {
  uploadKeys[index] = Date.now();
};
// ä¸Šä¼ å¤±è´¥
const onError = (error, file, fileList, index) => {
  ElMessage.error("文件上传失败,请重试");
  if (uploadRefs.value[index]) {
    uploadRefs.value[index].clearFiles();
  }
};
// æ–‡ä»¶æ•°é‡è¶…限提示
const onExceed = () => {
  ElMessage.warning("超出文件个数");
};
const paginationSearch = ({ page, limit }) => {
  emit("pagination", { page: page, limit: limit });
};
const expandChange = (row, expandedRows) => {
  emit("expand-change", row, expandedRows);
};
const handleSelectionChange = (newSelection) => {
  emit("selection-change", newSelection);
};
</script>
<style scoped lang="scss">
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 0 !important;
  padding-left: 0 !important;
}
</style>
src/components/Table/Pagination.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
<template>
  <div :class="{ hidden }" class="pagination-container">
    <el-pagination
      :background="background"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :pager-count="pagerCount"
      :total="total"
      v-bind="$attrs"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>
<script setup>
import { computed } from 'vue'
import { scrollTo } from '@/utils/scroll-to'
const props = defineProps({
  total: {
    type: Number,
    required: true
  },
  page: {
    type: Number,
    default: 1
  },
  limit: {
    type: Number,
    default: 20
  },
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 50, 100]
  },
  pagerCount: {
    type: Number,
    default: () => (document.body.clientWidth < 992 ? 5 : 7)
  },
  layout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  background: {
    type: Boolean,
    default: true
  },
  autoScroll: {
    type: Boolean,
    default: true
  },
  hidden: {
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
const currentPage = computed({
  get: () => props.page,
  set: (val) => emit('update:page', val)
})
const pageSize = computed({
  get: () => props.limit,
  set: (val) => emit('update:limit', val)
})
const handleSizeChange = (val) => {
  if (currentPage.value * val > props.total) {
    currentPage.value = 1
  }
  emit('pagination', { page: currentPage.value, limit: val })
  if (props.autoScroll) {
    scrollTo(0, 800)
  }
}
const handleCurrentChange = (val) => {
  emit('pagination', { page: val, limit: pageSize.value })
  if (props.autoScroll) {
    scrollTo(0, 800)
  }
}
</script>
<style scoped>
.pagination-container {
  background: #fff;
  padding: 16px 0;
  margin-top: 0;
}
.pagination-container.hidden {
  display: none;
}
</style>
src/components/Table/table.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
<template>
  <el-table :data="tableData" :column="columnss" style="width: 100%">
    <el-table-column type="index" width="50">
      <template #default="scope">
        {{ getRowIndex(scope.$index) }}
      </template>
    </el-table-column>
    <el-table-column
      v-for="(item, index) in columnss"
      :key="index"
      :prop="item.prop"
      :label="item.label"
      :align="item.align || 'center'"
      :min-width="item.minWidth || '100px'"
      :width="item.width"
      :fixed="item.fixed || false"
      :show-overflow-tooltip="showOverflowTooltip || true"
    >
    </el-table-column>
  </el-table>
</template>
<script setup>
import { ref, onMounted, watch, nextTick } from "vue";
const props = defineProps({
  tableData: {
    type: Array,
    default: () => [],
  },
  columnss: {
    type: Array,
    default: () => [],
  },
});
const getRowIndex = (index) => {
  return index + 1;
};
</script>
<style scoped></style>
src/hooks/useFormData.js
@@ -4,7 +4,8 @@
 */
import { ref, reactive, computed, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { clone } from "lodash";
import { deepClone } from "@/utils/index.js"
/**
 * åˆ›å»ºè¡¨å•数据管理功能
@@ -324,8 +325,8 @@
}
// å‘后兼容的默认导出
export default function useFormDataSimple(initData) {
  const form = reactive(clone(initData, true));
export default function useFormDatas(initData) {
  const form = reactive(deepClone(initData, true));
  function resetForm() {
    const initData2 = JSON.parse(JSON.stringify(initData));
src/hooks/useModal.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
import { ref } from "vue";
export function useModal(options) {
  const id = ref();
  const visible = ref(false);
  const loading = ref(false);
  const modalOptions = ref({});
  const openModal = (e) => {
    id.value = e;
    modalOptions.value = {
      title: e ? `修改${options.title}` : `新增${options.title}`,
      content: "确定执行此操作吗?",
      confirmText: "确定",
      cancelText: "取消",
    };
    visible.value = true;
  };
  // å…³é—­æ¨¡æ€æ¡†
  const closeModal = () => {
    visible.value = false;
    loading.value = false;
  };
  // ç¡®è®¤æ“ä½œ
  const handleConfirm = async (callback) => {
    loading.value = true;
    callback();
    closeModal();
  };
  return {
    id,
    visible,
    loading,
    modalOptions,
    openModal,
    closeModal,
    handleConfirm,
  };
}
src/hooks/usePaginationApi.jsx
@@ -1,8 +1,8 @@
import { ref, reactive, watchEffect, unref } from "vue";
import useFormData from "./useFormData.js";
// import { message } from "@/utils/message";
import useFormData from "@/hooks/useFormData";
import { deepClone, isEqual } from "@/utils/index.js"
import { ElMessage } from 'element-plus'
import { clone, isEqual } from "lodash";
/**
 * åˆ†é¡µapi
 * @param api æŽ¥å£
@@ -20,7 +20,7 @@
) {
  const dataList = ref([]);
  const { form: filters, resetForm } = useFormData(initalFilters);
  let lastFilters = clone(initalFilters);
  let lastFilters = deepClone(initalFilters);
  const sorter = reactive(sorters || {});
  const others = ref({});
  const loading = ref(true);
@@ -79,14 +79,14 @@
    // å¦‚果这次和上次的filter不同,那么就重置页码
    if (!isEqual(unref(filters), lastFilters)) {
      pagination.currentPage = 1;
      lastFilters = clone(unref(filters));
      lastFilters = deepClone(unref(filters));
    }
    loading.value = true;
    api({
      ...getFinalParams(),
      current: pagination.currentPage,
      size: pagination.pageSize
    }).then(({ code, data, ...rest }) => {
    }).then(({ code, data, msg, ...rest }) => {
      if (code == 200) {
        // pagination.currentPage = meta.current_page;
        // pagination.pageSize = meta.per_page;
@@ -97,7 +97,7 @@
        loading.value = false;
      } else {
        loading.value = false;
        // message(data.msg, { type: "error" });
        ElMessage({ message: msg, type: "error" });
      }
    });
  }
@@ -120,7 +120,7 @@
  }
  watchEffect(() => {
    pagination.align = paginationAlign.value;
    pagination.align = paginationAlign.value
  });
  // onMounted(() => {
src/utils/index.js
@@ -387,4 +387,7 @@
export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}
export function isEqual(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}
src/views/archiveManagement/index.vue
@@ -118,12 +118,12 @@
            </el-input>
          </div>
        </el-col>
        <el-col :offset="10" :span="2">
        <el-col :offset="8" :span="3">
          <el-button :icon="Delete" type="danger" @click="delHandler"
            >删除</el-button
          >
        </el-col>
        <el-col :span="2">
        <el-col :span="3">
          <el-button
            :disabled="!tableSwitch"
            :icon="Plus"
@@ -142,6 +142,7 @@
        :table-data="tableData"
        @edit="handleEdit"
        @selection-change="handleSelectionChange"
        style="height: calc(65vh);"
      >
      </ETable>
      <Pagination
@@ -288,6 +289,7 @@
      treeId: queryParams.treeId,
      current: queryParams.current,
      size: queryParams.pageSize,
      searchAll: queryParams.searchAll,
    });
    if (res.code !== 200) {
@@ -556,7 +558,10 @@
};
// ===== ç”Ÿå‘½å‘¨æœŸ =====
onMounted(getList);
onMounted(()=>{
  getList();
  getArchiveListData();
});
</script>
<style lang="scss" scoped>
.custom-tree-node {
src/views/basicInformation/index.vue
@@ -891,7 +891,9 @@
    width: 16%;
  }
}
.app-container{
  padding: 18px !important;
}
.table-toolbar {
  margin-bottom: 20px;
  display: flex;
src/views/equipment/management/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,336 @@
<template>
  <div class="app-container">
    <el-form :inline="true" :model="queryParams" class="search-form">
      <el-form-item v-if="shouldShowSearch" label="搜索">
        <el-input
          v-model="queryParams.searchAll"
          :placeholder="searchPlaceholder"
          clearable
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="search">查询</el-button>
        <el-button @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-card>
      <!-- æ ‡ç­¾é¡µ -->
      <el-tabs
        v-model="activeTab"
        class="info-tabs"
        @tab-click="handleTabClick"
      >
        <el-tab-pane
          v-for="tab in tabs"
          :key="tab.name"
          :label="tab.label"
          :name="tab.name"
        />
      </el-tabs>
      <!-- æ“ä½œæŒ‰é’®åŒº -->
      <el-row :gutter="24" class="table-toolbar">
        <el-button :icon="Plus" type="primary" @click="handleAdd"
          >新建</el-button
        >
        <el-button :icon="Delete" type="danger" @click="handleDelete"
          >删除</el-button
        >
      </el-row>
      <!-- è¡¨æ ¼ç»„ä»¶ -->
      <div>
        <data-table
          :border="true"
          :columns="columns"
          :loading="loading"
          style="width: 100%; height: calc(100vh - 29em)"
          :show-selection="true"
          :table-data="tableData"
          @edit="handleEdit"
          @viewRow="handleView"
          @selection-change="handleSelectionChange"
          :operations="['edit', 'viewRow']"
          :operationsWidth="200"
        >
          <!-- å­—段名称列的自定义插槽 - æ˜¾ç¤ºä¸ºæ ‡ç­¾ -->
          <template
            v-if="activeTab === 'coalQualityMaintenance'"
            #fieldIds="{ row }"
          >
            <template
              v-if="
                typeof row.fieldIds === 'string' && row.fieldIds.includes(',')
              "
            >
              <el-tag
                v-for="(field, index) in row.fieldIds.split(',')"
                :key="index"
                size="small"
                style="margin-right: 4px; margin-bottom: 2px"
                type="primary"
              >
              </el-tag>
            </template>
            <template v-else>
              <el-tag size="small" type="primary">
              </el-tag>
            </template>
          </template>
        </data-table>
      </div>
      <pagination
        v-if="total > 0"
        :layout="'total, prev, pager, next, jumper'"
        :limit="pageSizes"
        :page="pageNum"
        :total="total"
        @pagination="handPagination"
      />
      <managementDialog
        v-model:copyForm="copyForm"
        v-model:managementFormDialog="manaDialog"
        :addOrEdit="addOrEdit"
        :form="form"
        @submit="getList"
      ></managementDialog>
    </el-card>
  </div>
</template>
<script setup>
import { computed, onMounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { Delete, Plus } from "@element-plus/icons-vue";
// ç»„件导入
import DataTable from "@/components/Table/ETable.vue";
import Pagination from "@/components/Pagination";
import managementDialog from "./mould/managementDialog.vue";
// API æœåС坼入
import { useDelete } from "@/hooks/useDelete.js";
import { getManagementList, delEquipment } from "@/api/equipment/management/index.js";
// å“åº”式状态管理
const form = ref({});
const title = ref("");
const copyForm = ref({});
const addOrEdit = ref("add");
const manaDialog = ref(false);
const loading = ref(false);
const activeTab = ref("management");
const selectedRows = ref([]);
const tableData = ref([]);
// åˆ†é¡µçŠ¶æ€
const pageNum = ref(1);
const pageSizes = ref(10);
const total = ref(0);
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  searchAll: ""
});
// æ ‡ç­¾é¡µé…ç½® - ä¾¿äºŽåŽç»­æ‰©å±•
const tabsConfig = {
  management: {
    label: "设备列表",
    searchPlaceholder: "设备编号/设备名称/规格型号",
    showSearch: true,
    api: getManagementList,
    deleteApi: delEquipment,
    columns: [
      { prop: "equipmentId", label: "设备编号", minWidth: 100 },
      { prop: "equipmentName", label: "设备名称", minWidth: 100 },
      { prop: "quantity", label: "数量", minWidth: 100 },
      { prop: "specification", label: "规格型号", minWidth: 100 },
      {
        prop: "usageStatus",
        label: "使用状态",
        minWidth: 100,
        formatter: (row) => row.usageStatus == 1 ? "启用" : "禁用"
      },
      { prop: "usingDepartment", label: "使用部门", minWidth: 100 },
      { prop: "purchaseDate", label: "采购日期", minWidth: 100 },
      { prop: "purchasePrice", label: "采购价格", minWidth: 100 },
    ]
  }
  // åŽç»­å¯ä»¥åœ¨è¿™é‡Œæ·»åŠ æ–°çš„æ ‡ç­¾é¡µé…ç½®
};
// æ ‡ç­¾é¡µæ•°æ®
const tabs = reactive(
  Object.entries(tabsConfig).map(([name, config]) => ({
    name,
    label: config.label
  }))
);
// å½“前标签页配置
const currentTabConfig = computed(() => tabsConfig[activeTab.value]);
// è®¡ç®—属性
const searchPlaceholder = computed(() => currentTabConfig.value?.searchPlaceholder || "请输入搜索信息");
const shouldShowSearch = computed(() => currentTabConfig.value?.showSearch || false);
const columns = computed(() => currentTabConfig.value?.columns || []);
const selectedCount = computed(() => selectedRows.value.length);
// äº‹ä»¶å¤„理函数
const handleTabClick = (tab) => {
  activeTab.value = tab.props.name;
  resetState();
  getList();
};
const resetState = () => {
  form.value = {};
  addOrEdit.value = "add";
  loading.value = true;
  tableData.value = [];
  pageNum.value = 1;
  pageSizes.value = 10;
  total.value = 0;
  queryParams.searchAll = "";
};
const resetQuery = () => {
  queryParams.searchAll = "";
  pageNum.value = 1;
  getList();
};
const search = () => {
  pageNum.value = 1;
  getList();
};
const handleAdd = () => {
  addOrEdit.value = "add";
  form.value = {};
  title.value = `新增${currentTabConfig.value.label}`;
  manaDialog.value = true;
};
const handleEdit = (row) => {
  form.value = { ...row };
  addOrEdit.value = "edit";
  title.value = `编辑${currentTabConfig.value.label}`;
  copyForm.value = { ...row };
  manaDialog.value = true;
};
const handleView = (row) => {
  form.value = { ...row };
  addOrEdit.value = "viewRow";
  title.value = `查看${currentTabConfig.value.label}`;
  copyForm.value = { ...row };
  manaDialog.value = true;
};
const handPagination = (val) => {
  pageNum.value = val.page;
  pageSizes.value = val.limit;
  getList();
};
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
// åˆ é™¤å¤„理
const { handleDeleteBatch: handleDelete } = useDelete({
  deleteApi: () => currentTabConfig.value.deleteApi,
  selectedRows: selectedRows,
  getList: () => getList(),
  tableData: tableData,
  total: total,
  confirmText: "确认删除选中的数据吗?",
  successText: "删除成功",
});
// æ•°æ®èŽ·å–
const getList = async () => {
  try {
    loading.value = true;
    const apiParams = {
      current: pageNum.value,
      pageSize: pageSizes.value,
      searchAll: queryParams.searchAll,
    };
    const { data, code } = await currentTabConfig.value.api(apiParams);
    if (code !== 200) {
      ElMessage.error("获取数据失败:" + (data?.msg || "未知错误"));
      return;
    }
    tableData.value = data.records || [];
    total.value = data.total || 0;
  } catch (error) {
    ElMessage.error("获取数据失败,请稍后再试");
  } finally {
    loading.value = false;
  }
};
// ç»„件挂载
onMounted(() => {
  handleTabClick({ props: { name: "management" } });
});
</script>
<style scoped>
/* å“åº”式布局 */
@media screen and (min-width: 768px) {
  .search-form :deep(.el-form-item) {
    width: 50%;
  }
}
@media screen and (min-width: 1200px) {
  .search-form :deep(.el-form-item) {
    width: 16%;
  }
}
.table-toolbar {
  margin-bottom: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.app-container{
  padding: 18px !important;
}
/* å“åº”式表格 */
@media screen and (max-width: 768px) {
  .table-toolbar {
    flex-direction: column;
  }
  .table-toolbar .el-button {
    width: 100%;
  }
}
/* è¡¨æ ¼å·¥å…·æ  */
.table-toolbar,
.table-toolbar > * {
  margin: 0 0 0 0 !important;
}
.table-toolbar {
  margin-bottom: 20px !important;
}
.el-form--inline .el-form-item {
  margin-right: 25px;
}
.main-container {
  background: red !important;
}
</style>
src/views/equipment/management/mould/managementDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,241 @@
<template>
  <div>
    <el-dialog
      v-model="dialogVisible"
      :title="addOrEdit === 'edit' ? '编辑' : '新增' + '设备'"
      width="800"
      :title-style="{ textAlign: 'center' }"
      :close-on-click-modal="false"
      :before-close="handleClose"
    >
      <el-form
        ref="formRef"
        :model="formData"
        :rules="rules"
        label-width="auto"
      >
        <el-row :gutter="20">
          <el-col :span="11">
            <el-form-item label="设备编号" prop="equipmentId">
              <el-input
                v-model="formData.equipmentId"
                placeholder="请输入设备编号"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="设备名称" prop="equipmentName">
              <el-input
                v-model="formData.equipmentName"
                placeholder="请输入设备名称"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="数量" prop="quantity">
              <el-input
                v-model="formData.quantity"
                placeholder="请输入数量"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="规格型号" prop="specification">
              <el-input
                v-model="formData.specification"
                placeholder="请输入规格型号"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="使用状态" prop="usageStatus">
              <el-select
                v-model="formData.usageStatus"
                placeholder="请选择使用状态"
                :disabled="isViewMode"
              >
                <el-option label="启用" value="1" />
                <el-option label="禁用" value="0" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="使用部门" prop="usingDepartment">
              <el-input
                v-model="formData.usingDepartment"
                placeholder="请输入使用部门"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="存放位置" prop="storageLocation">
              <el-input
                v-model="formData.storageLocation"
                placeholder="请输入存放位置"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="采购价格" prop="purchasePrice">
              <el-input
                v-model="formData.purchasePrice"
                placeholder="请输入采购价格"
                :disabled="isViewMode"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item label="采购日期" prop="purchaseDate">
              <el-date-picker
                v-model="formData.purchaseDate"
                type="date"
                placeholder="请选择采购日期"
                size="default"
                :value-format="'YYYY-MM-DD'"
                style="width: 100%;"
                :disabled="isViewMode"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item class="dialog-footer">
          <el-button v-if="!isViewMode" @click="cancelForm">取消</el-button>
          <el-button v-if="!isViewMode" type="primary" @click="submitForm">确定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, watch, computed, reactive } from "vue";
import { addOrEditEquipment } from "@/api/equipment/management/index.js";
const props = defineProps({
  beforeClose: {
    type: Function,
    default: () => {},
  },
  form: {
    type: Object,
    default: () => ({}),
  },
  addOrEdit: {
    type: String,
    default: "add",
  },
  title: {
    type: String,
    default: "",
  },
});
const emit = defineEmits(["submit", "handleBeforeClose"]);
// è®¡ç®—属性:统一控制是否禁用
const isViewMode = computed(() => props.addOrEdit === "viewRow");
// è¡¨å•引用和数据
const formRef = ref(null);
const formData = ref({});
const copyForm = defineModel("copyForm", {
  required: true,
  type: Object,
  default: () => ({}),
});
// å¼¹çª—可见性
const dialogVisible = defineModel("managementFormDialog", {
  required: true,
  type: Boolean,
});
// ç›‘听外部传入的表单数据变化,合并监听逻辑
watch(
  [() => props.form, () => props.addOrEdit],
  ([newForm, newAddOrEdit]) => {
    formData.value = { ...newForm };
  },
  { deep: true, immediate: true }
);
// æäº¤è¡¨å•
const submitForm = async () => {
  if (!formRef.value) return;
  await formRef.value.validate(async (valid) => {
    if (!valid) return;
    try {
      const result = await addOrEditEquipment({ ...formData.value });
      const title = props.title.includes("新增") ? "新增" : "编辑";
      if (result.code === 200 && result.msg) {
        ElMessage.success(`${title}成功:${result.msg}`);
        emit("submit", { title, ...formData.value, result });
        closeDialog();
      } else {
        ElMessage.error(`${title}失败:${result.msg}`);
      }
    } catch (error) {
      console.error("提交失败:", error);
      ElMessage.error("提交失败,请重试");
    }
  });
};
// å…³é—­å¼¹çª—的统一方法
const closeDialog = () => {
  emit("update:managementFormDialog", false);
  formData.value = {};
};
// å–消表单
const cancelForm = () => {
  closeDialog();
};
// é‡ç½®è¡¨å•
const resetForm = () => {
  if (!formRef.value) return;
  formData.value = JSON.parse(JSON.stringify(copyForm.value));
};
// å…³é—­å¼¹çª—
const handleClose = () => {
  emit("handleBeforeClose");
  closeDialog();
};
const rules = reactive({
  equipmentId: [
    { required: true, message: "请输入供货商名称", trigger: "blur" },
  ],
});
</script>
<style lang="scss" scoped>
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
  flex-direction: column;
}
// åªä¸ºdialog头部加下划线
:deep(.el-dialog__header) {
  border-bottom: 1px solid #e8eaec;
  padding: 0 20px 10px 0;
  margin-bottom: 14px;
}
</style>
src/views/inspectionManagement/index.vue
@@ -96,47 +96,58 @@
</template>
<script setup>
import {Download, Delete, Plus} from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
const { proxy } = getCurrentInstance()
import { Delete, Plus } from "@element-plus/icons-vue";
import { onMounted, ref, reactive, getCurrentInstance, nextTick } from "vue";
// ç»„件引入
import Pagination from "@/components/Pagination/index.vue";
import ETable from "@/components/Table/ETable.vue";
import FormDia from "@/views/inspectionManagement/components/formDia.vue";
import QrCodeDia from "@/views/inspectionManagement/components/qrCodeDia.vue";
import ViewFiles from "@/views/inspectionManagement/components/viewFiles.vue";
import ViewQrCodeFiles from "@/views/inspectionManagement/components/viewQrCodeFiles.vue";
// æŽ¥å£å¼•å…¥
import {
  delInspectionTask,
  delTimingTask,
  inspectionTaskList,
  timingTaskList
} from "@/api/inspectionManagement/index.js";
import ViewFiles from "@/views/inspectionManagement/components/viewFiles.vue";
import {delQrCode, qrCodeList, qrCodeScanRecordList} from "@/api/inspectionUpload/index.js";
import ViewQrCodeFiles from "@/views/inspectionManagement/components/viewQrCodeFiles.vue";
import {
  delQrCode,
  qrCodeList,
  qrCodeScanRecordList
} from "@/api/inspectionUpload/index.js";
const formDia = ref()
const qrCodeDia = ref()
const viewFiles = ref()
const viewQrCodeFiles = ref()
// å…¨å±€å˜é‡
const { proxy } = getCurrentInstance();
const formDia = ref();
const qrCodeDia = ref();
const viewFiles = ref();
const viewQrCodeFiles = ref();
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  searchAll: "",
})
// å½“前标签
});
// æ ‡ç­¾é¡µé…ç½®
const activeTab = ref("task");
const tabName = ref("task");
// æ ‡ç­¾é¡µæ•°æ®
const tabs = reactive([
  { name: "task", label: "生产巡检" },
  { name: "qrCodeScanRecord", label: "现场巡检记录" },
]);
// å•选框
// å•选框配置
const activeRadio = ref("taskManage");
const radios = reactive([
  { name: "taskManage", label: "定时任务管理" },
  { name: "task", label: "定时任务记录" },
  { name: "qrCode", label: "二维码管理" },
]);
// è¡¨æ ¼
// è¡¨æ ¼æ•°æ®
const selectedRows = ref([]);
const tableData = ref([]);
const operationsArr = ref([]);
@@ -145,27 +156,49 @@
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
// åˆ—配置
const columns = ref([
  { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
  { prop: "inspectionLocation", label: "地点", minWidth: 120 },
  { prop: "remarks", label: "备注", minWidth: 150 },
  { prop: "inspector", label: "执行巡检人", minWidth: 150 },
  { prop: "frequencyType", label: "频次", minWidth: 150,
  {
    prop: "frequencyType",
    label: "频次",
    minWidth: 150,
    formatter: (_, __, val) => ({
      DAILY: "每日",
      WEEKLY: "每周",
      MONTHLY: "每月",
      QUARTERLY: "季度"
    }[val] || "")
  },
  {
    prop: "frequencyDetail",
    label: "开始日期与时间",
    minWidth: 150,
    formatter: (row, column, cellValue) => {
    if (cellValue === 'DAILY') {
      return '每日';
    } else if (cellValue === 'MONTHLY') {
      return '每月';
    } else if (cellValue === 'WEEKLY') {
      return '每周';
    } else {
      return '季度'
      // å…ˆåˆ¤æ–­æ˜¯å¦æ˜¯å­—符串
      if (typeof cellValue !== 'string') return '';
      let val = cellValue;
      const replacements = {
        MON: '周一',
        TUE: '周二',
        WED: '周三',
        THU: '周四',
        FRI: '周五',
        SAT: '周六',
        SUN: '周日'
      };
      // ä½¿ç”¨æ­£åˆ™ä¸€æ¬¡æ€§æ›¿æ¢æ‰€æœ‰åŒ¹é…é¡¹
      return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]);
    }
    }},
  { prop: "frequencyDetail", label: "开始日期与时间", minWidth: 150 },
  },
  { prop: "registrant", label: "登记人", minWidth: 100 },
  { prop: "createTime", label: "登记日期", minWidth: 100 },
]);
const columns1 = ref([
  { prop: "deviceName", label: "设备名称", minWidth: 160 },
  { prop: "location", label: "所在位置描述", minWidth: 120 },
@@ -176,114 +209,120 @@
onMounted(() => {
  radioChange('taskManage');
});
// æ ‡ç­¾é¡µç‚¹å‡»
// æ ‡ç­¾é¡µç‚¹å‡»äº‹ä»¶
const handleTabClick = (tab) => {
  tabName.value = tab.props.name;
  tableData.value = [];
  getList();
};
// å•选变化
const radioChange = (value) => {
  if (value === "taskManage") {
    tableColumns.value = columns.value;
    operationsArr.value = ['edit']
    operationsArr.value = ['edit'];
  } else if (value === "task") {
    tableColumns.value = columns.value;
    operationsArr.value = ['viewFile']
    operationsArr.value = ['viewFile'];
  } else {
    tableColumns.value = columns1.value;
    operationsArr.value = ['edit']
    operationsArr.value = ['edit'];
  }
  pageNum.value = 1;
  pageSize.value = 10;
  getList();
}
// ç‚¹å‡»æŸ¥è¯¢
};
// æŸ¥è¯¢æ“ä½œ
const handleQuery = () => {
  pageNum.value = 1
  pageSize.value = 10
  getList()
}
  pageNum.value = 1;
  pageSize.value = 10;
  getList();
};
// èŽ·å–åˆ—è¡¨æ•°æ®
const getList = () => {
  tableLoading.value = true;
  const params = { ...queryParams, size: pageSize.value, current: pageNum.value };
  let apiCall;
  if (tabName.value === 'task') {
    if (activeRadio.value === "task") {
      inspectionTaskList({...queryParams, size: pageSize.value, current: pageNum.value}).then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        total.value = res.data.total;
      })
    } else if (activeRadio.value === "qrCode") {
      qrCodeList({...queryParams, size: pageSize.value, current: pageNum.value}).then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        total.value = res.data.total;
      })
    } else {
      timingTaskList({...queryParams, size: pageSize.value, current: pageNum.value}).then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        total.value = res.data.total;
      })
    switch (activeRadio.value) {
      case "task":
        apiCall = inspectionTaskList(params);
        break;
      case "qrCode":
        apiCall = qrCodeList(params);
        break;
      default:
        apiCall = timingTaskList(params);
    }
  } else {
    qrCodeScanRecordList({size: pageSize.value, current: pageNum.value}).then(res => {
      tableLoading.value = false;
      tableData.value = res.data.records;
      total.value = res.data.total;
    })
    apiCall = qrCodeScanRecordList(params);
  }
  
  apiCall.then(res => {
    tableData.value = res.data.records || [];
    total.value = res.data.total || 0;
  }).finally(() => {
    tableLoading.value = false;
  });
};
// é‡ç½®æŸ¥è¯¢
const resetQuery = () => {
  Object.keys(queryParams).forEach((key) => {
    if (key !== "pageNum" && key !== "pageSize") {
  for (const key in queryParams) {
    if (!["pageNum", "pageSize"].includes(key)) {
      queryParams[key] = "";
    }
  });
  }
  handleQuery();
};
// æ–°å¢žã€ç¼–辑
// æ–°å¢ž / ç¼–辑
const handleAdd = (row) => {
  console.log(row)
  const type = row === undefined ? 'add' : 'edit'
  const type = row ? 'edit' : 'add';
  nextTick(() => {
    if (tabName.value === 'task') {
      if (activeRadio.value === "taskManage") {
        formDia.value?.openDialog(type, row)
        formDia.value?.openDialog(type, row);
      } else if (activeRadio.value === "qrCode") {
        qrCodeDia.value?.openDialog(type, row)
        qrCodeDia.value?.openDialog(type, row);
      }
    } else {
      viewQrCodeFiles.value?.openDialog(row)
      viewQrCodeFiles.value?.openDialog(row);
    }
  })
  });
};
// æŸ¥çœ‹é™„ä»¶
const viewFile = (row) => {
  nextTick(() => {
    viewFiles.value?.openDialog(row)
  })
}
// åˆ é™¤ä»»åŠ¡
    viewFiles.value?.openDialog(row);
  });
};
// åˆ é™¤æ“ä½œ
const handleDelete = () => {
  if (selectedRows.value.length === 0) {
  if (!selectedRows.value.length) {
    proxy.$modal.msgWarning("请选择要删除的数据");
    return;
  }
  const deleteIds = selectedRows.value.map(item => item.id);
  proxy.$modal.confirm('是否确认删除所选数据项?').then(function() {
    if (activeRadio.value === "taskManage") {
      return delTimingTask(deleteIds)
    } else {
      return delQrCode(deleteIds)
    }
  const api = activeRadio.value === "taskManage" ? delTimingTask : delQrCode;
  proxy.$modal.confirm('是否确认删除所选数据项?').then(() => {
    return api(deleteIds);
  }).then(() => {
    handleQuery()
    proxy.$modal.msgSuccess("删除成功")
  }).catch(() => {})
    proxy.$modal.msgSuccess("删除成功");
    handleQuery();
  }).catch(() => {});
};
// é€‰æ‹©è¡Œ
// å¤šé€‰å˜æ›´
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
src/views/salesOutbound/components/formDia.vue
@@ -7,6 +7,7 @@
          <el-col :span="12">
            <el-form-item label="销售日期" prop="saleDate">
              <el-date-picker
                  :disabled="operationType === 'view'"
                  v-model="form.saleDate"
                  type="date"
                  value-format="YYYY-MM-DD"
@@ -19,7 +20,7 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择客户">
              <el-select v-model="form.customerId" placeholder="请选择客户" :disabled="operationType === 'view'">
                <el-option
                    v-for="item in customerOptions"
                    :key="item.value"
@@ -33,7 +34,7 @@
        <el-row>
          <el-col :span="12">
            <el-form-item label="煤种" prop="coalId">
              <el-select v-model="form.coalId" placeholder="请选择煤种" @change="setInfo">
              <el-select v-model="form.coalId" placeholder="请选择煤种" @change="setInfo" :disabled="operationType === 'view'">
                <el-option
                    v-for="item in coalOptions"
                    :key="item.id"
@@ -45,67 +46,67 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="单位" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入单位" maxlength="30" />
              <el-input v-model="form.unit" placeholder="请输入单位" maxlength="30" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="库存数量" prop="inventoryQuantity">
              <el-input v-model="form.inventoryQuantity" placeholder="请输入销售数量" maxlength="30" type="number" />
              <el-input v-model="form.inventoryQuantity" placeholder="请输入销售数量" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="单价(含税)" prop="priceIncludingTax" @change="mathProfit">
              <el-input v-model="form.priceIncludingTax" placeholder="请输入销售单价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.priceIncludingTax" placeholder="请输入销售单价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="销售数量" prop="saleQuantity" @change="mathProfit">
              <el-input v-model="form.saleQuantity" placeholder="请输入销售数量" maxlength="30" type="number" />
              <el-input v-model="form.saleQuantity" placeholder="请输入销售数量" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="销售单价(含税)" prop="salePrice" @change="mathProfit">
              <el-input v-model="form.salePrice" placeholder="请输入销售单价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.salePrice" placeholder="请输入销售单价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="销售总价(含税)" prop="totalAmount">
              <el-input v-model="form.totalAmount" placeholder="请输入销售总价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.totalAmount" placeholder="请输入销售总价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="运费" prop="freight">
              <el-input v-model="form.freight" placeholder="请输入销售总价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.freight" placeholder="请输入销售总价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="购销煤税率(%)" prop="taxCoal">
              <el-input v-model="form.taxCoal" placeholder="请输入销售总价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.taxCoal" placeholder="请输入销售总价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="运输税率(%)" prop="taxTrans">
              <el-input v-model="form.taxTrans" placeholder="请输入销售总价(含税)" maxlength="30" type="number" />
              <el-input v-model="form.taxTrans" placeholder="请输入销售总价(含税)" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="毛利润" prop="grossProfit">
              <el-input v-model="form.grossProfit" placeholder="毛利润" maxlength="30" type="number" />
              <el-input v-model="form.grossProfit" placeholder="毛利润" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="净利润" prop="netProfit">
              <el-input v-model="form.netProfit" placeholder="净利润" maxlength="30" type="number" />
              <el-input v-model="form.netProfit" placeholder="净利润" maxlength="30" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
@@ -158,6 +159,7 @@
// æ‰“开弹框
const openDialog = async (type, row) => {
  operationType.value = type
  dialogVisitable.value = true
  form.value.saleDate = proxy.getCurrentDate()
  const [supplyRes, coalRes] = await Promise.all([
@@ -175,7 +177,7 @@
  form.value.taxCoal = 13
  form.value.taxTrans = 9
  form.value.freight = 20
  if (type === 'edit') {
  if (type !== 'add') {
    form.value = {...row}
  }
}
src/views/salesOutbound/index.vue
@@ -26,7 +26,7 @@
      </el-tabs>
      <!-- æ“ä½œæŒ‰é’®åŒº -->
      <el-space>
        <el-button type="primary" :icon="Plus" @click="openDia()">新建</el-button>
        <el-button type="primary" :icon="Plus" @click="openDia(undefined, 'add')">新建</el-button>
        <el-button type="danger" :icon="Delete" @click="handleDelete">删除</el-button>
        <!-- <el-button type="info" plain :icon="Download" @click="handleExport">导出</el-button> -->
      </el-space>
@@ -38,8 +38,11 @@
                @selection-change="handleSelectionChange"
                :show-selection="true"
                :border="true"
                :operations="operationsArr"
                style="width: 100%;height: calc(100vh - 30em)"
                @edit="openDia"></ETable>
                @edit="(row) => openDia(row, 'edit')"
                @viewRow="(row) => openDia(row, 'view')"
        ></ETable>
      </div>
      <pagination
          v-if="total>0"
@@ -70,6 +73,7 @@
  { name: "out", label: "销售出库" },
]);
// è¡¨æ ¼æ•°æ®
const operationsArr = ref(['edit', 'viewRow']);
const tableLoading = ref(false);
const tableData = ref([]);
const columns = ref([
@@ -125,9 +129,8 @@
  handleQuery();
};
// æ–°å¢žå‡ºåº“
const openDia = (row) => {
const openDia = (row, type) => {
  console.log(row)
  const type = row === undefined ? 'add' : 'edit'
  nextTick(() => {
    formDia.value?.openDialog(type, row)
  })
src/views/warehouseManagement/index.vue
@@ -52,10 +52,11 @@
          </el-table-column>
          <el-table-column prop="registrant" label="登记人" width="180"/>
          <el-table-column prop="registrationDate" label="登记日期" width="180"/>
          <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <el-table-column fixed="right" label="操作" min-width="100" align="center">
            <template #default="scope">
              <el-button link type="primary" size="small" @click="reviewDia(scope.row)" v-if="activeTab !== 'officialInventory'">审核</el-button>
              <el-button link type="primary" size="small" @click="mergeRows('edit', scope.row)" v-else>编辑</el-button>
              <el-button link type="primary" size="small" @click="mergeRows('edit', scope.row)" v-if="activeTab === 'officialInventory'">编辑</el-button>
              <el-button link type="primary" size="small" @click="mergeRows('view', scope.row)" v-if="activeTab === 'officialInventory'">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -160,14 +161,14 @@
        <el-row>
          <el-col :span="12">
            <el-form-item label="供应商名称" prop="supplierId">
              <el-select v-model="mergeForm.supplierId" placeholder="请选择供应商">
              <el-select v-model="mergeForm.supplierId" placeholder="请选择供应商" :disabled="operationType === 'view'">
                <el-option :label="item.label" v-for="item in supplyList" :key="item.value" :value="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="煤种" prop="coalId">
              <el-select v-model="mergeForm.coalId" placeholder="请选择煤种">
              <el-select v-model="mergeForm.coalId" placeholder="请选择煤种" :disabled="operationType === 'view'">
                <el-option :label="item.label" v-for="item in coalList" :key="item.value" :value="item.value"/>
              </el-select>
            </el-form-item>
@@ -176,43 +177,43 @@
        <el-row>
          <el-col :span="12">
            <el-form-item label="单位" prop="unit">
              <el-input v-model="mergeForm.unit" placeholder="请输入单位" maxlength="30" />
              <el-input v-model="mergeForm.unit" placeholder="请输入单位" maxlength="30" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="库存数量" prop="inventoryQuantity">
              <el-input v-model="mergeForm.inventoryQuantity" placeholder="请输入库存数量" :max="inventoryQuantity" type="number"/>
              <el-input v-model="mergeForm.inventoryQuantity" placeholder="请输入库存数量" :max="inventoryQuantity" type="number" :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="单价(含税)" prop="priceIncludingTax">
              <el-input v-model="mergeForm.priceIncludingTax" placeholder="请输入单价(含税)" maxlength="30" />
              <el-input v-model="mergeForm.priceIncludingTax" placeholder="请输入单价(含税)" maxlength="30" :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="总价(含税)" prop="totalPriceIncludingTax">
              <el-input v-model="mergeForm.totalPriceIncludingTax" placeholder="请输入总价(含税)" maxlength="30" />
              <el-input v-model="mergeForm.totalPriceIncludingTax" placeholder="请输入总价(含税)" maxlength="30" :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="单价(不含税)" prop="priceExcludingTax">
              <el-input v-model="mergeForm.priceExcludingTax" placeholder="请输入单价(不含税)" maxlength="30" />
              <el-input v-model="mergeForm.priceExcludingTax" placeholder="请输入单价(不含税)" maxlength="30" :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="总价(不含税)" prop="totalPriceExcludingTax">
              <el-input v-model="mergeForm.totalPriceExcludingTax" placeholder="请输入总价(不含税)" maxlength="30" />
              <el-input v-model="mergeForm.totalPriceExcludingTax" placeholder="请输入总价(不含税)" maxlength="30" :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="煤质方案" prop="coalPlanId">
              <el-select v-model="mergeForm.coalPlanId" placeholder="请选择" @change="coalPlanByIdList" clearable>
              <el-select v-model="mergeForm.coalPlanId" placeholder="请选择" @change="coalPlanByIdList" clearable :disabled="operationType === 'view'">
                <el-option
                    v-for="dict in qualityPlanOption"
                    :key="dict.id"
@@ -227,7 +228,7 @@
        <el-row>
          <el-col :span="12" v-for="item in filteredList" :key="item.id">
            <el-form-item :label="item.fieldName">
              <el-input v-model="mergeForm[item.fields]" />
              <el-input v-model="mergeForm[item.fields]" :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -464,7 +465,7 @@
  coalPlanListOptions()
  mergeVisible.value = true;
  operationType.value = type;
  if (type === 'edit') {
  if (type !== 'merge') {
    mergeForm.value = {...row}
  } else {
    if (selectedRows.value.length < 2) {