|
|
@@ -0,0 +1,1056 @@
|
|
|
+<template>
|
|
|
+ <!-- 唯一根节点:el-card -->
|
|
|
+ <el-card
|
|
|
+ class="el-content-wrap mb-3px"
|
|
|
+ shadow="never"
|
|
|
+ style="height: 100%; display: flex; flex-direction: column"
|
|
|
+ >
|
|
|
+ <!-- 原 content-wrap 的 slot 内容 -->
|
|
|
+ <el-row class="mb-10px" style="flex-shrink: 0">
|
|
|
+ <!-- 按钮区域已注释 -->
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 表格 - 设置高度为100%以撑满剩余空间 -->
|
|
|
+ <el-table
|
|
|
+ id="table_excel"
|
|
|
+ ref="tableRef"
|
|
|
+ v-loading="loading"
|
|
|
+ class="dark-panel"
|
|
|
+ :data="list"
|
|
|
+ border
|
|
|
+ :row-style="rowStyle"
|
|
|
+ :cell-style="cellStyle"
|
|
|
+ height="100%"
|
|
|
+ style="font-size: 11px; flex: 1"
|
|
|
+ show-overflow-tooltip
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ @header-dragend="handleResize"
|
|
|
+ >
|
|
|
+ <el-table-column
|
|
|
+ v-if="showMultipleList.length"
|
|
|
+ key="selection-column"
|
|
|
+ type="selection"
|
|
|
+ width="45"
|
|
|
+ />
|
|
|
+ <el-table-column type="index" width="45" align="center" />
|
|
|
+
|
|
|
+ <template v-for="(item, i) in queryData">
|
|
|
+ <el-table-column
|
|
|
+ v-if="!item.ifHide"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.columnComment"
|
|
|
+ :prop="item.columnComment"
|
|
|
+ align="center"
|
|
|
+ :min-width="item.javaField || ''"
|
|
|
+ :sortable="false"
|
|
|
+ show-overflow-tooltip
|
|
|
+ >
|
|
|
+ <template slot="header">
|
|
|
+ <div class="mr-5px flex items-center" style="font-size: 11px">
|
|
|
+ <!-- 排序图标 -->
|
|
|
+ <div v-show="item.ifSort" class="mr-5px flex flex-col gap-0">
|
|
|
+ <i
|
|
|
+ class="el-icon-caret-top"
|
|
|
+ style="font-size: 12px; 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: 12px; cursor: pointer"
|
|
|
+ :class="{
|
|
|
+ 'is-sort':
|
|
|
+ currentSortField === item.columnComment &&
|
|
|
+ currentSortDirection === 'desc',
|
|
|
+ }"
|
|
|
+ @click="handleSort(item.columnComment, 'desc')"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <span>{{ item.columnComment }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <div
|
|
|
+ :class="{ active: item.example }"
|
|
|
+ @click="
|
|
|
+ pathChange(item.example, row[item.columnComment], item, row)
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <dict-tag
|
|
|
+ v-if="
|
|
|
+ isDict(item.columnComment) &&
|
|
|
+ ![undefined, null].includes(row[item.columnComment])
|
|
|
+ "
|
|
|
+ :type="isDict(item.columnComment)"
|
|
|
+ :value="row[item.columnComment]"
|
|
|
+ />
|
|
|
+ <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>
|
|
|
+
|
|
|
+ <!-- 分页 - 仅在刷新时间为0时显示 -->
|
|
|
+ <pagination
|
|
|
+ v-show="total > 0 && refreshMin == 0"
|
|
|
+ :total="total"
|
|
|
+ :page.sync="pageNo"
|
|
|
+ :limit.sync="pageSize"
|
|
|
+ :page-sizes="[5, 10, 20, 30, 50]"
|
|
|
+ style="flex-shrink: 0; margin-top: 4px"
|
|
|
+ @pagination="handleSearch"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 弹窗 -->
|
|
|
+ <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 "@/views/mes/queryManage/components/FilterColumnInQuery.vue";
|
|
|
+import DictTag from "@/components/DictTag";
|
|
|
+import ParameterDetail from "@/views/mes/queryManage/components/ParameterDetail.vue";
|
|
|
+import ReportPrint from "@/views/mes/queryManage/components/ReportPrint.vue";
|
|
|
+import request from "@/utils/request";
|
|
|
+import { getAccessToken, getTenantId } from "@/utils/auth";
|
|
|
+import axios from "axios";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "QueryNew",
|
|
|
+ components: {
|
|
|
+ FilterColumnInQuery,
|
|
|
+ ParameterDetail,
|
|
|
+ ReportPrint,
|
|
|
+ DictTag,
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ documentId: { type: String, required: true },
|
|
|
+ refreshMin: { type: Number, default: 10 },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ title: "",
|
|
|
+ message: "",
|
|
|
+ baseUrl: "",
|
|
|
+ queryList: [],
|
|
|
+ searchData: [],
|
|
|
+ queryData: [],
|
|
|
+ list: [],
|
|
|
+ originalList: [],
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 5,
|
|
|
+ total: 0,
|
|
|
+ loading: false,
|
|
|
+ form: {},
|
|
|
+ visible: false,
|
|
|
+ customFilters: {},
|
|
|
+ currentSortField: null,
|
|
|
+ currentSortDirection: null,
|
|
|
+ dynamicButtons: [],
|
|
|
+ queryParamList: [],
|
|
|
+ exportLoading: false,
|
|
|
+ showMultipleList: [],
|
|
|
+ isClear: false,
|
|
|
+ multipleSelection: [],
|
|
|
+ headerWidthChange: false,
|
|
|
+ filterKey: 0,
|
|
|
+ filterAlive: true,
|
|
|
+ autoPageTimer: null,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ "$route.query.name": {
|
|
|
+ handler(newName) {
|
|
|
+ this.title =
|
|
|
+ newName || this.$route.redirectedFrom?.meta?.title || "查询";
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "$route.query.id": {
|
|
|
+ handler() {
|
|
|
+ this.init();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ refreshMin: {
|
|
|
+ handler() {
|
|
|
+ this.restartAutoPage();
|
|
|
+ },
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.init();
|
|
|
+ this.startAutoPage();
|
|
|
+ },
|
|
|
+ activated() {
|
|
|
+ this.init();
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ this.stopAutoPage();
|
|
|
+ this.saveColumnWidth();
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.baseUrl = process.env.VUE_APP_REPORT_API;
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async init() {
|
|
|
+ this.title =
|
|
|
+ this.$route.query?.name ||
|
|
|
+ this.$route.redirectedFrom?.meta?.title ||
|
|
|
+ "查询";
|
|
|
+ if (this.documentId) {
|
|
|
+ await this.getFilterData();
|
|
|
+ } else {
|
|
|
+ this.buildQueryParamFromRoute();
|
|
|
+ await this.getQueryData();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async getQueryData() {
|
|
|
+ try {
|
|
|
+ this.loading = true;
|
|
|
+ const data = await QueryManageApi.getQueryManageColumnListByMasterId(
|
|
|
+ this.documentId
|
|
|
+ );
|
|
|
+ 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" : "",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ await this.getManageButtons(this.documentId);
|
|
|
+ await this.getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.error("getQueryData 出现了错误:", error);
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async getList() {
|
|
|
+ try {
|
|
|
+ this.loading = true;
|
|
|
+ const data = await QueryManageApi.loadTableData({
|
|
|
+ pageNo: this.pageNo,
|
|
|
+ pageSize: this.pageSize,
|
|
|
+ paramList: this.queryParamList,
|
|
|
+ id: this.documentId,
|
|
|
+ });
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async getManageButtons(masterId) {
|
|
|
+ const data = await getQueryManageButtonPage({ masterId });
|
|
|
+ this.dynamicButtons = data?.data?.list || [];
|
|
|
+ },
|
|
|
+
|
|
|
+ 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.documentId,
|
|
|
+ [],
|
|
|
+ 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.documentId,
|
|
|
+ this.multipleSelection,
|
|
|
+ this.queryData
|
|
|
+ );
|
|
|
+ } else if (operateType === 7) {
|
|
|
+ this.$router.push({ path: `${interfaceUrl}` });
|
|
|
+ } else {
|
|
|
+ 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";
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ 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("请先选择数据!");
|
|
|
+ }
|
|
|
+
|
|
|
+ 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("未配置打印模板!");
|
|
|
+
|
|
|
+ const url = String(interfaceUrl || "").trim();
|
|
|
+ if (!url || url === "0") {
|
|
|
+ this.$message.error("接口地址未配置或格式错误!");
|
|
|
+ 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;
|
|
|
+
|
|
|
+ const url = String(interfaceUrl || "").trim();
|
|
|
+ if (!url || url === "0") {
|
|
|
+ this.$message.error("接口地址未配置或格式错误!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const fieldValues = this.paramsToConver(paramList);
|
|
|
+ const config = { method: restMethod, url };
|
|
|
+ this.handleGetDelete(config, fieldValues, String(requestParameter));
|
|
|
+
|
|
|
+ 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 {
|
|
|
+ const parsed = new URL(url);
|
|
|
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
|
+ } catch {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ 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);
|
|
|
+ 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,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ 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() {
|
|
|
+ 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(() => {
|
|
|
+ this.filterKey++;
|
|
|
+ this.queryData = tmp;
|
|
|
+ this.filterAlive = true;
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.getList();
|
|
|
+ setTimeout(() => (this.isClear = false), 1000);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ handleSearch() {
|
|
|
+ this.list = [];
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+
|
|
|
+ async Export() {
|
|
|
+ try {
|
|
|
+ await this.$confirm("确定导出当前页?", "提示", { type: "warning" });
|
|
|
+ setTimeout(() => {
|
|
|
+ const xlsxParam = { raw: true };
|
|
|
+ const tables = document.getElementById("table_excel");
|
|
|
+ const table_book = XLSX.utils.table_to_book(tables, xlsxParam);
|
|
|
+ const tableWrite = XLSX.write(table_book, {
|
|
|
+ bookType: "xlsx",
|
|
|
+ bookSST: true,
|
|
|
+ type: "array",
|
|
|
+ });
|
|
|
+ saveAs(
|
|
|
+ new Blob([tableWrite], { type: "application/octet-stream" }),
|
|
|
+ `${this.title}.xlsx`
|
|
|
+ );
|
|
|
+ }, 1000);
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== "cancel") {
|
|
|
+ console.error("导出失败:", error);
|
|
|
+ this.$message.error("导出失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ async ExportAll() {
|
|
|
+ try {
|
|
|
+ await this.$confirm("确定导出全部?", "提示", { type: "warning" });
|
|
|
+ this.exportLoading = true;
|
|
|
+ const data = await QueryManageApi.exportExcel({
|
|
|
+ id: this.documentId,
|
|
|
+ paramList: this.queryParamList,
|
|
|
+ });
|
|
|
+ this.$download.excel(data, this.title + ".xls");
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== "cancel") {
|
|
|
+ console.error("导出失败:", error);
|
|
|
+ this.$message.error("导出失败");
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ this.exportLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ getHandleNumber(val) {
|
|
|
+ return Math.round(parseFloat(val) * 100000000) / 100000000;
|
|
|
+ },
|
|
|
+
|
|
|
+ getSummaries({ columns }) {
|
|
|
+ const sums = [];
|
|
|
+ columns.forEach((column, index) => {
|
|
|
+ if (index === 0) {
|
|
|
+ sums[index] = "总计";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ 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 sums;
|
|
|
+ },
|
|
|
+
|
|
|
+ handleSelectionChange(val) {
|
|
|
+ this.multipleSelection = val;
|
|
|
+ },
|
|
|
+
|
|
|
+ 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 } });
|
|
|
+ },
|
|
|
+
|
|
|
+ handleBack() {
|
|
|
+ this.$router.push({ path: "/querymanage/queryManageIndex" });
|
|
|
+ },
|
|
|
+
|
|
|
+ handleResize() {
|
|
|
+ this.headerWidthChange = true;
|
|
|
+ },
|
|
|
+
|
|
|
+ async saveColumnWidth() {
|
|
|
+ if (!this.headerWidthChange) return;
|
|
|
+ this.headerWidthChange = false;
|
|
|
+
|
|
|
+ const widthList = [];
|
|
|
+ const visibleMap = new Map(
|
|
|
+ this.queryData.filter((c) => !c.ifHide).map((c) => [c.columnComment, c])
|
|
|
+ );
|
|
|
+
|
|
|
+ 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 });
|
|
|
+ });
|
|
|
+
|
|
|
+ if (widthList.length) {
|
|
|
+ await QueryManageApi.updateWidth(widthList);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ 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] + "'",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.queryParamList = queryParam;
|
|
|
+ },
|
|
|
+
|
|
|
+ async getFilterData() {
|
|
|
+ const data = await getQueryManageButtonPage({
|
|
|
+ masterId: this.$route.query?.infraQueryId || this.documentId,
|
|
|
+ });
|
|
|
+ const list = data?.data?.list || data?.data || [];
|
|
|
+ const arr = [];
|
|
|
+ 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();
|
|
|
+ },
|
|
|
+
|
|
|
+ handleRefresh() {
|
|
|
+ location.reload(true);
|
|
|
+ },
|
|
|
+
|
|
|
+ startAutoPage() {
|
|
|
+ this.stopAutoPage();
|
|
|
+ const ms = this.refreshMin * 1000;
|
|
|
+ if (!ms || ms <= 0) return;
|
|
|
+ this.autoPageTimer = setInterval(() => {
|
|
|
+ const max = Math.ceil(this.total / this.pageSize);
|
|
|
+ this.pageNo = this.pageNo < max ? this.pageNo + 1 : 1;
|
|
|
+ this.getList();
|
|
|
+ }, ms);
|
|
|
+ },
|
|
|
+
|
|
|
+ stopAutoPage() {
|
|
|
+ if (this.autoPageTimer) {
|
|
|
+ clearInterval(this.autoPageTimer);
|
|
|
+ this.autoPageTimer = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ restartAutoPage() {
|
|
|
+ this.startAutoPage();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 修改后的 rowStyle - 添加固定行高
|
|
|
+ rowStyle({ row }) {
|
|
|
+ const baseStyle = { height: "28px" };
|
|
|
+ if (row.colorControl) {
|
|
|
+ return {
|
|
|
+ ...baseStyle,
|
|
|
+ backgroundColor: row.colorControl + " !important",
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return baseStyle;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 新增 cellStyle - 控制单元格内边距
|
|
|
+ cellStyle() {
|
|
|
+ return {
|
|
|
+ padding: "2px 0",
|
|
|
+ fontSize: "11px",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* ---------- ContentWrap 原样式 ---------- */
|
|
|
+.el-content-wrap {
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+.text-16px {
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+.font-700 {
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+.ml-5px {
|
|
|
+ margin-left: 5px;
|
|
|
+}
|
|
|
+.max-w-200px {
|
|
|
+ max-width: 200px;
|
|
|
+}
|
|
|
+.mb-3px {
|
|
|
+ margin-bottom: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+/* ---------- 表格样式优化 ---------- */
|
|
|
+/* 行高设置 - 修改为28px */
|
|
|
+:deep(.el-table__row) {
|
|
|
+ height: 28px !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 单元格样式 */
|
|
|
+:deep(.el-table .cell) {
|
|
|
+ line-height: 24px !important;
|
|
|
+ padding: 2px 4px !important;
|
|
|
+ font-size: 11px !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表头样式 */
|
|
|
+:deep(.el-table th) {
|
|
|
+ height: 28px !important;
|
|
|
+ padding: 0 !important;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-table th > .cell) {
|
|
|
+ line-height: 28px !important;
|
|
|
+ font-size: 11px !important;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表格整体字体 */
|
|
|
+:deep(.el-table) {
|
|
|
+ font-size: 11px !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 选中列和索引列宽度调整 */
|
|
|
+:deep(.el-table-column--selection),
|
|
|
+:deep(.el-table-column--index) {
|
|
|
+ width: 45px !important;
|
|
|
+ min-width: 45px !important;
|
|
|
+}
|
|
|
+
|
|
|
+.active:hover {
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+.has-filter,
|
|
|
+.is-sort,
|
|
|
+.active {
|
|
|
+ color: #1890ff !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 整卡背景 & 边框 ========= */
|
|
|
+>>> .el-card,
|
|
|
+>>> .el-card__body {
|
|
|
+ background-color: #0a1e44 !important;
|
|
|
+ color: #fff !important;
|
|
|
+ border-color: #1a2e5a !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 卡片头部 ========= */
|
|
|
+>>> .el-card__header {
|
|
|
+ background-color: #071b38 !important;
|
|
|
+ color: #fff !important;
|
|
|
+ border-bottom: 1px solid #1a2e5a !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 表格整体 ========= */
|
|
|
+>>> .el-table,
|
|
|
+>>> .el-table__body-wrapper,
|
|
|
+>>> .el-table__header-wrapper {
|
|
|
+ background-color: transparent !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 表头 ========= */
|
|
|
+>>> .el-table th,
|
|
|
+>>> .el-table th > .cell {
|
|
|
+ background-color: #071b38 !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 表行/表格 ========= */
|
|
|
+>>> .el-table tr,
|
|
|
+>>> .el-table td,
|
|
|
+>>> .el-table td > .cell {
|
|
|
+ background-color: transparent !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 鼠标悬停 ========= */
|
|
|
+>>> .el-table__body tr:hover > td {
|
|
|
+ background-color: rgba(255, 255, 255, 0.12) !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 分页器/底部工具栏 ========= */
|
|
|
+>>> .el-pagination__total,
|
|
|
+>>> .el-pagination__jump,
|
|
|
+>>> .el-pager li {
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 去掉列表与分页之间白块 ========= */
|
|
|
+>>> .el-card__body {
|
|
|
+ padding-bottom: 0 !important;
|
|
|
+}
|
|
|
+
|
|
|
+>>> .pagination-container .el-pagination {
|
|
|
+ margin-top: 0 !important;
|
|
|
+}
|
|
|
+
|
|
|
+>>> .pagination-container {
|
|
|
+ margin-top: -4px;
|
|
|
+ background-color: #0a1e44 !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========= 分页数字块 ========= */
|
|
|
+>>> .el-pagination.is-background .el-pager li {
|
|
|
+ background-color: transparent !important;
|
|
|
+ color: #fff !important;
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.35) !important;
|
|
|
+}
|
|
|
+
|
|
|
+>>> .el-pagination.is-background .el-pager li.active {
|
|
|
+ background-color: rgba(255, 255, 255, 0.9) !important;
|
|
|
+ color: #0a1e44 !important;
|
|
|
+ border-color: transparent !important;
|
|
|
+}
|
|
|
+
|
|
|
+>>> .el-pagination.is-background .el-pager li:hover:not(.active) {
|
|
|
+ background-color: rgba(255, 255, 255, 0.15) !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+</style>
|