Просмотр исходного кода

在SQL工作台中的查询结果之间切换的时候优先使用缓存,修改入库申请明细页面的字段

chensibo 2 дней назад
Родитель
Сommit
41806076ab

+ 954 - 717
src/views/mes/queryManage/query.vue

@@ -1,349 +1,148 @@
 <template>
-  <div class="app-container">
-    <!-- 搜索工作栏  -->
-    <el-form
-      v-if="queryData.length"
-      ref="queryForm"
-      :model="queryParams"
-      size="small"
-      label-position="left"
-    >
-      <SearchBar :show-span="12" :collapse-span="6" :show-more="false">
-        <template #header>
-          <template>
-            <el-col :span="24">
-              <el-button type="text" style="font-weight: bold">{{
-                title
-              }}</el-button></el-col
-            >
-            <template v-for="(data, idx) in queryList">
-              <el-col :key="idx" :span="9">
-                <el-select
-                  v-model="queryList[idx].key"
-                  style="width: 35%"
-                  size="mini"
-                  filterable
-                  placeholder="请选择"
-                  @change="queryKeyChange($event, idx, 'query')"
-                >
-                  <el-option
-                    v-for="(item, i) in searchData"
-                    :key="i"
-                    :label="item.columnComment"
-                    :value="item.columnName"
-                  />
-                </el-select>
-                <DictSelect
-                  v-if="data.dataType != 'ym_date_query_type'"
-                  v-model="queryList[idx].operate"
-                  style="width: 28%"
-                  size="mini"
-                  placeholder="请选择"
-                  :dict-type="data.dataType ? data.dataType.toUpperCase() : ''"
-                />
-                <el-form-item
-                  style="display: inline-block"
-                  :style="
-                    data.dataType == 'ym_date_query_type'
-                      ? 'width: 63%;'
-                      : 'width: 35%;'
-                  "
-                >
-                  <!-- 文本域 -->
-                  <el-input
-                    v-if="data.htmlType == 'textarea'"
-                    v-model="queryList[idx].value"
-                    type="textarea"
-                    :placeholder="'请输入'"
-                    clearable
-                    size="mini"
-                    @keyup.enter.native="handleQuery"
-                  />
-                  <!-- 日期选择 -->
-                  <el-date-picker
-                    v-else-if="
-                      data.htmlType == 'datetime' ||
-                      data.htmlType == 'datetimerange' ||
-                      data.htmlType == 'daterange'
-                    "
-                    v-model="queryList[idx].value"
-                    value-format="yyyy-MM-dd HH:mm:ss"
-                    type="datetimerange"
-                    :default-time="['00:00:00', '23:59:59']"
-                    placeholder="选择日期"
-                    start-placeholder="开始时间"
-                    end-placeholder="结束时间"
-                  />
-                  <!-- 字典下拉 -->
-                  <DictSelect
-                    v-else-if="data.htmlType == 'select' && data.dictType"
-                    v-model="queryList[idx].value"
-                    placeholder="请选择"
-                    :dict-type="data.dictType.toUpperCase()"
-                  />
-                  <!-- 字典单选 -->
-                  <el-radio-group
-                    v-else-if="data.htmlType == 'radio' && data.dictType"
-                    v-model="queryList[idx].value"
-                  >
-                    <el-radio
-                      v-for="dict in getDictDatas(
-                        DICT_TYPE[data.dictType.toUpperCase()]
-                      )"
-                      :key="dict.value"
-                      :label="parseInt(dict.value)"
-                      >{{ dict.label }}</el-radio
-                    >
-                  </el-radio-group>
-                  <!-- 输入框 -->
-                  <el-input
-                    v-else
-                    v-model="queryList[idx].value"
-                    :placeholder="'请输入'"
-                    clearable
-                    size="mini"
-                  />
-                </el-form-item>
-              </el-col>
-            </template>
-            <el-col :span="6">
-              <el-button
-                type="primary"
-                icon="el-icon-search"
-                size="mini"
-                @click="handleQuery"
-                >搜索</el-button
-              >
-              <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
-                >重置</el-button
-              >
-              <el-popover
-                v-if="true"
-                v-model="visible"
-                placement="bottom"
-                width="500"
-              >
-                <div>
-                  <template v-for="(data, idx) in querySetList">
-                    <el-col :key="idx" :span="24">
-                      <el-select
-                        v-model="querySetList[idx].key"
-                        style="width: 30%"
-                        size="mini"
-                        placeholder="请选择"
-                        filterable
-                        @change="queryKeyChange($event, idx, 'querySet')"
-                      >
-                        <el-option
-                          v-for="(item, i) in searchData"
-                          :key="i"
-                          :label="item.columnComment"
-                          :value="item.columnName"
-                        />
-                      </el-select>
-                      <DictSelect
-                        v-if="data.dataType != 'ym_date_query_type'"
-                        v-model="querySetList[idx].operate"
-                        style="width: 25%"
-                        size="mini"
-                        placeholder="请选择"
-                        :dict-type="
-                          data.dataType ? data.dataType.toUpperCase() : ''
-                        "
-                      />
-                      <el-form-item
-                        style="display: inline-block"
-                        :style="
-                          data.dataType == 'ym_date_query_type'
-                            ? 'width: 55%;'
-                            : 'width: 30%;'
-                        "
-                      >
-                        <!-- 文本域 -->
-                        <el-input
-                          v-if="data.htmlType == 'textarea'"
-                          v-model="querySetList[idx].value"
-                          type="textarea"
-                          :placeholder="'请输入'"
-                          clearable
-                          size="mini"
-                        />
-                        <!-- 日期选择 -->
-                        <el-date-picker
-                          v-else-if="
-                            data.htmlType == 'datetime' ||
-                            data.htmlType == 'datetimerange' ||
-                            data.htmlType == 'daterange'
-                          "
-                          v-model="querySetList[idx].value"
-                          style="width: 100%"
-                          value-format="yyyy-MM-dd HH:mm:ss"
-                          type="datetimerange"
-                          :default-time="['00:00:00', '23:59:59']"
-                          placeholder="选择日期"
-                          start-placeholder="开始时间"
-                          end-placeholder="结束时间"
-                        />
-                        <!-- 字典下拉 -->
-                        <DictSelect
-                          v-else-if="data.htmlType == 'select' && data.dictType"
-                          v-model="querySetList[idx].value"
-                          placeholder="请选择"
-                          :dict-type="data.dictType.toUpperCase()"
-                        />
-                        <!-- 字典单选 -->
-                        <el-radio-group
-                          v-else-if="data.htmlType == 'radio' && data.dictType"
-                          v-model="querySetList[idx].value"
-                        >
-                          <el-radio
-                            v-for="dict in getDictDatas(
-                              DICT_TYPE[data.dictType.toUpperCase()]
-                            )"
-                            :key="dict.value"
-                            :label="parseInt(dict.value)"
-                            >{{ dict.label }}</el-radio
-                          >
-                        </el-radio-group>
-                        <!-- 输入框 -->
-                        <el-input
-                          v-else
-                          v-model="querySetList[idx].value"
-                          :placeholder="'请输入'"
-                          clearable
-                          size="mini"
-                        />
-                      </el-form-item>
-                      <i
-                        v-if="idx != 0"
-                        class="el-icon-remove-outline"
-                        @click="delQueryItem(idx)"
-                      />
-                    </el-col>
-                  </template>
-
-                  <el-col :span="24">
-                    <el-select
-                      v-model="querySettingKey"
-                      style="width: 30%"
-                      filterable
-                      size="mini"
-                      placeholder="请选择"
-                      @change="querySettingKeyChange"
-                    >
-                      <el-option
-                        v-for="(item, i) in searchData"
-                        :key="i"
-                        :label="item.columnComment"
-                        :value="item.columnName"
-                      />
-                    </el-select>
-                  </el-col>
-                </div>
-
-                <div style="text-align: right; margin: 0">
-                  <el-button size="mini" type="text" @click="visible = false"
-                    >取消</el-button
-                  >
-                  <el-button type="primary" size="mini" @click="queryDataSetOk"
-                    >确定</el-button
-                  >
-                </div>
-                <el-button slot="reference" size="mini"
-                  ><i class="el-icon-setting"
-                /></el-button> </el-popover
-            ></el-col>
-          </template>
-        </template>
-        <template #buttons />
-      </SearchBar>
-    </el-form>
-
-    <!-- 操作工具栏  -->
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
+  <!-- 唯一根节点:el-card -->
+  <el-card class="el-content-wrap mb-3px" shadow="never">
+    <!-- 原 content-wrap 的 slot 内容 -->
+    <el-row class="mb-10px">
+      <template v-for="btn in dynamicButtons">
         <el-button
-          type="warning"
-          plain
-          icon="el-icon-download"
-          size="mini"
-          @click="Export"
-          >导出</el-button
-        >
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-download"
-          size="mini"
-          :loading="exportLoading"
-          @click="ExportAll"
-          >导出全部</el-button
-        >
-      </el-col>
-      <el-col :span="1.5">
-        <el-dropdown
-          v-show="dropdownList && dropdownList.length > 0"
-          @command="batchCommand"
+          v-if="!btn.ifHide"
+          :key="btn.id"
+          :type="getButtonType(btn)"
+          size="small"
+          @click="handleDynamicButtonClick(btn)"
         >
-          <el-button type="primary" size="mini">
-            扩展业务功能<i class="el-icon-arrow-down" />
-          </el-button>
-          <el-dropdown-menu>
-            <el-dropdown-item
-              v-for="(item, i) in dropdownList"
-              :key="i"
-              :command="item.value"
-              >{{ item.text }}</el-dropdown-item
-            >
-          </el-dropdown-menu>
-        </el-dropdown>
-      </el-col>
-    </el-row>
+          <i
+            :class="getButtonIcon(btn)"
+            class="mr-5px"
+            style="font-size: 14px"
+          />
+          {{ btn.buttonName }}
+        </el-button>
+      </template>
+
+      <el-button size="small" type="primary" @click="Export">
+        <i class="el-icon-download mr-5px" style="font-size: 14px" />
+        导出当前页
+      </el-button>
 
-    <el-row :gutter="10" class="mb8">
-      <right-toolbar
-        ref="rightToolbar"
-        :show-search.sync="showSearch"
-        :columns="columnsList"
-        @queryTable="getList"
+      <el-button
+        size="small"
+        type="success"
+        :loading="exportLoading"
+        @click="ExportAll"
       >
-        <el-button
-          type="primary"
-          size="small"
-          :loading="saveLoading"
-          @click="saveColumnsList"
-          >保存</el-button
-        >
-      </right-toolbar>
+        <i class="el-icon-download mr-5px" style="font-size: 14px" />
+        导出全部
+      </el-button>
+
+      <el-button size="small" type="warning" @click="AllConditionReset">
+        <i class="el-icon-refresh mr-5px" style="font-size: 14px" />
+        全条件重置
+      </el-button>
+      <!-- <el-button size="small" type="warning" @click="handleRefresh">
+        <i class="el-icon-refresh mr-5px" style="font-size: 14px" />
+        全条件重置
+      </el-button> -->
     </el-row>
+
+    <!-- 表格 -->
     <el-table
       id="table_excel"
-      ref="table"
+      ref="tableRef"
       v-loading="loading"
       :data="list"
-      :stripe="true"
-      :show-overflow-tooltip="true"
-      :summary-method="getSummaries"
-      show-summary
       border
+      show-overflow-tooltip
+      :row-style="rowStyle"
+      @selection-change="handleSelectionChange"
       @header-dragend="handleResize"
     >
-      <el-table-column type="selection" width="50" fixed="left" />
-      <el-table-column type="index" width="50" align="center" />
+      <el-table-column
+        v-if="showMultipleList.length"
+        key="selection-column"
+        type="selection"
+        width="55"
+      />
+      <el-table-column type="index" width="55" align="center" />
+
       <template v-for="(item, i) in queryData">
         <el-table-column
-          v-if="item.ifHide === false"
-          :key="i"
+          v-if="!item.ifHide"
+          :key="item.id"
           :label="item.columnComment"
-          align="center"
           :prop="item.columnComment"
-          :show-overflow-tooltip="true"
-          :width="item.javaField || ''"
-          :sortable="item.ifSort"
+          align="center"
+          :min-width="item.javaField || ''"
+          :sortable="false"
+          show-overflow-tooltip
         >
-          <template #default="{ row }">
+          <template slot="header">
+            <div class="mr-5px flex items-center">
+              <!-- 排序图标 -->
+              <div v-show="item.ifSort" class="mr-5px flex flex-col gap-0">
+                <i
+                  class="el-icon-caret-top"
+                  style="font-size: 15px; cursor: pointer"
+                  :class="{
+                    'is-sort':
+                      currentSortField === item.columnComment &&
+                      currentSortDirection === 'asc',
+                  }"
+                  @click="handleSort(item.columnComment, 'asc')"
+                />
+                <i
+                  ref=""
+                  class="el-icon-caret-bottom -mt-1.2"
+                  style="font-size: 15px; cursor: pointer"
+                  :class="{
+                    'is-sort':
+                      currentSortField === item.columnComment &&
+                      currentSortDirection === 'desc',
+                  }"
+                  @click="handleSort(item.columnComment, 'desc')"
+                />
+              </div>
+
+              <span>{{ item.columnComment }}</span>
+
+              <!-- 列过滤 -->
+              <FilterColumnInQuery
+                v-if="item.listOperationResult && filterAlive"
+                :key="`filter_${item.id}_${filterKey}`"
+                :ref="`filter_${item.id}`"
+                :label="item.columnComment"
+                :prop="item.columnName"
+                :filter-list="queryData"
+                :query-id="$route.query.id"
+                :filter-list-key="item.columnName"
+                order-type="queryManage"
+                :param-list="queryParamList"
+                :active-filters="customFilters"
+                :html-type="item.htmlType"
+                :dict-type="item.dictType"
+                :is-clear="isClear"
+                @select-data="
+                  (data, field, htmlType) =>
+                    filterData(data, field, htmlType, item)
+                "
+              >
+                <template slot="reference">
+                  <div
+                    class="flex items-center justify-center text-gray-600"
+                    :class="{ 'has-filter': hasFilter(item.columnName) }"
+                  >
+                    <svg-icon
+                      icon-class="search"
+                      class="ml-2px"
+                      style="font-size: 14px; cursor: pointer"
+                    />
+                  </div>
+                </template>
+              </FilterColumnInQuery>
+            </div>
+          </template>
+
+          <template slot-scope="{ row }">
             <div
               :class="{ active: item.example }"
               @click="
@@ -351,493 +150,931 @@
               "
             >
               <dict-tag
-                v-if="isDict(item.columnComment)"
+                v-if="
+                  isDict(item.columnComment) &&
+                  ![undefined, null].includes(row[item.columnComment])
+                "
                 :type="isDict(item.columnComment)"
                 :value="row[item.columnComment]"
               />
-              <span v-else-if="isDateTime(item.columnComment)">{{
-                parseData(row[item.columnComment])
-              }}</span>
+              <span
+                v-else-if="
+                  row[item.columnComment] && isDateTime(item.columnComment)
+                "
+              >
+                {{ formatToDateTime(row[item.columnComment]) }}
+              </span>
               <span v-else>{{ row[item.columnComment] }}</span>
             </div>
           </template>
-        </el-table-column></template
-      >
+        </el-table-column>
+      </template>
     </el-table>
 
-    <!-- 分页组件  -->
+    <!-- 分页 -->
     <pagination
       v-show="total > 0"
       :total="total"
       :page.sync="pageNo"
       :limit.sync="pageSize"
+      :page-sizes="[10, 20, 50, 100, 200, 500, 1000, 5000]"
+      layout="total, sizes, prev, pager, next, jumper"
       @pagination="handleSearch"
     />
-  </div>
+
+    <!-- 弹窗 -->
+    <ReportPrint ref="reportPrint" />
+    <ParameterDetail ref="parameterDetailRef" @success="getQueryData" />
+  </el-card>
 </template>
+
 <script>
 import * as QueryManageApi from "@/api/mes/queryManage";
+import { getQueryManageButtonPage } from "@/api/mes/queryManage/button";
+import { saveAs } from "file-saver";
+import * as XLSX from "xlsx";
+import FilterColumnInQuery from "./components/FilterColumnInQuery.vue";
+import DictTag from "@/components/DictTag";
+import ParameterDetail from "./components/ParameterDetail.vue";
+import ReportPrint from "./components/ReportPrint.vue";
+import request from "@/utils/request";
+import { getAccessToken, getTenantId } from "@/utils/auth";
+import axios from "axios";
+// 此组件没有使用缓存,在不同页面之间切换时,会调用接口重新获取数据。
 export default {
-  name: "MocsQueryForm",
+  name: "QueryForm",
   components: {
-    SearchBar: () => import("@/components/SearchBar"),
+    FilterColumnInQuery,
+    ParameterDetail,
+    ReportPrint,
+    DictTag,
   },
   data() {
     return {
-      // 显示搜索条件
-      showSearch: true,
-      // 显隐列参数
-      columnsList: [],
-      // 保存加载层
-      saveLoading: false,
-      exportLoading: false,
-      title: "",
-      visible: false,
-      // 所有的查询/产看条件
-      queryData: [],
-      // 所有的查询条件
-      searchData: [],
-      // 已添加的查询条件
+      title: "", // ContentWrap 的 title
+      message: "", // ContentWrap 的 message
+      baseUrl: "",
       queryList: [],
-      // 设置查询条件弹框中的数据
-      querySetList: [],
-      // 设置查询条件弹框中添加查询条件的值
-      querySettingKey: "",
-      // 遮罩层
-      loading: true,
-      // 总条数
-      total: 0,
-      // 物料及产品列表列表
+      searchData: [],
+      queryData: [],
       list: [],
-      // 查询参数
+      originalList: [],
       pageNo: 1,
       pageSize: 20,
-      sql: "",
-      queryParams: {},
+      total: 0,
+      loading: false,
+      form: {},
+      visible: false,
+      customFilters: {},
+      currentSortField: null,
+      currentSortDirection: null,
+      dynamicButtons: [],
+      queryParamList: [],
+      exportLoading: false,
+      showMultipleList: [],
+      isClear: false,
+      multipleSelection: [],
       headerWidthChange: false,
-      dropdownList: [],
-      dataSourceConfigId: null,
+      filterKey: 0,
+      filterAlive: true,
     };
   },
   watch: {
-    $route: function (to, from) {
-      // 获取显隐列列表
-      this.id = this.$route.query?.id;
-      this.getQueryData();
-      QueryManageApi.queryManageExecutecomplexdropdownlist().then((res) => {
-        this.dropdownList = res;
-      });
+    // 监听路由参数变化,确保标题正确更新
+    "$route.query.name": {
+      handler(newName) {
+        this.title =
+          newName || this.$route.redirectedFrom?.meta?.title || "查询";
+      },
     },
-    visible(nVal) {
-      if (nVal) {
-        this.querySetList = JSON.parse(JSON.stringify([...this.queryList]));
-      }
+    // 监听路由参数变化,确保数据正确加载
+    "$route.query.id": {
+      handler() {
+        this.init();
+      },
     },
+    // filterAlive(v) {
+    //   console.log(
+    //     `[%c父%c] filterAlive 变为 ${v}  ${Date.now()}`,
+    //     "color:blue",
+    //     ""
+    //   );
+    // },
   },
-  created() {
-    // 获取显隐列列表
-    this.id = this.$route.query?.id;
-    this.getQueryData();
-    // 昱懋的,应该用不上
-    /* QueryManageApi.queryManageExecutecomplexdropdownlist().then((res) => {
-      this.dropdownList = res;
-    });*/
+  mounted() {
+    this.init();
+  },
+  activated() {
+    // 每次激活标签页时都调用init(),确保数据正确加载
+    this.init();
   },
   beforeDestroy() {
-    if (this.headerWidthChange) {
-      this.headerWidthChange = false;
-      const widthList = [];
-      const headers = this.$refs.table.$el.querySelectorAll(
-        ".el-table__header-wrapper tr th"
-      );
-      const queryData = this.queryData.filter((item) => {
-        return !item.ifHide;
-      });
-      // console.log(queryData);
-      headers.forEach((header, i) => {
-        const width = header.offsetWidth;
-        if (i !== 0 && headers.length - 1 !== i) {
-          widthList.push({ id: queryData[i - 1].id, javaField: width });
-        }
-      });
-      // console.log(widthList);
-      QueryManageApi.updateWidth(widthList);
-    }
+    this.saveColumnWidth();
+  },
+  created() {
+    this.baseUrl = process.env.VUE_APP_REPORT_API;
   },
   methods: {
-    // 小数点问题处理
-    getHandleNumber(val) {
-      return Math.round(parseFloat(val) * 100000000) / 100000000;
+    /* 生命周期 */
+    async init() {
+      this.title =
+        this.$route.query?.name ||
+        this.$route.redirectedFrom?.meta?.title ||
+        "查询";
+      // 需要提示文字时,再写 this.message = 'xxx'
+      if (this.$route.query.infraQueryId) {
+        await this.getFilterData();
+      } else {
+        this.buildQueryParamFromRoute();
+        await this.getQueryData();
+      }
     },
-    // 数量合计
-    getSummaries(param) {
-      const { columns, data } = param;
-      const sums = [];
-      columns.forEach((column, index) => {
-        if (index === 0) {
-          sums[index] = "总计";
-          return;
-        }
-        const values = this.list.map((item) => Number(item[column.property]));
-        // console.log(column,values);
-        if (this.isNumber(column.property)) {
-          sums[index] = values.reduce((acc, cur) => {
-            const value = Number(cur);
-            if (!isNaN(value)) {
-              return this.getHandleNumber(acc + cur);
-            } else {
-              return acc;
-            }
-          }, 0);
-          sums[index];
+
+    /* 以下所有方法保持与原文件一致,不再赘述 */
+    async getQueryData() {
+      try {
+        this.loading = true;
+        const data = await QueryManageApi.getQueryManageColumnListByMasterId(
+          this.$route.query.id
+        );
+        // 确保queryData是数组
+        this.queryData = Array.isArray(data.data) ? data.data || [] : [];
+        this.searchData = this.queryData.filter(
+          (item) => item.listOperationResult && item.ifHide === false
+        );
+        this.showMultipleList = this.queryData.filter(
+          (item) => item.listOperationCondition === "1"
+        );
+        this.queryList = [];
+        for (let i = 0; i < this.searchData.length; i++) {
+          const { dataType, htmlType, dictType, columnName } =
+            this.searchData[i];
+          this.queryList.push({
+            dataType,
+            htmlType,
+            dictType,
+            key: columnName,
+            operate: dataType === "ym_string_query_type" ? "like" : "",
+          });
         }
-      });
-      return sums;
-    },
-    saveColumnsList(e) {
-      this.saveLoading = true;
-      const list = this.columnsList.map((item) => {
-        const { id, visible } = item;
-        return { id, ifHide: !visible };
-      });
-      QueryManageApi.updateWidth(list)
-        .then(() => {
-          this.$refs.rightToolbar.open = false;
-          this.getQueryData();
-        })
-        .finally(() => {
-          this.saveLoading = false;
-        });
+        await this.getManageButtons(this.$route.query?.id);
+        await this.getList();
+      } finally {
+        this.loading = false;
+      }
     },
-    async getQueryList() {
+
+    async getList() {
+      // console.log("触发了getList方法");
       try {
         this.loading = true;
-        // const res = await SaleOrderApi.getSaleOrderPage(this.queryParams);
-        // this.list = res.data.list;
-        // this.total = res.data.total;
+        const data = await QueryManageApi.loadTableData({
+          pageNo: this.pageNo,
+          pageSize: this.pageSize,
+          paramList: this.queryParamList,
+          id: this.$route.query?.id,
+        });
+        this.list = data?.data?.list || [];
+        this.originalList = JSON.parse(JSON.stringify(data?.data?.list || []));
+        this.total = data?.data?.total || 0;
+      } catch (error) {
+        console.error("getList错误:", error);
       } finally {
         this.loading = false;
       }
     },
-    handleResize() {
-      this.headerWidthChange = true;
+
+    async getManageButtons(masterId) {
+      const data = await getQueryManageButtonPage({ masterId });
+      this.dynamicButtons = data?.data?.list || [];
     },
-    pathChange(path, val, item, row) {
-      // console.log(path);
-      if (path) {
-        console.log(val, item, row);
-        let url = `${path}`;
-        if (item) {
-          url =
-            url +
-            "&columnComment=" +
-            item.columnComment +
-            "&value=" +
-            row[item.columnComment];
+
+    // async handleDynamicButtonClick(btn = {}) {
+    //   const {
+    //     ifJimu,
+    //     interfaceUrl,
+    //     printSoft,
+    //     operateType,
+    //     paramList = [],
+    //   } = btn;
+
+    //   // 确认数据值和类型
+    //   if (ifJimu) {
+    //     this.handlePrintByJimu(btn);
+    //   } else if (this.isFullUrl(interfaceUrl) && printSoft) {
+    //     this.handlePrintByOtherSoft(btn);
+    //   } else if (operateType === 2) {
+    //     this.$refs.parameterDetailRef.open(
+    //       "create",
+    //       btn,
+    //       this.$route.query?.id,
+    //       [],
+    //       this.queryData
+    //     );
+    //   } else if (operateType === 3) {
+    //     if (this.multipleSelection.length === 0) {
+    //       return this.$message.warning("请先选择行数据!");
+    //     }
+    //     if (this.multipleSelection.length > 1) {
+    //       return this.$message.warning("只能选择单条数据修改!");
+    //     }
+    //     this.$refs.parameterDetailRef.open(
+    //       "update",
+    //       btn,
+    //       this.$route.query?.id,
+    //       this.multipleSelection,
+    //       this.queryData
+    //     );
+    //   } else if (operateType === 7) {
+    //     this.$router.push({ path: `${interfaceUrl}` });
+    //   } else {
+    //     this.handleDynamic(btn);
+    //   }
+    // },
+    async handleDynamicButtonClick(btn = {}) {
+      const {
+        ifJimu,
+        interfaceUrl,
+        printSoft,
+        operateType,
+        paramList = [],
+        ifArray,
+      } = btn;
+
+      // 统一校验函数
+      const checkSelection = () => {
+        if (this.multipleSelection.length === 0) {
+          this.$message.warning("请先选择数据!");
+          return false;
+        }
+        // 核心:根据 ifArray 决定是否允许多选
+        if (ifArray !== true && this.multipleSelection.length > 1) {
+          this.$message.warning("只能选择单条数据!");
+          return false;
         }
-        this.$router.push({ path: url });
+        return true;
+      };
+
+      if (ifJimu) {
+        if (!checkSelection()) return;
+        this.handlePrintByJimu(btn);
+      } else if (this.isFullUrl(interfaceUrl) && printSoft) {
+        if (!checkSelection()) return;
+        this.handlePrintByOtherSoft(btn);
+      } else if (operateType === 2) {
+        // 新增不需要选数据
+        this.$refs.parameterDetailRef.open(
+          "create",
+          btn,
+          this.$route.query?.id,
+          [],
+          this.queryData
+        );
+      } else if (operateType === 3) {
+        // 修改
+        if (!checkSelection()) return;
+        this.$refs.parameterDetailRef.open(
+          "update",
+          btn,
+          this.$route.query?.id,
+          this.multipleSelection,
+          this.queryData
+        );
+      } else if (operateType === 7) {
+        this.$router.push({ path: `${interfaceUrl}` });
+      } else {
+        // 自定义按钮
+        if (!checkSelection()) return;
+        this.handleDynamic(btn);
+      }
+    },
+
+    getButtonIcon(btn) {
+      const { buttonName, operateType } = btn;
+      const name = buttonName.toLowerCase();
+
+      // 根据按钮名称关键词分配图标
+      if (
+        name.includes("新增") ||
+        name.includes("添加") ||
+        name.includes("创建")
+      ) {
+        return "el-icon-circle-plus";
+      } else if (name.includes("保存") || name.includes("提交")) {
+        return "el-icon-check";
+      } else if (name.includes("审核") || name.includes("审批")) {
+        return "el-icon-document-checked";
+      }
+
+      // 根据操作类型分配图标
+      switch (operateType) {
+        case 2: // 新增
+          return "el-icon-circle-plus";
+        case 3: // 修改
+          return "el-icon-edit";
+        case 4: // 删除
+          return "el-icon-delete";
+        case 5: // 导出
+          return "el-icon-download";
+        case 6: // 打印
+          return "el-icon-printer";
+        case 7: // 跳转
+          return "el-icon-right";
+        default:
+          return "el-icon-star-off"; // 默认图标
       }
     },
-    // 批量操作
-    async batchCommand(url) {
-      const list = this.$refs.table.selection;
-      if (list.length === 0) {
-        return this.$message.warning(`请选择需要批量操作的订单!`);
+
+    getButtonType(btn) {
+      const { operateType } = btn;
+
+      // 根据操作类型分配
+      switch (operateType) {
+        case 2: // 新增
+          return "success";
+        case 3: // 修改
+          return "warning";
+        case 4: // 删除
+          return "danger";
+        case 5: // 导出
+          return "primary";
+        case 6: // 打印
+          return "info";
+        case 7: // 跳转
+          return "success";
+        default:
+          return "primary";
       }
+    },
+
+    formatToDateTime(val) {
+      const d = val ? new Date(val) : new Date();
+      if (isNaN(d.getTime())) return "";
+      const pad = (n) => String(n).padStart(2, "0");
+      return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(
+        d.getDate()
+      )} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
+    },
+
+    handlePrintByJimu(params) {
+      // if (this.multipleSelection.length === 0) {
+      //   return this.$message.warning("请先选择数据!");
+      // }
+      // if (this.multipleSelection.length > 1) {
+      //   return this.$message.warning("只能选择单条数据打印!");
+      // }
+      // 确认数据值和类型
+
+      // 验证interfaceUrl
+      const interfaceUrl = String(params.interfaceUrl || "").trim();
+      if (!interfaceUrl || interfaceUrl === "0") {
+        return this.$message.error("接口地址未配置或格式错误!");
+      }
+
+      const token = getAccessToken();
+      const tenantId = getTenantId();
+      const { paramList = [], reportId } = params;
+      const fieldValues = this.paramsToConver(paramList);
+      const printParams = new URLSearchParams({
+        token,
+        tenantId,
+        ...fieldValues,
+      });
+      const src = `${
+        this.baseUrl
+      }${interfaceUrl}${reportId}?${printParams.toString()}`;
+      this.$refs.reportPrint.open(
+        src,
+        this.$route.query?.name ||
+          this.$route.redirectedFrom?.meta?.title ||
+          "报表打印"
+      );
+    },
+
+    async handlePrintByOtherSoft(params) {
+      // if (this.multipleSelection.length === 0) {
+      //   return this.$message.warning("请先选择数据!");
+      // }
+
+      // 确认数据值和类型
+
+      const { interfaceUrl, paramList, restMethod, templet } = params;
+      if (!templet) return this.$message.warning("未配置打印模板!");
+
+      // 确保 url 是合法字符串,而不是数字 0 或其他无效值
+      const url = String(interfaceUrl || "").trim();
+      if (!url || url === "0") {
+        this.$message.error("接口地址未配置或格式错误!");
+        return; // 确保return掉
+      }
+
+      const fieldValues = this.paramsToConver(paramList);
+      const printParams = { ...fieldValues, fileUrl: templet };
+      const config = {
+        method: restMethod,
+        url,
+        [restMethod === "get" || restMethod === "delete" ? "params" : "data"]:
+          printParams,
+      };
+      await axios(config);
+      this.$message.success("操作成功!");
+      this.getList();
+    },
+
+    async handleDynamic(params) {
+      // if (this.multipleSelection.length === 0) {
+      //   return this.$message.warning("请先选择数据!");
+      // }
+
+      // 确认数据值和类型
+
+      const {
+        interfaceUrl,
+        restMethod = "get",
+        paramList = [],
+        requestParameter = "0",
+      } = params;
+
+      // 确保 url 是合法字符串,而不是数字 0 或其他无效值
+      const url = String(interfaceUrl || "").trim();
+      if (!url || url === "0") {
+        this.$message.error("接口地址未配置或格式错误!");
+        return; // 确保return掉
+      }
+
+      const fieldValues = this.paramsToConver(paramList);
+      const config = { method: restMethod, url };
+      this.handleGetDelete(config, fieldValues, String(requestParameter));
+
+      // 直接使用request(config)而不是request[restMethod]?.(config),确保method被正确处理
+      await request(config);
+
+      this.$message.success("操作成功");
+      this.getList();
+    },
+
+    handleGetDelete(config, fieldValues, requestParameter) {
+      switch (requestParameter) {
+        case "1":
+          config.params = fieldValues;
+          break;
+        case "3":
+          const queryString = new URLSearchParams(fieldValues).toString();
+          config.url = queryString
+            ? `${config.url}?${queryString}`
+            : config.url;
+          break;
+        case "4":
+          config.headers = { ...config.headers, ...fieldValues };
+          break;
+        default:
+          config.data = fieldValues;
+      }
+    },
+
+    paramsToConver(paramList) {
+      const matchListWithParam = paramList
+        ?.filter((item) =>
+          this.queryData.some((query) => item.columnId === query?.id)
+        )
+        .map((item) => {
+          const paramItem = this.queryData.find(
+            (query) => item.columnId === query?.id
+          );
+          return { ...item, columnComment: paramItem?.columnComment };
+        });
+      const result = this.generateMappedData(
+        this.multipleSelection,
+        matchListWithParam
+      );
+      const allFields = [...new Set(result.flatMap(Object.keys))];
+      return allFields.reduce((acc, field) => {
+        acc[field] = result.map((item) => item[field]).join(",");
+        return acc;
+      }, {});
+    },
+
+    generateMappedData(selectList, keys) {
+      return selectList.map((item) =>
+        keys.reduce((res, key) => {
+          const { columnComment, paramName } = key;
+          if (item.hasOwnProperty(columnComment)) {
+            const field = paramName.split(".").pop();
+            res[field] = item[columnComment];
+          }
+          return res;
+        }, {})
+      );
+    },
+
+    isFullUrl(url) {
       try {
-        await this.$modal.confirm(`您正在进行批量操作,请确认是否继续?`);
-        const baseUrl = url.replace("/admin-api", ""); // 去掉 /admin-api
-        await QueryManageApi.batchApi(baseUrl, list);
-        this.$message.success(`批量操作成功`);
+        const parsed = new URL(url);
+        return parsed.protocol === "http:" || parsed.protocol === "https:";
       } catch {
-      } finally {
-        this.handleQuery();
+        return false;
       }
     },
-    Export() {
-      this.$confirm("确定要导出文件到Excel?", "导出提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "info",
-      }).then(() => {
-        setTimeout(() => {
-          var xlsxParam = { raw: true }; // 导出的内容只做解析,不进行格式转换
-          const tables = document.getElementById("table_excel"); // 这里是绑定元素,输入你要导出的table表格的id
-          const table_book = this.$XLSX.utils.table_to_book(tables, xlsxParam);
-          const table_write = this.$XLSX.write(table_book, {
-            bookType: "xlsx",
-            bookSST: true,
-            type: "array",
+
+    isDict(key) {
+      if (!Array.isArray(this.queryData)) return false;
+      const item = this.queryData.find((item) => item.columnComment === key);
+      return item ? item.dictType : false;
+    },
+
+    isNumber(key) {
+      if (!Array.isArray(this.queryData)) return false;
+      const item = this.queryData.find((item) => item.columnComment === key);
+      return item && item.dataType === "ym_int_query_type";
+    },
+
+    // isDateTime(key) {
+    //   if (!Array.isArray(this.queryData)) return false;
+    //   const item = this.queryData.find((item) => item.columnComment === key);
+    //   return item && item.javaType === "LocalDateTime";
+    // },
+    isDateTime(key) {
+      if (!Array.isArray(this.queryData)) return false;
+      const item = this.queryData.find((item) => item.columnComment === key);
+      if (!item) return false;
+
+      // 扩展更多时间类型
+      const timeTypes = [
+        "LocalDateTime",
+        "LocalDate",
+        "LocalTime",
+        "Date",
+        "Timestamp",
+        "DateTime",
+        "java.util.Date",
+        "java.sql.Date",
+        "java.sql.Timestamp",
+      ];
+
+      return timeTypes.includes(item.javaType);
+    },
+
+    hasFilter(field) {
+      return !!(this.customFilters[field] && this.customFilters[field].length);
+    },
+
+    handleSort(field, direction) {
+      if (
+        this.currentSortField === field &&
+        this.currentSortDirection === direction
+      ) {
+        this.currentSortField = "";
+        this.currentSortDirection = "";
+        this.list = JSON.parse(JSON.stringify(this.originalList));
+        return;
+      }
+      this.currentSortField = field;
+      this.currentSortDirection = direction;
+      this.list = [...this.originalList].sort((a, b) => {
+        let valA = a[field];
+        let valB = b[field];
+        valA =
+          typeof valA === "string" ? parseFloat(valA.replace(/,/g, "")) : valA;
+        valB =
+          typeof valB === "string" ? parseFloat(valB.replace(/,/g, "")) : valB;
+        if (isNaN(valA)) {
+          return direction === "asc"
+            ? valA > valB
+              ? 1
+              : -1
+            : valA < valB
+            ? 1
+            : -1;
+        }
+        if (isNaN(valB)) {
+          return direction === "asc"
+            ? valA > valB
+              ? 1
+              : -1
+            : valA < valB
+            ? 1
+            : -1;
+        }
+        return direction === "asc" ? valA - valB : valB - valA;
+      });
+    },
+
+    filterData(data, field, type, row) {
+      const { dataType } = row;
+      this.$set(this.customFilters, field, data);
+      const isDateRange = data[0]?.isRange;
+      if (isDateRange) {
+        const valueList = data.flatMap((item) => item.column).join(",");
+        const idx = this.queryParamList.findIndex((item) => item.key === field);
+        if (idx > -1) {
+          this.queryParamList[idx].value = valueList;
+        } else {
+          this.queryParamList.push({
+            key: field,
+            operate: "like",
+            htmlType: type,
+            value: valueList,
           });
-          try {
-            this.$FileSaver.saveAs(
-              new Blob([table_write], { type: "application/octet-stream" }),
-              `${this.title}.xlsx` // 这里是文件名
-            );
-          } catch (e) {
-            if (typeof console !== "undefined") {
-              // console.log(e, table_write);
-            }
-          }
-          return table_write;
-        }, 1000);
+        }
+        this.getList();
+        return;
+      }
+      let valueStr;
+      if (data.length) {
+        valueStr =
+          dataType === "ym_int_query_type"
+            ? data.map((item) => item.column).join(",")
+            : data.map((item) => `'${item.column}'`).join(",");
+        const idx = this.queryParamList.findIndex((item) => item.key === field);
+        if (idx > -1) {
+          this.queryParamList[idx].value = valueStr;
+        } else {
+          this.queryParamList.push({
+            key: field,
+            operate: "like",
+            htmlType: type,
+            value: valueStr,
+          });
+        }
+      } else {
+        const idx = this.queryParamList.findIndex((item) => item.key === field);
+        if (idx > -1) this.queryParamList.splice(idx, 1);
+      }
+      this.getList();
+    },
+
+    AllConditionReset() {
+      /* 0. 先让表格进入“空壳”状态 */
+      this.filterAlive = false;
+      const tmp = this.queryData; // 暂存
+      this.queryData = []; // 强制清空
+
+      // 清空过滤和排序条件
+      this.queryParamList = [];
+      this.customFilters = {};
+      this.currentSortField = null;
+      this.currentSortDirection = null;
+      this.pageNo = 1;
+      this.pageSize = 20;
+      this.multipleSelection = [];
+      this.isClear = true;
+
+      this.$nextTick(() => {
+        /* 1. 再一次性把列塞回去,配合新的 filterKey */
+        this.filterKey++;
+        this.queryData = tmp;
+        /* 2. 重新激活 filter 组件 */
+        this.filterAlive = true; // ← 关键:重新激活
+
+        /* 3. 等待组件重新渲染后获取数据 */
+        this.$nextTick(() => {
+          this.getList();
+          // 重置 isClear 状态
+          setTimeout(() => (this.isClear = false), 1000);
+        });
       });
     },
-    async ExportAll() {
-      await this.$modal.confirm("是否确认导出所有查询数据项?");
+    handleSearch() {
+      this.list = [];
+      this.getList();
+    },
+
+    async Export() {
       try {
-        const list = [];
-        const paramList = this.queryList.forEach((item) => {
-          let { key, operate, value } = item;
-          value = (value || "").toString();
-          if (item.dataType === "ym_date_query_type") {
-            operate = "between";
-          }
-          list.push({ key, operate, value });
+        await this.$confirm("确定导出当前页?", "提示", { type: "warning" });
+
+        // 当前页条数
+        const realSize = this.list.length;
+        if (!realSize) {
+          this.$message.warning("当前无数据可导出");
+          return;
+        }
+
+        // 用后端导出接口,只把当前页码 & 条数发过去
+        const data = await QueryManageApi.exportExcel({
+          id: this.$route.query?.id,
+          paramList: this.queryParamList,
+          pageNo: this.pageNo, // 当前页码
+          pageSize: realSize, // 当前页实际条数
         });
-        // return
+
+        // 同一套下载逻辑
+        this.$download.excel(data, `${this.title}_第${this.pageNo}页.xls`);
+      } catch (error) {
+        if (error !== "cancel") {
+          console.error("导出失败:", error);
+          this.$message.error("导出失败");
+        }
+      }
+    },
+
+    async ExportAll() {
+      try {
+        await this.$confirm("确定导出全部?", "提示", { type: "warning" });
         this.exportLoading = true;
-        const res = await QueryManageApi.exportExcel({
-          id: this.id,
-          paramList: list,
+        const data = await QueryManageApi.exportExcel({
+          id: this.$route.query?.id,
+          paramList: this.queryParamList,
         });
-        this.$download.excel(res, this.title);
-      } catch {
+        this.$download.excel(data, this.title + ".xls");
+      } catch (error) {
+        // 忽略取消操作的错误
+        if (error !== "cancel") {
+          console.error("导出失败:", error);
+          this.$message.error("导出失败");
+        }
       } finally {
         this.exportLoading = false;
       }
     },
-    // 确定修改查询条件
-    queryDataSetOk() {
-      this.queryList = JSON.parse(JSON.stringify([...this.querySetList]));
-      this.visible = false;
+
+    getHandleNumber(val) {
+      return Math.round(parseFloat(val) * 100000000) / 100000000;
     },
-    // 查询条件下拉修改
-    queryKeyChange(e, i, type) {
-      const { dataType, htmlType, dictType } = this.searchData.find(
-        (item) => item.columnName === e
-      );
-      if (type === "query") {
-        this.queryList[i].dataType = dataType;
-        this.queryList[i].htmlType = htmlType;
-        this.queryList[i].dictType = dictType;
-        this.queryList[i].operate =
-          dataType == "ym_string_query_type" ? "like" : "";
-      }
-      if (type === "querySet") {
-        this.querySetList[i].dataType = dataType;
-        this.querySetList[i].htmlType = htmlType;
-        this.querySetList[i].dictType = dictType;
-        this.querySetList[i].operate =
-          dataType == "ym_string_query_type" ? "like" : "";
-      }
-      // console.log(dataType, htmlType, dictType);
-    },
-    // 判断table中的数据是否为字典数据
-    isDict: function (key) {
-      let isDict = false;
-      this.queryData.some((item) => {
-        if (item.columnComment == key) {
-          if (item.dictType) {
-            isDict = item.dictType;
-          }
-          return true;
-        }
-        return false;
-      });
-      return isDict;
-    },
-    // 判断table中的数据字段类型是否为数值 ym_int_query_type
-    isNumber: function (key) {
-      let isNum = false;
-      this.queryData.some((item) => {
-        if (item.columnComment == key) {
-          if (item.dataType === "ym_int_query_type") {
-            isNum = true;
-          }
-          return true;
+
+    getSummaries({ columns }) {
+      const sums = [];
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "总计";
+          return;
         }
-        return false;
-      });
-      return isNum;
-    },
-    // 判断table中的数据是否为时间
-    isDateTime: function (key) {
-      let isDateTime = false;
-      this.queryData.some((item) => {
-        if (item.columnComment == key) {
-          if (item.javaType === "LocalDateTime") {
-            isDateTime = true;
-          }
-          return true;
+        const values = this.list.map((item) => Number(item[column.property]));
+        if (this.isNumber(column.property)) {
+          sums[index] = values.reduce((acc, cur) => {
+            const value = Number(cur);
+            return !isNaN(value) ? this.getHandleNumber(acc + cur) : acc;
+          }, 0);
         }
-        return false;
       });
-      return isDateTime;
+      return sums;
     },
-    parseData(val) {
-      if (!val) {
-        return "";
-      }
-      var date = new Date(val); // 时间戳转换成Date对象
-      return date.toISOString().slice(0, 10); // 格式化为YYYY-MM-DD
+
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
     },
-    // 设置查询条件 删除
-    delQueryItem(i) {
-      this.querySetList.splice(i, 1);
+
+    pathChange(path, val, item, row) {
+      if (path === "sameRouter") return;
+      if (!path) return;
+      const data = {};
+      this.dynamicButtons
+        .filter((v) => v.ifHide && v.paramList.length)
+        .forEach((v) =>
+          v.paramList.forEach((val) => {
+            data[val.paramName] = val.value || row[val.paramComment];
+          })
+        );
+      this.$router.push({ path: `${path}`, query: { id: val, ...data } });
     },
-    // 设置查询条件修改查询条件下拉 添加
-    querySettingKeyChange(e) {
-      if (this.querySetList.length === this.searchData.length) {
-        return;
-      }
-      const { dataType, htmlType, dictType } = this.searchData.find(
-        (item) => item.columnName === e
-      );
-      this.querySettingKey = "";
-      this.querySetList.push({
-        dataType,
-        htmlType,
-        dictType,
-        key: e,
-      });
+
+    handleBack() {
+      this.$router.push({ path: "/querymanage/queryManageIndex" });
     },
-    /** 获取查询列表 */
-    async getQueryData() {
-      this.loading = true;
-      // 执行查询
-      const res = await QueryManageApi.getQueryManageColumnListByMasterId(
-        this.id
+
+    handleResize() {
+      this.headerWidthChange = true;
+    },
+
+    async saveColumnWidth() {
+      if (!this.headerWidthChange) return;
+      this.headerWidthChange = false;
+
+      const widthList = [];
+      // 1. 所有“逻辑上应该显示”的列
+      const visibleMap = new Map(
+        this.queryData.filter((c) => !c.ifHide).map((c) => [c.columnComment, c]) // 用列名当 key
       );
-      // console.log(res.data,'==========');
-      this.queryData = res.data;
-      this.columnsList = res.data.map((item, i) => {
-        const { columnComment, id, ifHide } = item;
-        return { key: i, label: columnComment, id, visible: !ifHide };
-      });
-      this.searchData = res.data.filter((item) => {
-        return item.listOperationResult && item.ifHide === false;
+
+      // 2. 真正渲染出来的 th
+      const thList = Array.from(
+        this.$refs.tableRef.$el.querySelectorAll(
+          ".el-table__header-wrapper tr th"
+        )
+      ).filter(
+        (th) =>
+          !th.classList.contains("el-table-column--selection") &&
+          !th.classList.contains("el-table-column--index")
+      );
+
+      thList.forEach((th) => {
+        const w = th.offsetWidth;
+        if (!w) return; // 虚拟滚动或隐藏时直接跳过
+        const comment = th.innerText.trim();
+        const col = visibleMap.get(comment);
+        if (col) widthList.push({ id: col.id, javaField: w });
       });
-      // console.log(this.searchData);
-      this.queryList = [];
-      for (let i = 0; i < 2; i++) {
-        if (!this.searchData[i]) {
-          break;
-        }
-        const { dataType, htmlType, dictType, columnName } = this.searchData[i];
-        this.queryList.push({
-          dataType,
-          htmlType,
-          dictType,
-          key: columnName,
-          operate: dataType == "ym_string_query_type" ? "like" : "",
-        });
+
+      if (widthList.length) {
+        await QueryManageApi.updateWidth(widthList);
       }
+    },
 
-      if (this.$route.query?.columnComment) {
-        let key = "";
-        this.searchData.filter((v) => {
-          if (v.columnComment === this.$route.query?.columnComment) {
-            key = v.columnName;
-          }
-        });
-        if (key) {
-          this.queryList.push({
-            key: key,
-            operate: "=",
-            value: this.$route.query?.value,
+    buildQueryParamFromRoute() {
+      const queryParam = [];
+      for (const i in this.$route.query) {
+        if (i !== "id" && i !== "name") {
+          queryParam.push({
+            key: i,
+            operate: "like",
+            htmlType: "input",
+            value: "'" + this.$route.query[i] + "'",
           });
         }
       }
-      const res1 = await QueryManageApi.getQueryManage(this.id);
-      this.title = res1.data.name;
-      this.sql = res1.data.sqlStatement;
-      this.dataSourceConfigId = res1.data?.dataSourceConfigId;
-      this.getList();
-      this.loading = false;
-    },
-    getList() {
-      this.loading = true;
-      const paramList = this.queryList.map((item) => {
-        let { key, operate, value } = item;
-        value = (value || "").toString();
-        if (item.dataType === "ym_date_query_type") {
-          operate = "between";
-        }
-        return { key, operate, value };
-      });
-      QueryManageApi.loadTableData({
-        // sql: this.sql,
-        id: this.id,
-        pageNo: this.pageNo,
-        pageSize: this.pageSize,
-        paramList,
-        dataSourceConfigId: this.dataSourceConfigId,
-      })
-        .then((res) => {
-          this.list = res.data.list;
-          this.total = res.data.total;
-        })
-        .finally(() => {
-          this.loading = false;
-        });
+      this.queryParamList = queryParam;
     },
-    handleSearch() {
-      this.list = [];
-      this.getList();
+
+    async getFilterData() {
+      const data = await getQueryManageButtonPage({
+        masterId: this.$route.query?.infraQueryId,
+      });
+      const arr = [];
+      data.list
+        .filter((v) => v.ifHide && v.paramList.length)
+        .forEach((v) =>
+          v.paramList.forEach((val) => {
+            if (val.filter) arr.push(val.paramName);
+          })
+        );
+      const queryParam = [];
+      for (const i in this.$route.query) {
+        if (arr.indexOf(i) > -1) {
+          queryParam.push({
+            key: i,
+            operate: "like",
+            htmlType: "input",
+            value: "'" + this.$route.query[i] + "'",
+          });
+        }
+      }
+      this.queryParamList = queryParam;
+      await this.getQueryData();
     },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.pageNo = 1;
-      this.getList();
+    handleRefresh() {
+      // 初始化所有条件
+      location.reload(true);
+
+      // 初始化所有条件
+      // this.queryParamList = [];
+      // this.customFilters = {};
+      // this.currentSortField = null;
+      // this.currentSortDirection = null;
+      // this.pageNo = 1;
+      // this.pageSize = 20;
+      // this.multipleSelection = [];
+      // this.isClear = true;
+
+      // // 重新拉取按钮、列配置和表格数据
+      // this.init();
+
+      // // 重置isClear状态
+      // setTimeout(() => (this.isClear = false), 1000);
     },
-    /** 重置按钮操作  */
-    resetQuery() {
-      this.queryList.forEach((item, i) => {
-        // this.queryList[i].value = null;
-        this.$set(this.queryList[i], "value", null);
-      });
-      this.handleQuery();
+    rowStyle({ row }) {
+      // 有值才上色,没有就保持默认
+      return row.colorControl ? { backgroundColor: row.colorControl } : {};
     },
   },
 };
 </script>
-<style lang="scss" scoped>
-.mb8 {
-  margin-bottom: 0;
-}
 
-.app-container {
-  margin: 8px;
-  padding: 0;
-  // height: calc(100vh - 100px);
-  padding-bottom: 20px;
+<style scoped lang="scss">
+/* ---------- ContentWrap 原样式 ---------- */
+.el-content-wrap {
+  /* 自定义 */
+  overflow-y: auto;
 }
-
-::v-deep .el-form-item {
-  margin-bottom: 0px !important;
+.text-16px {
+  font-size: 16px;
 }
-
-::v-deep .el-tabs__item {
-  height: 30px !important;
-  line-height: 30px !important;
-  padding: 0 15px !important;
+.font-700 {
+  font-weight: 700;
 }
-
-::v-deep .el-tabs--border-card > .el-tabs__content {
-  padding: 2px !important;
+.ml-5px {
+  margin-left: 5px;
 }
-
-::v-deep .pagination-container {
-  margin: 0;
-  padding: 0;
+.max-w-200px {
+  max-width: 200px;
 }
-
-.active {
-  color: #1890ff !important;
+.mb-3px {
+  margin-bottom: 3px;
 }
 
+/* ---------- 原来的表格样式 ---------- */
+:deep(.el-table__row) {
+  height: 10px !important;
+}
+.el-table--medium .el-table__cell,
+.el-table--small .el-table__cell {
+  padding: 1px 0 !important;
+}
 .active:hover {
   cursor: pointer;
 }
+.has-filter,
+.is-sort,
+.active {
+  color: #1890ff !important;
+}
 </style>

+ 102 - 25
src/views/mes/queryManage/queryNew.vue

@@ -200,7 +200,7 @@ import ReportPrint from "./components/ReportPrint.vue";
 import request from "@/utils/request";
 import { getAccessToken, getTenantId } from "@/utils/auth";
 import axios from "axios";
-
+// 此组件使用了缓存,在/querymanage/queryFormNew页面之间切换时,先在缓存中搜索,如果命中了先使用缓存数据,没有命中则调用接口。
 export default {
   name: "QueryForm",
   components: {
@@ -237,6 +237,8 @@ export default {
       headerWidthChange: false,
       filterKey: 0,
       filterAlive: true,
+      pageCache: {}, // { [id]: 快照 }
+      curPageId: null, // 当前正在展示的页面 id
     };
   },
   watch: {
@@ -250,7 +252,7 @@ export default {
     // 监听路由参数变化,确保数据正确加载
     "$route.query.id": {
       handler() {
-        this.init();
+        this.loadIfNeed();
       },
     },
     // filterAlive(v) {
@@ -261,20 +263,84 @@ export default {
     //   );
     // },
   },
-  mounted() {
-    this.init();
-  },
   activated() {
-    // 每次激活标签页时都调用init(),确保数据正确加载
-    this.init();
+    this.loadIfNeed();
   },
   beforeDestroy() {
     this.saveColumnWidth();
   },
+  beforeCreate() {
+    const max = 10;
+    this.$watch(
+      "pageCache",
+      function (val) {
+        const keys = Object.keys(val);
+        if (keys.length > max) delete val[keys[0]]; // LRU
+      },
+      { deep: true }
+    );
+  },
   created() {
     this.baseUrl = process.env.VUE_APP_REPORT_API;
+    this.loadIfNeed();
   },
   methods: {
+    // 新增:一次性拿齐头部与表格数据
+    async loadPageData(id, params = {}) {
+      const [col, btn, table] = await Promise.all([
+        QueryManageApi.getQueryManageColumnListByMasterId(id),
+        getQueryManageButtonPage({ masterId: id }),
+        QueryManageApi.loadTableData({
+          pageNo: params.pageNo || 1,
+          pageSize: params.pageSize || 20,
+          paramList: params.paramList || [],
+          id,
+        }),
+      ]);
+      const list = table?.data?.list || [];
+      return {
+        queryData: Array.isArray(col.data) ? col.data : [],
+        dynamicButtons: btn?.data?.list || [],
+        list,
+        total: table?.data?.total || 0,
+        originalList: JSON.parse(JSON.stringify(list)),
+        // 用户现场
+        queryParamList: params.paramList || [],
+        customFilters: params.customFilters || {},
+        pageNo: params.pageNo || 1,
+        pageSize: params.pageSize || 20,
+        currentSortField: params.currentSortField || "",
+        currentSortDirection: params.currentSortDirection || "",
+      };
+    },
+    // 统一入口:有缓存直接恢复,没有才调接口
+    loadIfNeed() {
+      const id = this.$route.query.id;
+      if (!id) return;
+
+      this.title =
+        this.$route.query.name ||
+        this.$route.redirectedFrom?.meta?.title ||
+        "查询";
+
+      // 命中缓存 → 恢复现场
+      if (this.pageCache[id]) {
+        Object.assign(this, this.pageCache[id]);
+        this.filterKey += 1;
+        return;
+      }
+
+      // 未命中 → 第一次进或缓存被清,走接口
+      this.loading = true;
+      this.loadPageData(id)
+        .then((data) => {
+          Object.assign(this, data);
+          this.$set(this.pageCache, id, data);
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
     /* 生命周期 */
     async init() {
       this.title =
@@ -341,6 +407,23 @@ export default {
         console.error("getList错误:", error);
       } finally {
         this.loading = false;
+        // ===== 新增:把当前现场写回缓存 =====
+        const id = this.$route.query.id;
+        if (id && this.pageCache[id]) {
+          this.pageCache[id] = {
+            ...this.pageCache[id],
+            list: this.list,
+            total: this.total,
+            originalList: this.originalList,
+            queryParamList: this.queryParamList,
+            customFilters: this.customFilters,
+            pageNo: this.pageNo,
+            pageSize: this.pageSize,
+            currentSortField: this.currentSortField,
+            currentSortDirection: this.currentSortDirection,
+          };
+        }
+        // =====================================
       }
     },
 
@@ -1012,24 +1095,18 @@ export default {
       await this.getQueryData();
     },
     handleRefresh() {
-      // 初始化所有条件
-      location.reload(true);
-
-      // 初始化所有条件
-      // this.queryParamList = [];
-      // this.customFilters = {};
-      // this.currentSortField = null;
-      // this.currentSortDirection = null;
-      // this.pageNo = 1;
-      // this.pageSize = 20;
-      // this.multipleSelection = [];
-      // this.isClear = true;
-
-      // // 重新拉取按钮、列配置和表格数据
-      // this.init();
-
-      // // 重置isClear状态
-      // setTimeout(() => (this.isClear = false), 1000);
+      const id = this.$route.query.id;
+      if (!id) return;
+      this.$delete(this.pageCache, id); // 清缓存
+      this.loading = true;
+      this.loadPageData(id)
+        .then((data) => {
+          Object.assign(this, data);
+          this.$set(this.pageCache, id, data);
+        })
+        .finally(() => {
+          this.loading = false;
+        });
     },
     rowStyle({ row }) {
       // 有值才上色,没有就保持默认

+ 8 - 8
src/views/rtkwms/inrequest/InRequestForm.vue

@@ -329,12 +329,12 @@
               </el-form-item>
             </el-col>
             <el-col :span="12">
-              <el-form-item label="原材仓仓管员" prop="receivePerson">
+              <el-form-item label="仓管员" prop="receivePerson">
                 <el-select
                   v-model="formData.receivePerson"
                   filterable
                   :disabled="isFormDisabled || !formData.businessType"
-                  placeholder="请输入原材仓仓管员"
+                  placeholder="请输入仓管员"
                   clearable
                   style="width: 100%"
                 >
@@ -625,7 +625,7 @@ export default {
         receivePerson: [
           {
             required: true,
-            message: "原材仓仓管员不能为空",
+            message: "仓管员不能为空",
             trigger: "blur",
           },
         ],
@@ -680,7 +680,7 @@ export default {
     },
     // 动态生成表单验证规则
     dynamicFormRules() {
-      // 从原始规则中只保留业务类型、优先级、预计出入库时间、原材仓仓管员
+      // 从原始规则中只保留业务类型、优先级、预计出入库时间、仓管员
       const baseRules = {
         businessType: this.formRules.businessType,
         priority: this.formRules.priority,
@@ -766,7 +766,7 @@ export default {
   created() {
     // 从路由参数获取ID
     const id = this.$route.query.id;
-    // 一次性获取全部原材仓仓管员
+    // 一次性获取全部仓管员
     getUserList().then((response) => {
       this.users = response.data;
     });
@@ -1020,7 +1020,7 @@ export default {
       try {
         // /* 1. 深拷贝一份,避免污染页面数据 */
         // const data = JSON.parse(JSON.stringify(this.formData));
-        // /* 2. 把原材仓仓管员转回字符串 */
+        // /* 2. 把仓管员转回字符串 */
         // data.receivePerson =
         //   data.receivePerson != null ? String(data.receivePerson) : "";
         const data = this.formData;
@@ -1068,9 +1068,9 @@ export default {
     },
     /** 提交按钮 */
     async commit() {
-      console.log("打印一下原材仓仓管员信息", this.formData.receivePerson);
+      console.log("打印一下仓管员信息", this.formData.receivePerson);
       if (!this.formData.receivePerson) {
-        this.$modal.msgWarning("请先添加原材仓仓管员");
+        this.$modal.msgWarning("请先添加仓管员");
         return;
       }
       const menuId = this.$route.meta.id;