Kaynağa Gözat

查询管理相关

yesheng 2 hafta önce
ebeveyn
işleme
26c9ec6fbc

+ 54 - 0
src/api/mes/queryManage/button.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 查询查询管理的按钮列表
+export function getQueryManageButtonPage(params) {
+  return request({
+    url: '/infra/query-manage-button/page',
+    method: 'get',
+    params: params
+  })
+}
+
+// 查询查询管理的按钮详情
+export function getQueryManageButton(id) {
+  return request({
+    url: '/infra/query-manage-button/get?id=' + id,
+    method: 'get'
+  })
+}
+
+// 新增查询管理的按钮
+export function createQueryManageButton(data) {
+  return request({
+    url: '/infra/query-manage-button/create',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改查询管理的按钮
+export function updateQueryManageButton(data) {
+  return request({
+    url: '/infra/query-manage-button/update',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除查询管理的按钮
+export function deleteQueryManageButton(id) {
+  return request({
+    url: '/infra/query-manage-button/delete?id=' + id,
+    method: 'delete'
+  })
+}
+
+// 导出查询管理的按钮 Excel
+export function exportQueryManageButtonApi(params) {
+  return request({
+    url: '/infra/query-manage-button/export-excel',
+    method: 'get',
+    params: params,
+    responseType: 'blob'
+  })
+}

+ 1 - 1
src/views/mes/queryManage/index.vue

@@ -202,7 +202,7 @@ export default {
     },
     handleToQuery(id) {
       this.$router.push({
-        path: `/querymanage/queryForm?id=${id}`,
+        path: `/querymanage/queryFormNew?id=${id}`,
       });
     },
     /** 查询列表 */

+ 3 - 2
src/views/mes/queryManage/query.vue

@@ -438,9 +438,10 @@ export default {
     // 获取显隐列列表
     this.id = this.$route.query?.id;
     this.getQueryData();
-    QueryManageApi.queryManageExecutecomplexdropdownlist().then((res) => {
+    //昱懋的,应该用不上
+    /*QueryManageApi.queryManageExecutecomplexdropdownlist().then((res) => {
       this.dropdownList = res;
-    });
+    });*/
   },
   beforeDestroy() {
     if (this.headerWidthChange) {

+ 752 - 0
src/views/mes/queryManage/queryNew.vue

@@ -0,0 +1,752 @@
+<template>
+  <div class="content-wrap">
+    <el-row class="mb-10px">
+      <!-- 动态按钮 -->
+      <template v-for="btn in dynamicButtons">
+        <el-button
+          v-if="!btn.ifHide"
+          :key="btn.id"
+          type="primary"
+          size="small"
+          @click="handleDynamicButtonClick(btn)"
+        >
+          {{ btn.buttonName }}
+        </el-button>
+      </template>
+
+      <el-button @click="AllConditionReset" size="small" type="danger">
+        <i class="iconfont mr-5px">&#xe6a7;</i>
+        全条件重置
+      </el-button>
+      <el-button @click="Export" size="small" type="primary">
+        <i class="iconfont mr-5px">&#xe6a0;</i>
+        导出
+      </el-button>
+      <el-button @click="ExportAll" :loading="exportLoading" size="small" type="success">
+        <i class="iconfont mr-5px">&#xe6a0;</i>
+        导出全部
+      </el-button>
+      <el-button @click="handleBack" size="small">
+        <i class="iconfont mr-5px">&#xe6a9;</i>
+        返回
+      </el-button>
+    </el-row>
+
+    <el-table
+      id="table_excel"
+      v-loading="loading"
+      :data="list"
+      :stripe="true"
+      :max-height="tableMaxHeight"
+      :show-overflow-tooltip="true"
+      size="small"
+      :summary-method="getSummaries"
+      @header-dragend="handleResize"
+      show-summary
+      border
+      ref="tableRef"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column v-if="showMultipleList.length > 0" 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"
+          :label="item.columnComment"
+          align="center"
+          :prop="item.columnComment"
+          :show-overflow-tooltip="true"
+          :min-width="item.javaField || ''"
+          :sortable="false"
+        >
+          <template slot="header">
+            <div class="mr-5px flex items-center">
+              <div class="mr-5px flex flex-col gap-0" v-show="item.ifSort">
+                <i
+                  class="iconfont"
+                  :class="{
+                    'is-sort': currentSortField === item.columnComment && currentSortDirection === 'asc'
+                  }"
+                  style="font-size: 15px;"
+                  @click="handleSort(item.columnComment, 'asc')"
+                >&#xe6a3;</i>
+                <i
+                  class="iconfont -mt-1.2"
+                  :class="{
+                    'is-sort': currentSortField === item.columnComment && currentSortDirection === 'desc'
+                  }"
+                  style="font-size: 15px;"
+                  @click="handleSort(item.columnComment, 'desc')"
+                >&#xe6a4;</i>
+              </div>
+              <span>{{ item.columnComment }}</span>
+              <filter-column-in-query
+                v-if="item.listOperationResult"
+                :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"
+                @select-data="filterData"
+                :dict-type="item.dictType"
+                :is-clear="isClear"
+              >
+                <template slot="reference">
+                  <div
+                    class="flex items-center justify-center text-gray-600"
+                    :class="{ 'has-filter': hasFilter(item.columnName) }"
+                  >
+                    <i class="iconfont ml-2px" style="font-size: 14px;">&#xe6a2;</i>
+                  </div>
+                </template>
+              </filter-column-in-query>
+            </div>
+          </template>
+          <template slot-scope="{ row }">
+            <div
+              @click="pathChange(item.example, row[item.columnComment], item, row)"
+              :class="{ active: item.example }"
+            >
+              <dict-tag
+                v-if="isDict(item.columnComment) && row[item.columnComment] !== undefined && row[item.columnComment] !== null"
+                :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>
+
+    <!-- 分页组件 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="pageNo"
+      :limit.sync="pageSize"
+      @pagination="handleSearch"
+    />
+
+    <!-- 积木标签打印 -->
+    <!--<report-print ref="reportPrint" />--><!--暂时注掉-->
+    <!-- 新增参数 -->
+    <!--<parameter-detail ref="parameterDetailRef" @success="getQueryData" />--><!--暂时注掉-->
+  </div>
+</template>
+
+<script>
+  import * as QueryManageApi from '@/api/mes/queryManage'
+  import { getQueryManageButtonPage } from '@/api/mes/queryManage/button'
+  /*import download from '@/utils/download'
+  import * as XLSX from 'xlsx'
+  import { saveAs } from 'file-saver'
+  import FilterColumnInQuery from './components/FilterColumnInQuery.vue'
+  import ParameterDetail from './components/ParameterDetail.vue'
+  import ReportPrint from '@/views/mes/personalManage/employeeMaster/components/ReportPrint.vue'
+  import request from '@/config/axios'*/ //暂时注掉
+  import { getAccessToken, getTenantId } from '@/utils/auth'
+  import axios from 'axios'
+
+  export default {
+    name: 'QueryForm',
+    /*components: {
+      FilterColumnInQuery,
+      ParameterDetail,
+      ReportPrint
+    },*/
+    data() {
+      return {
+        title: '',
+        queryList: [],
+        searchData: [],
+        queryData: [],
+        list: [],
+        originalList: [],
+        pageNo: 1,
+        pageSize: 20,
+        total: 0,
+        loading: false,
+        form: {},
+        visible: false,
+        customFilters: {},
+        currentSortField: null,
+        currentSortDirection: null,
+        dynamicButtons: [],
+        queryParamList: [],
+        exportLoading: false,
+        showMultipleList: [],
+        isClear: false,
+        headerWidthChange: false,
+        multipleSelection: []
+      }
+    },
+    computed: {
+      tableMaxHeight() {
+        return 'calc(100vh - 230px)'
+      }
+    },
+    methods: {
+      hasFilter(field) {
+        return !!this.customFilters[field] && this.customFilters[field].length > 0
+      },
+
+      async getQueryData() {
+        try {
+          this.loading = true
+          const data = await QueryManageApi.getQueryManageColumnListByMasterId(this.$route.query.id)
+          this.queryData = data
+
+          this.searchData = data.filter((item) => {
+            return 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++) {
+            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' : ''
+            })
+          }
+
+          await this.getManageButtons(this.$route.query.id)
+          await this.getList()
+        } catch (error) {
+          console.error(error)
+        } finally {
+          this.loading = false
+        }
+      },
+
+      async getList() {
+        try {
+          const data = await QueryManageApi.loadTableData({
+            pageNo: this.pageNo,
+            pageSize: this.pageSize,
+            paramList: this.queryParamList,
+            id: this.$route.query.id
+          })
+          this.list = data.list || []
+          this.originalList = JSON.parse(JSON.stringify(data.list || []))
+          this.total = data.total || 0
+        } catch (error) {
+          console.error(error)
+        } finally {
+          this.loading = false
+        }
+      },
+
+      async getManageButtons(masterId) {
+        try {
+          const data = await getQueryManageButtonPage({ masterId })
+          this.dynamicButtons = data.list || []
+        } catch (error) {
+          console.error(error)
+        }
+      },
+
+      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)
+        }
+      },
+
+      handlePrintByJimu(params) {
+        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
+        const baseUrl = process.env.VUE_APP_BASE_URL
+        const token = getAccessToken()
+        const tenantId = getTenantId()
+        const { paramList = [], interfaceUrl, reportId } = params
+        const fieldValues = this.paramsToConver(paramList)
+        const printParams = new URLSearchParams({
+          token,
+          tenantId,
+          ...fieldValues
+        })
+
+        const src = `${baseUrl}${interfaceUrl}${reportId}?${printParams.toString()}`
+        this.$refs.reportPrint.open(src, this.$route.query.name || '报表打印')
+      },
+
+      async handlePrintByOtherSoft(params) {
+        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
+        try {
+          const { interfaceUrl, paramList, restMethod, templet } = params
+          if (!templet) return this.$message.warning('未配置打印模板!')
+          const fieldValues = this.paramsToConver(paramList)
+          const printParams = {
+            ...fieldValues,
+            fileUrl: templet
+          }
+
+          const config = {
+            method: restMethod,
+            url: interfaceUrl
+          }
+
+          if (['post', 'put'].includes(restMethod)) {
+            config.data = printParams
+          } else {
+            config.params = printParams
+          }
+
+          await axios(config)
+          this.$message.success('操作成功!')
+          this.getList()
+        } catch (error) {
+          console.error(error)
+        }
+      },
+
+      async handleDynamic(params) {
+        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
+        const { interfaceUrl, restMethod = 'get', paramList = [], requestParameter = '0' } = params
+        const fieldValues = this.paramsToConver(paramList)
+
+        try {
+          let config = { method: restMethod, url: interfaceUrl }
+
+          if (restMethod === 'get' || restMethod === 'delete') {
+            this.handleGetDelete(config, fieldValues, requestParameter)
+          } else {
+            if (requestParameter === '1') {
+              this.handleGetDelete(config, fieldValues, requestParameter)
+            } else {
+              config.data = fieldValues
+            }
+          }
+
+          await request[restMethod](config)
+          this.$message.success('操作成功')
+          this.getList()
+        } catch (error) {
+          console.error(error)
+        }
+      },
+
+      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
+        }
+      },
+
+      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
+          }, {})
+        )
+      },
+
+      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 ? 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
+        }, {})
+      },
+
+      isFullUrl(url) {
+        try {
+          const parsed = new URL(url)
+          return parsed.protocol === 'http:' || parsed.protocol === 'https:'
+        } catch (e) {
+          return false
+        }
+      },
+
+      isDict(key) {
+        const item = this.queryData.find((item) => item.columnComment === key)
+        return item && item.dictType ? item.dictType : false
+      },
+
+      isNumber(key) {
+        const item = this.queryData.find((item) => item.columnComment === key)
+        return item && item.dataType === 'ym_int_query_type'
+      },
+
+      isDateTime(key) {
+        const item = this.queryData.find((item) => item.columnComment === key)
+        return item && item.javaType === 'LocalDateTime'
+      },
+
+      handleSort(field, direction) {
+        if (this.currentSortField === field && this.currentSortDirection === direction) {
+          this.currentSortField = null
+          this.currentSortDirection = null
+          this.list = [...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) || isNaN(valB)) {
+            return direction === 'asc'
+              ? String(valA).localeCompare(String(valB))
+              : String(valB).localeCompare(String(valA))
+          }
+
+          return direction === 'asc' ? valA - valB : valB - valA
+        })
+      },
+
+      filterData(data, field, type, item) {
+        const { dataType } = item
+        this.customFilters[field] = data
+
+        if (data.length === 0) {
+          const index = this.queryParamList.findIndex((item) => item.key === field)
+          if (index > -1) this.queryParamList.splice(index, 1)
+          this.getList()
+          return
+        }
+
+        const isDateRange = data[0] && data[0].isRange
+        let valueStr
+
+        if (isDateRange) {
+          valueStr = data.flatMap((item) => item.column).join(',')
+        } else {
+          valueStr = dataType === 'ym_int_query_type'
+            ? data.map((item) => item.column).join(',')
+            : data.map((item) => `'${item.column}'`).join(',')
+        }
+
+        const index = this.queryParamList.findIndex((item) => item.key === field)
+        if (index > -1) {
+          this.queryParamList[index].value = valueStr
+        } else {
+          this.queryParamList.push({ key: field, operate: 'like', htmlType: type, value: valueStr })
+        }
+
+        this.getList()
+      },
+
+      AllConditionReset() {
+        this.queryParamList = []
+        this.customFilters = {}
+        this.isClear = true
+        setTimeout(() => {
+          this.isClear = false
+          this.getList()
+        }, 1000)
+      },
+
+      handleSearch() {
+        this.getList()
+      },
+
+      async Export() {
+        try {
+          await this.$confirm('确定要导出数据吗?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          })
+
+          setTimeout(() => {
+            const tables = document.getElementById('table_excel')
+            const table_book = XLSX.utils.table_to_book(tables, { raw: true })
+            const table_write = XLSX.write(table_book, {
+              bookType: 'xlsx',
+              bookSST: true,
+              type: 'array'
+            })
+            saveAs(new Blob([table_write], { type: 'application/octet-stream' }), `${this.title}.xlsx`)
+          }, 1000)
+        } catch (error) {
+          console.error(error)
+        }
+      },
+
+      async ExportAll() {
+        try {
+          await this.$confirm('确定要导出全部数据吗?', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          })
+
+          this.exportLoading = true
+          const data = await QueryManageApi.exportExcel({
+            id: this.$route.query.id,
+            paramList: this.queryParamList
+          })
+          download.excel(data, this.title + '.xls')
+        } catch (error) {
+          console.error(error)
+        } finally {
+          this.exportLoading = false
+        }
+      },
+
+      getHandleNumber(val) {
+        return Math.round(parseFloat(val) * 100000000) / 100000000
+      },
+
+      getSummaries(param) {
+        const { columns } = param
+        const sums = []
+        columns.forEach((column, index) => {
+          if (index === 0) {
+            sums[index] = '总计'
+            return
+          }
+
+          if (this.isNumber(column.property)) {
+            const values = this.list.map((item) => Number(item[column.property])).filter(val => !isNaN(val))
+            sums[index] = values.reduce((acc, cur) => this.getHandleNumber(acc + cur), 0)
+          } else {
+            sums[index] = ''
+          }
+        })
+        return sums
+      },
+
+      handleSelectionChange(val) {
+        this.multipleSelection = val
+      },
+
+      pathChange(path, val, item, row) {
+        if (!path || path === 'sameRouter') return
+
+        const data = {}
+        this.dynamicButtons.filter((v) => {
+          if (v.ifHide && v.paramList) {
+            v.paramList.forEach((param) => {
+              data[param.paramName] = param.value || row[param.paramComment]
+            })
+          }
+        })
+
+        this.$router.push({ path, query: { id: val, ...data } })
+      },
+
+      handleResize() {
+        this.headerWidthChange = true
+      },
+
+      handleBack() {
+        this.$router.push({ path: '/querymanage/queryManageIndex' })
+      },
+
+      formatToDateTime(date) {
+        if (!date) return ''
+        try {
+          const d = new Date(date)
+          return d.toLocaleString()
+        } catch (e) {
+          return date
+        }
+      },
+
+      async getFilterData() {
+        const data = await getQueryManageButtonPage({ masterId: this.$route.query.infraQueryId })
+        const arr = []
+
+        data.list.forEach((v) => {
+          if (v.ifHide && v.paramList) {
+            v.paramList.forEach((val) => {
+              if (val.filter) arr.push(val.paramName)
+            })
+          }
+        })
+
+        this.queryParamList = Object.keys(this.$route.query)
+          .filter(key => key !== 'id' && key !== 'name' && arr.includes(key))
+          .map(key => ({
+            key,
+            operate: 'like',
+            htmlType: 'input',
+            value: `'${this.$route.query[key]}'`
+          }))
+
+        await this.getQueryData()
+      }
+    },
+
+    async mounted() {
+      this.title = this.$route.query.name || ''
+      if (this.$route.query.infraQueryId) {
+        await this.getFilterData()
+      } else {
+        this.queryParamList = Object.keys(this.$route.query)
+          .filter(key => key !== 'id' && key !== 'name')
+          .map(key => ({
+            key,
+            operate: 'like',
+            htmlType: 'input',
+            value: `'${this.$route.query[key]}'`
+          }))
+        await this.getQueryData()
+      }
+    },
+
+    activated() {
+      if (this.$route.query.name) {
+        this.title = this.$route.query.name
+        if (this.$route.query.infraQueryId) {
+          this.getFilterData()
+        } else {
+          this.queryParamList = Object.keys(this.$route.query)
+            .filter(key => key !== 'id' && key !== 'name')
+            .map(key => ({
+              key,
+              operate: 'like',
+              htmlType: 'input',
+              value: `'${this.$route.query[key]}'`
+            }))
+          this.getQueryData()
+        }
+      }
+    },
+
+    beforeDestroy() {
+      if (!this.headerWidthChange) return
+
+      const headers = this.$refs.tableRef.$el.querySelectorAll('.el-table__header-wrapper tr th')
+      const visibleColumns = this.queryData.filter((item) => !item.ifHide)
+      const widthList = []
+
+      Array.from(headers).forEach((header, i) => {
+        if (i >= visibleColumns.length) return
+        if (header.classList.contains('el-table-column--selection')) return
+        if (header.innerText.trim() === '') return
+
+        widthList.push({
+          id: visibleColumns[i].id,
+          javaField: header.offsetWidth
+        })
+      })
+
+      QueryManageApi.updateWidth(widthList).catch(console.error)
+    }
+  }
+</script>
+
+<style scoped>
+  .mb-10px {
+    margin-bottom: 10px;
+  }
+
+  .mr-5px {
+    margin-right: 5px;
+  }
+
+  .ml-2px {
+    margin-left: 2px;
+  }
+
+  .mt-1\.2 {
+    margin-top: -1.2em;
+  }
+
+  .flex {
+    display: flex;
+  }
+
+  .items-center {
+    align-items: center;
+  }
+
+  .justify-center {
+    justify-content: center;
+  }
+
+  .flex-col {
+    flex-direction: column;
+  }
+
+  .gap-0 {
+    gap: 0;
+  }
+
+  .text-gray-600 {
+    color: #718096;
+  }
+
+  .active:hover {
+    cursor: pointer;
+    color: #1890ff;
+  }
+
+  .has-filter,
+  .is-sort {
+    color: #1890ff !important;
+  }
+
+  :deep(.el-table__row) {
+    height: 15px !important;
+  }
+
+  :deep(.el-table--medium .el-table__cell),
+  :deep(.el-table--small .el-table__cell) {
+    padding: 1px 0 !important;
+  }
+</style>