CustomTable.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. <script setup lang="ts">
  2. import type { PropsParams, TablePaginationSetting } from '@/types/table.ts'
  3. import type { ReqConfig } from '@/types/dataAnalysis.ts'
  4. import { FieldSpecialEffectType } from '@/types/tableText.ts'
  5. import { fuzzySearch, throttleFunc } from '@/utils/common'
  6. import { useTable } from '@/hooks/useTable.ts'
  7. import { useRequest } from '@/hooks/useRequest.ts'
  8. import {
  9. computed,
  10. type ComputedRef,
  11. markRaw,
  12. nextTick,
  13. onMounted,
  14. reactive,
  15. ref,
  16. toRaw,
  17. watch
  18. } from 'vue'
  19. import TableFilterForm from '@/components/table/TableFilterForm/TableFilterForm.vue'
  20. import axiosInstance from '@/utils/axios/axiosInstance.ts'
  21. import TableTools from './TableTools.vue'
  22. import TableColumn from './TableColumn/TableColumn.vue'
  23. import type { ResponseInfo } from '@/types/res.ts'
  24. type TableFilterFormRef = InstanceType<typeof TableFilterForm>
  25. // 查询表单的Ref
  26. const filterFormRef = ref<TableFilterFormRef>()
  27. const { analysisResCode } = useRequest()
  28. // 节流的延迟时间
  29. const throttleTime = 500
  30. const props = withDefaults(defineProps<PropsParams>(), {
  31. needRowindex: true,
  32. needAverage: false,
  33. needTotal: false,
  34. openFilterQuery: true,
  35. openPageQuery: true,
  36. loadingState: false,
  37. openRemoteReqData: true,
  38. openRemoteQuery: true
  39. })
  40. const emits = defineEmits(['addNewItem', 'upload', 'downLoad'])
  41. // 加载动画
  42. const loading = ref(false)
  43. // 表格数据
  44. const tableData: Array<any> = reactive([])
  45. // 展开表格数据
  46. const expandTableData: Record<string, Array<any>> = reactive({})
  47. // 分页展开表格数据
  48. const expandPaginationConfig = reactive<Record<string, TablePaginationSetting>>({})
  49. const expandPageData = computed(() => {
  50. const nowActive = activeExpandTablePageConfig.value
  51. const { currentPage, limit } = expandPaginationConfig[nowActive]
  52. if (!expandTableData[nowActive]) return []
  53. // const data = expandTableData[nowActive].slice((currentPage - 1) * limit, currentPage * limit)
  54. return expandTableData[nowActive].slice((currentPage - 1) * limit, currentPage * limit)
  55. })
  56. // 现在使用的分页
  57. const activeExpandTablePageConfig = ref<string>('')
  58. // 查询表单的数据
  59. const queryFormData = ref<{ [key: string]: any }>({})
  60. // 分页数据
  61. const paginationConfig = reactive<TablePaginationSetting>({
  62. currentPage: 1,
  63. limit: 0,
  64. total: 0,
  65. pageSizeList: []
  66. })
  67. // 请求配置
  68. const reqConfig = reactive<ReqConfig>({
  69. url: '',
  70. otherOptions: {}
  71. })
  72. // 一些公用方法
  73. const {
  74. getTableData,
  75. setTableData,
  76. computedRowIndex,
  77. handleCurrentChange,
  78. handleSizeChange,
  79. insertAverageRow,
  80. getDecimalFromRange,
  81. resetTableData,
  82. initPageConfig,
  83. initReqConfig,
  84. createRowKey,
  85. downLoadTable
  86. } = useTable(tableData, paginationConfig, props.tableFieldsInfo)
  87. /**
  88. * 本地使用的数据,只有在使用外部数据的情况下使用
  89. */
  90. let localTableData: ComputedRef | [] = []
  91. if (!props.openRemoteReqData && props.dataList) {
  92. if (Array.isArray(props.dataList)) {
  93. localTableData = computed<Array<any>>(() => {
  94. let curPage = paginationConfig.currentPage
  95. let limit = paginationConfig.limit
  96. let begin = curPage * limit - limit
  97. let end = curPage * limit
  98. return tableData.slice(begin, end)
  99. })
  100. }
  101. }
  102. /**
  103. * 获取表格数据
  104. * @returns [表格数据,数据总数]
  105. */
  106. const getData = async (): Promise<[Array<any>, number]> => {
  107. try {
  108. for (let [k, v] of Object.entries(expandTableData)) {
  109. if (v) {
  110. delete expandTableData[k]
  111. }
  112. }
  113. expandRowKeys.value = []
  114. // expandPageData.value.splice(0, expandPageData.value.length)
  115. // 使用传入数据源
  116. // 如果使用前端查询,则需要传入dataList作为数据源
  117. if (!props.openRemoteReqData) {
  118. if (props.dataList) {
  119. return [JSON.parse(JSON.stringify(props.dataList)), 0]
  120. } else {
  121. console.error('请传入dataList,没有数据源!')
  122. return [[], 0]
  123. }
  124. } else {
  125. // 如果需要表格自己请求数据的
  126. // 必须要传入requestConfig
  127. if (props.requestConfig) {
  128. // 当使用远程请求数据源的时候,默认使用远程查询
  129. reqConfig.otherOptions.offset = (paginationConfig.currentPage - 1) * paginationConfig.limit
  130. reqConfig.otherOptions.limit = paginationConfig.limit
  131. return await getTableData(reqConfig.url, reqConfig.otherOptions)
  132. } else {
  133. console.error('缺少请求配置')
  134. return [[], 0]
  135. }
  136. }
  137. } catch (err) {
  138. console.error('请求错误:', err)
  139. return [[], 0] // 确保返回 false 表示失败
  140. }
  141. }
  142. /**
  143. * 将获取的数据赋值给tableData,同时设置分页数据的总数
  144. * @param tableList 表格数据
  145. * @param total 数据总数
  146. * @returns 设置是否成功
  147. */
  148. const setData = (tableList: Array<any>, total: number): boolean => {
  149. try {
  150. setTableData(tableList, total, props.openPageQuery, props.openRemoteReqData)
  151. insertAverageRow(props.needAverage, props.openRemoteReqData)
  152. return true
  153. } catch (err) {
  154. console.error(err)
  155. return false
  156. }
  157. }
  158. /**
  159. * 更新表格数据
  160. * @returns 设置是否成功
  161. */
  162. const updateTableData = async (): Promise<boolean> => {
  163. try {
  164. loading.value = true
  165. let [tableList, total] = await getData()
  166. setData(tableList, total)
  167. return true
  168. } catch (err) {
  169. console.log(err)
  170. return false
  171. } finally {
  172. loading.value = false
  173. }
  174. }
  175. // 包装一下获取数据
  176. const throttleGetData = throttleFunc(updateTableData, 1000)
  177. /**
  178. * @description 按条件查询,如果开启了分页查询,那么会直接重新查询数据,否则,会根据现有数据进行查询
  179. */
  180. const queryTableData = () => {
  181. if (props.openRemoteQuery && props.openRemoteReqData && props.requestConfig) {
  182. reqConfig.otherOptions = { ...reqConfig.otherOptions, ...queryFormData.value }
  183. // 需要在查询前清除掉目前的数据,不然会导致之前缓存的数据混入
  184. // 比如第一页已经缓存了,在第二页重新查询,在切回第一页,还是显示查询前的数据,因为缓存没被清除
  185. tableData.splice(0, tableData.length)
  186. updateTableData()
  187. console.log(reqConfig.otherOptions)
  188. } else {
  189. let filteredTable: any[]
  190. // 过滤出来所有符合formData数据的条件
  191. if (props.dataList) {
  192. filteredTable = props.dataList.filter((item) => {
  193. let state = true
  194. for (let [k, v] of Object.entries(queryFormData.value)) {
  195. // 模糊查询,看值是否跟表格中的数据匹配
  196. if (!fuzzySearch(v, item[k])) {
  197. state = false
  198. break
  199. }
  200. }
  201. return state
  202. })
  203. paginationConfig.total = filteredTable.length
  204. tableData.splice(0, tableData.length, ...filteredTable)
  205. } else {
  206. console.error('没有数据源')
  207. }
  208. }
  209. }
  210. // 把查询方法包装一下,节流
  211. const throttleQueryTableData = throttleFunc(queryTableData, throttleTime)
  212. /**
  213. * @description: 单独处理拥有均值行的表格每个单元格的样式,均值字段均加粗,其他需要比较的字段根据自身百分比显示颜色
  214. * 其中使用row-style无效,scope会导致无法覆盖样式
  215. * 同时由于自定义了表格内容,哪里的样式会覆盖row的样式,所以只能单独对单元格设置
  216. * @param {*} info 每个单元格的信息
  217. */
  218. const tableCellStyle = (info: any) => {
  219. if (info.row.date === '均值')
  220. return {
  221. 'font-weight': 'bold'
  222. }
  223. else if (info.column.property != 'count' && info.column.property != 'date' && props.needAverage) {
  224. return {
  225. 'background-color': `rgba(59, 157, 247,${getDecimalFromRange(info.row[info.column.property])})`
  226. }
  227. } else return {}
  228. }
  229. /**
  230. * 监听limit的变化,改变后将页码置为1,同时去重新请求数据
  231. */
  232. const watchLimit = watch(
  233. () => paginationConfig.limit,
  234. (newLimit, oldLimit) => {
  235. if (newLimit !== oldLimit) {
  236. paginationConfig.currentPage = 1
  237. if (props.openFilterQuery) {
  238. filterFormRef.value?.throttleResetQuery()
  239. } else {
  240. throttleQueryTableData()
  241. }
  242. }
  243. },
  244. { deep: true }
  245. )
  246. /**
  247. * 监听currentPage的变化,如果开启了分页查询,并且当前页发生变化,并且当前页的数据不存在,则重新请求数据
  248. */
  249. const watchCurPage = watch(
  250. () => paginationConfig.currentPage,
  251. (newPage, oldPage) => {
  252. if (newPage !== oldPage && !tableData[newPage]) {
  253. updateTableData()
  254. }
  255. },
  256. {
  257. deep: true
  258. }
  259. )
  260. // 如果没有开启分页查询,直接关闭这两个监听
  261. if (!props.openPageQuery) {
  262. watchLimit()
  263. watchCurPage()
  264. }
  265. // 监听传入的datalist的变化,然后去更新数据
  266. const changeDataList = watch(
  267. () => [props.dataList],
  268. () => {
  269. updateTableData()
  270. },
  271. {
  272. deep: true
  273. }
  274. )
  275. /**
  276. * 对传入的props进行检查,对错误配置进行提示
  277. */
  278. const checkPropsConfig = () => {
  279. const {
  280. openFilterQuery,
  281. queryInfo,
  282. openPageQuery,
  283. paginationConfig,
  284. openRemoteReqData,
  285. requestConfig,
  286. openRemoteQuery,
  287. dataList
  288. } = props
  289. if (openFilterQuery && !queryInfo) {
  290. console.error('请输入查询的配置信息')
  291. }
  292. if (openPageQuery && !paginationConfig) {
  293. console.error('请输入分页配置信息')
  294. }
  295. if (openRemoteReqData || openRemoteQuery) {
  296. if (!requestConfig) {
  297. console.error('请输入请求配置信息')
  298. }
  299. }
  300. if (!openRemoteReqData) {
  301. if (!dataList) {
  302. console.error('请至少确保一个数据源')
  303. }
  304. if (openRemoteQuery) {
  305. console.error('远程查询无效,请开启数据远程请求')
  306. }
  307. }
  308. }
  309. /**
  310. * 监听请求配置的变化,如果开启了查询功能,则需要重置表单后查询
  311. * 否则直接请求数据
  312. */
  313. const watchReqConfig = watch(
  314. () => props.requestConfig,
  315. () => {
  316. Object.assign(reqConfig, props.requestConfig)
  317. if (props.openFilterQuery) {
  318. filterFormRef.value?.throttleResetQuery()
  319. } else {
  320. throttleQueryTableData()
  321. }
  322. },
  323. {
  324. deep: true
  325. }
  326. )
  327. /**
  328. * 不使用远程数据,则不用监听请求数据的变化
  329. */
  330. if (!props.openRemoteReqData) {
  331. watchReqConfig()
  332. }
  333. // 如果是使用远程数据源,则取消监听
  334. if (props.openRemoteReqData) {
  335. changeDataList()
  336. }
  337. /**
  338. * @description: 表格排序
  339. * @param {*} data 获取到的数据
  340. */
  341. const tableSortChange = (data: { column: any; prop: string; order: any }) => {
  342. filterFormRef.value?.resetFormData()
  343. let { order } = { ...data }
  344. if (order === 'ascending') order = 'asc'
  345. else if (order === 'descending') order = 'desc'
  346. else order = ''
  347. reqConfig.otherOptions.order = order
  348. throttleQueryTableData()
  349. }
  350. /**
  351. * 删除行
  352. * @param url 请求地址
  353. * @param fieldsInfo 行数据
  354. */
  355. const deleteRow = (url: string, fieldsInfo: any) => {
  356. axiosInstance
  357. .post(url, { ...fieldsInfo })
  358. .then((data) => {
  359. analysisResCode(data).then(() => {
  360. if (props.openFilterQuery) {
  361. filterFormRef.value?.throttleResetQuery()
  362. } else {
  363. throttleQueryTableData()
  364. }
  365. })
  366. })
  367. .catch((err) => {
  368. console.log(err)
  369. })
  370. }
  371. /**
  372. * @description: 外部获取数据
  373. */
  374. const outGetTableData = () => {
  375. return toRaw(tableData).flat()
  376. }
  377. const getTotal = () => {
  378. if (!props.needTotal || !props.totalFunc) {
  379. return []
  380. }
  381. return props.totalFunc(tableData, paginationConfig.total)
  382. }
  383. const getFormQueryData = (): { [p: string]: any } => {
  384. return markRaw(queryFormData.value)
  385. }
  386. // 定义暴露出去的方法
  387. defineExpose({
  388. updateTableData,
  389. resetTableData,
  390. deleteRow,
  391. downLoadTable,
  392. outGetTableData,
  393. getFormQueryData
  394. })
  395. onMounted(() => {
  396. initPageConfig(props.paginationConfig)
  397. initReqConfig(reqConfig, props.requestConfig)
  398. checkPropsConfig()
  399. nextTick(() => {
  400. // changeTableFooterPos()
  401. })
  402. })
  403. const expandRowKeys = ref<string[]>([])
  404. const getRowKey = (row: any) => {
  405. const id = row['actionId'] ?? row['id']
  406. if (!id) {
  407. console.warn('请检查表格数据,没有可用的ID 作为RowKey,当前使用随机key')
  408. return createRowKey()
  409. }
  410. return id + ''
  411. }
  412. const handleExpand = async (row: any, expandedRows: any[]) => {
  413. if (!props.expandConfig) return
  414. let id = row['actionId'] ?? row['id']
  415. if (!id) {
  416. console.warn('请检查表格数据,没有可用的ID 作为RowKey,当前使用随机key')
  417. id = createRowKey()
  418. }
  419. // expandRowKeys.value.push(id)
  420. if (expandedRows.length) {
  421. //展开
  422. expandRowKeys.value = [] //先干掉之前展开的行
  423. if (row) {
  424. expandRowKeys.value.push(id) //push新的行 (原理有点类似防抖)
  425. }
  426. } else {
  427. expandRowKeys.value = [] //折叠 就清空expand-row-keys对应的数组
  428. }
  429. activeExpandTablePageConfig.value = id
  430. if (!expandPaginationConfig[id]) {
  431. expandPaginationConfig[id] = {
  432. currentPage: 1,
  433. limit: 10,
  434. total: 0,
  435. pageSizeList: [10, 20, 30]
  436. }
  437. }
  438. // 有数据后就不要重新请求数据
  439. // 这里只判断是否已经请求过了,而不判断是否有数据,防止重复请求
  440. if (expandTableData[id] !== undefined) return
  441. const params = {
  442. ...props.expandConfig.expandReqConfig.otherOptions,
  443. actionId: id + ''
  444. }
  445. const res = (await axiosInstance.post(
  446. props.expandConfig.expandReqConfig.url,
  447. params
  448. )) as ResponseInfo
  449. if (res.code !== 0) {
  450. ElMessage.error('获取展开信息失败')
  451. return
  452. }
  453. expandTableData[id] = res.data
  454. expandPaginationConfig[id].total = res.data.length
  455. }
  456. const handleExpandPageChange = (page: number) => {
  457. const config = expandPaginationConfig[activeExpandTablePageConfig.value]
  458. config.currentPage = page
  459. }
  460. const handleExpandSizeChange = (size: number) => {
  461. const config = expandPaginationConfig[activeExpandTablePageConfig.value]
  462. config.currentPage = 1
  463. config.limit = size
  464. }
  465. const handleRowClass = (row: any, _rowIndex: number): string => {
  466. const hasOptions = row.row.haveOption
  467. return hasOptions ? '' : 'noneExpandIcon'
  468. }
  469. </script>
  470. <template>
  471. <div class="tableContent">
  472. <div class="filterBox" v-if="openFilterQuery && queryInfo">
  473. <div class="filterHeader">
  474. <span>查询条件</span>
  475. </div>
  476. <div class="filterBody">
  477. <TableFilterForm
  478. v-model:query-form-data="queryFormData"
  479. :queryInfo="queryInfo"
  480. @query="throttleQueryTableData"
  481. ref="filterFormRef"
  482. ></TableFilterForm>
  483. </div>
  484. </div>
  485. <!-- <div class="chartContainer" v-if="needChart && props.chartOptions">-->
  486. <!-- <PieBorderRadius :options="props.chartOptions"></PieBorderRadius>-->
  487. <!-- </div>-->
  488. <slot name="chart" v-if="$slots.chart"></slot>
  489. <div class="tableTools">
  490. <TableTools
  491. :table-fields-info="props.tableFieldsInfo"
  492. :tools-config="props.tools"
  493. @add="emits('addNewItem')"
  494. @download="downLoadTable(props.tools?.headerMap)"
  495. @refresh="throttleGetData"
  496. ></TableTools>
  497. </div>
  498. <div class="tableBox">
  499. <p class="totalRow" v-if="props.needTotal">
  500. <span class="totalItemLabel totalItem"> 总计 </span>
  501. <span class="totalItem" :key="'totalKey' + item" v-for="item in getTotal()">
  502. {{ item }}
  503. </span>
  504. </p>
  505. <!-- 没有分页的时候需要重新计算一下data -->
  506. <!-- :show-summary="props.needTotal"-->
  507. <!-- :summary-method="-->
  508. <!-- () => {-->
  509. <!-- if (props.totalFunc) {-->
  510. <!-- return props.totalFunc(tableData, paginationConfig.total)-->
  511. <!-- }-->
  512. <!-- return [] "-->
  513. <!-- }-->
  514. <el-table
  515. :data="
  516. openRemoteReqData && openRemoteQuery
  517. ? tableData[paginationConfig.currentPage]
  518. : localTableData
  519. "
  520. style="width: 100%"
  521. class="tableBody"
  522. :cell-style="tableCellStyle"
  523. v-loading="openRemoteReqData ? loading : props.loadingState"
  524. :row-key="getRowKey"
  525. :expand-row-keys="expandRowKeys"
  526. @sort-change="tableSortChange"
  527. @query="throttleGetData"
  528. @expand-change="handleExpand"
  529. table-layout="auto"
  530. :row-class-name="handleRowClass"
  531. >
  532. <el-table-column
  533. v-if="props.needRowindex"
  534. align="center"
  535. label="#"
  536. type="index"
  537. :index="computedRowIndex"
  538. />
  539. <el-table-column align="center" show-overflow-tooltip type="expand" v-if="props.needExpand">
  540. <template #default="rowInfo">
  541. <el-table :data="expandPageData">
  542. <template v-for="child in props.expandConfig?.expandField" :key="child.name">
  543. <el-table-column
  544. :prop="child.name"
  545. :label="child.cnName"
  546. align="center"
  547. show-overflow-tooltip
  548. v-if="child.isShow"
  549. :sortable="child.needSort ? 'custom' : false"
  550. >
  551. <template v-slot="scope">
  552. <TableColumn
  553. :column-config="child"
  554. :row="scope.row"
  555. :need-average="props.needAverage"
  556. ></TableColumn>
  557. </template>
  558. <!-- {{ expandTableData[rowInfo.row.actionId] }}-->
  559. <!-- <TableColumn-->
  560. <!-- :column-config="child"-->
  561. <!-- :row="rowInfo.row"-->
  562. <!-- :need-average="rowInfo.needAverage"-->
  563. <!-- ></TableColumn>-->
  564. </el-table-column>
  565. </template>
  566. </el-table>
  567. <div class="expandPageConfig">
  568. <el-pagination
  569. class="userTablePagination"
  570. background
  571. :page-size="expandPaginationConfig[rowInfo.row.actionId].limit"
  572. :page-sizes="expandPaginationConfig[rowInfo.row.actionId].pageSizeList"
  573. table-layout="fixed"
  574. layout="prev, pager, next ,jumper ,sizes,total,"
  575. :total="expandPaginationConfig[rowInfo.row.actionId].total"
  576. :current-page="expandPaginationConfig[rowInfo.row.actionId].currentPage"
  577. @current-change="handleExpandPageChange"
  578. @size-change="handleExpandSizeChange"
  579. />
  580. </div>
  581. </template>
  582. </el-table-column>
  583. <template v-for="item in tableFieldsInfo" :key="item.name">
  584. <el-table-column
  585. :prop="item.name"
  586. :label="item.cnName"
  587. :min-width="item.specialEffect?.type === FieldSpecialEffectType.DROPDOWN ? '170px' : ''"
  588. align="center"
  589. show-overflow-tooltip
  590. v-if="item.isShow"
  591. :sortable="item.needSort ? 'custom' : false"
  592. >
  593. <template v-slot="scope">
  594. <TableColumn
  595. :column-config="item"
  596. :row="scope.row"
  597. :need-average="props.needAverage"
  598. ></TableColumn>
  599. </template>
  600. </el-table-column>
  601. </template>
  602. <slot name="tableOperation"></slot>
  603. </el-table>
  604. <div class="userTablePaginationBox" v-if="openPageQuery">
  605. <el-pagination
  606. class="userTablePagination"
  607. background
  608. :page-size="paginationConfig.limit"
  609. :page-sizes="paginationConfig.pageSizeList"
  610. table-layout="fixed"
  611. layout="prev, pager, next ,jumper ,sizes,total,"
  612. :total="paginationConfig.total"
  613. :current-page="paginationConfig.currentPage"
  614. @current-change="handleCurrentChange"
  615. @size-change="handleSizeChange"
  616. />
  617. </div>
  618. </div>
  619. </div>
  620. </template>
  621. <style scoped>
  622. .tableContent {
  623. margin: 10px auto 20px;
  624. width: 100%;
  625. box-shadow:
  626. 0 4px 8px 0 rgba(0, 0, 0, 0.02),
  627. 0 1px 3px 0 rgba(0, 0, 0, 0.02);
  628. }
  629. .filterBox,
  630. .tableBox {
  631. width: 100%;
  632. }
  633. .filterBox {
  634. margin-top: 1%;
  635. min-height: 18%;
  636. display: flex;
  637. flex-direction: column;
  638. }
  639. .filterHeader,
  640. .filterBody {
  641. width: 98%;
  642. box-sizing: border-box;
  643. margin: 10px auto;
  644. }
  645. .filterHeader {
  646. display: flex;
  647. align-items: center;
  648. color: black;
  649. font-size: 16px;
  650. font-weight: bold;
  651. }
  652. .filterBody {
  653. display: flex;
  654. padding: 0 24px;
  655. }
  656. .queryBox {
  657. width: 10%;
  658. display: flex;
  659. justify-content: space-around;
  660. }
  661. .queryBtnBox {
  662. width: 100%;
  663. display: flex;
  664. flex-direction: column;
  665. align-items: center;
  666. justify-content: center;
  667. }
  668. .refreshBtn {
  669. margin-top: 10%;
  670. margin-bottom: 10%;
  671. }
  672. .queryPartition {
  673. height: 90%;
  674. }
  675. .queryForm {
  676. width: 90%;
  677. display: flex;
  678. flex-wrap: wrap;
  679. }
  680. .filterItem {
  681. /*width: 20%;*/
  682. display: flex;
  683. align-items: center;
  684. }
  685. .selectLabelContainer,
  686. .selectSupplement {
  687. display: flex;
  688. align-items: center;
  689. }
  690. .selectSupplement {
  691. margin-left: 5px;
  692. }
  693. .leftTools,
  694. .rightTools {
  695. width: 10%;
  696. display: flex;
  697. align-items: center;
  698. justify-content: space-between;
  699. }
  700. .rightTools {
  701. width: 5%;
  702. }
  703. .tableBox {
  704. width: 98%;
  705. margin: 5px auto;
  706. box-shadow:
  707. 0 4px 8px 0 rgba(0, 0, 0, 0.02),
  708. 0 1px 3px 0 rgba(0, 0, 0, 0.02);
  709. }
  710. .tableBody {
  711. box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.1);
  712. }
  713. .userTablePaginationBox {
  714. box-sizing: border-box;
  715. width: 98%;
  716. margin: 0 auto;
  717. padding: 1% 0;
  718. display: flex;
  719. justify-content: center;
  720. }
  721. .expandPageConfig {
  722. /*width: 98%;*/
  723. /*height: 600px;*/
  724. box-sizing: border-box;
  725. width: 98%;
  726. margin: 0 auto;
  727. padding: 1% 0;
  728. display: flex;
  729. justify-content: center;
  730. }
  731. .leftToolBtn {
  732. margin-right: 5px;
  733. }
  734. .totalRow {
  735. padding: 10px 0px;
  736. display: flex;
  737. /*justify-content: space-between;*/
  738. }
  739. .totalRow > .totalItemLabel {
  740. width: 60px;
  741. font-weight: bold;
  742. }
  743. .totalItem {
  744. width: 130px;
  745. margin-right: 15px;
  746. text-align: center;
  747. }
  748. </style>