Table.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. <!--
  2. * @Author: fxs bjnsfxs@163.com
  3. * @Date: 2024-08-20 18:16:18
  4. * @LastEditors: fxs bjnsfxs@163.com
  5. * @LastEditTime: 2024-09-18 12:00:45
  6. * @FilePath: \Game-Backstage-Management-System\src\components\Table.vue
  7. * @Description:
  8. *
  9. -->
  10. <script setup lang="ts">
  11. import type { PropsParams, TablePaginationSetting } from '@/types/table'
  12. import type { ReqConfig } from '@/types/dataAnalysis'
  13. import { FilterType, FieldSpecialEffectType } from '@/types/table'
  14. import { initLoadResouce } from '@/utils/resource'
  15. import { fuzzySearch } from '@/utils/common'
  16. import { computed, onMounted, reactive, ref, toRaw, watch } from 'vue'
  17. import { useTable } from '@/hooks/useTable'
  18. import FilterPopover from './toolsBtn/FilterPopover.vue'
  19. import RegreshBtn from './toolsBtn/RegreshBtn.vue'
  20. import { useRequest } from '@/hooks/useRequest'
  21. import type { FormInstance } from 'element-plus'
  22. import axiosInstance from '@/utils/axios/axiosInstance'
  23. const { analysisResCode } = useRequest()
  24. // 表格工具图标大小
  25. const toolsIconSize = ref(25)
  26. // 查询表单
  27. const queryFormRef = ref<FormInstance>()
  28. // 传过来的配置
  29. const props = withDefaults(defineProps<PropsParams>(), {
  30. needRowindex: true,
  31. needAverage: false,
  32. needLeftTools: false,
  33. needRightTools: false,
  34. openFilterQuery: false,
  35. openPageQuery: false,
  36. needUpload: false,
  37. needDownLoad: false
  38. })
  39. // 父组件触发的方法
  40. // 删除了一个事件触发,loadSuccess
  41. const emits = defineEmits(['addNewItem', 'upload', 'downLoad'])
  42. // 加载动画
  43. const loading = ref(false)
  44. // 表格数据
  45. const tableData: Array<any> = reactive([])
  46. // 备份表格数据,用于在不分页查询的时候,恢复数据
  47. const backupTableData: Array<any> = []
  48. // 查询表单的数据
  49. const queryFormData = reactive<{ [key: string]: any }>({})
  50. const backupQueryFormData = reactive<{ [key: string]: any }>({})
  51. // 分页数据
  52. const paginationConfig2 = reactive<TablePaginationSetting>({
  53. currentPage: 0,
  54. limit: 0,
  55. total: 0,
  56. pagesizeList: []
  57. })
  58. // 请求配置
  59. const reqconfig = reactive<ReqConfig>({
  60. url: '',
  61. otherOptions: {}
  62. })
  63. // 资源的加载路径
  64. const resourceInfo: Record<string, string> = {
  65. defaultHead: `/img/default/defaultHead.png`
  66. }
  67. // 使用blob的资源路径信息
  68. const blobUrlInfo = reactive<Record<string, string>>({})
  69. // 一些公用方法
  70. const { getTableData } = useTable(tableData, paginationConfig2)
  71. // 没有开启分页查询的时候使用的数据
  72. const tableDataNoPaging = computed(() => {
  73. let curPage = paginationConfig2.currentPage
  74. let limit = paginationConfig2.limit
  75. let begin = curPage * limit - limit
  76. //这里不减一是因为,slice方法裁切是左闭右开数组
  77. let end = curPage * limit
  78. return tableData.slice(begin, end)
  79. })
  80. // 所有类型为input的表单控件信息
  81. const inputFieldsList = computed(() => {
  82. return props.queryInfo?.filter((item) => item.type === FilterType.INPUT)
  83. })
  84. // 所有类型为select的表单控件信息
  85. const selectFieldsList = computed(() => {
  86. return props.queryInfo?.filter((item) => {
  87. return item.type === FilterType.SELECT
  88. })
  89. })
  90. // 所有类型为date的表单控件信息
  91. const dateFieldsList = computed(() => {
  92. return props.queryInfo?.filter((item) => item.type === FilterType.DATE)
  93. })
  94. // 计算行号
  95. const computedRowIndex = (index: number) => {
  96. return (paginationConfig2.currentPage - 1) * paginationConfig2.limit + index + 1
  97. }
  98. // 改变页码
  99. const handleCurrentChange = (val: number) => {
  100. paginationConfig2.currentPage = val
  101. }
  102. // 改变每页大小
  103. const handleSizeChange = (val: number) => {
  104. paginationConfig2.limit = val
  105. }
  106. /**
  107. * @description: 获取数据,如果没有直接传入数据,则去请求数据,有则直接用
  108. * @return {*}
  109. */
  110. const getData = () => {
  111. return new Promise(async (resolve, reject) => {
  112. try {
  113. Object.assign(queryFormData, JSON.parse(JSON.stringify(backupQueryFormData)))
  114. const loadTableData = async () => {
  115. return new Promise((resolve, reject) => {
  116. if (props.dataList) {
  117. tableData.splice(0, tableData.length, ...props.dataList)
  118. paginationConfig2.total = props.paginationConfig.total
  119. loading.value = false
  120. // emits('loadSuccess', tableData)
  121. resolve(true)
  122. } else {
  123. loading.value = true
  124. if (props.requestConfig) {
  125. if (props.openPageQuery) {
  126. // 如果开启了分页查询,那么要计算出需要展示的页码位置所对应的偏移量
  127. // 同时要将查询的条数改为对应的用户选择的展示条数
  128. reqconfig.otherOptions.offset =
  129. (paginationConfig2.currentPage - 1) * paginationConfig2.limit
  130. reqconfig.otherOptions.limit = paginationConfig2.limit
  131. }
  132. // 查询时要根据是否开启分页查询传入对应参数
  133. getTableData(reqconfig.url, reqconfig.otherOptions, props.openPageQuery)
  134. .then(() => {
  135. // emits('loadSuccess', tableData)
  136. backupTableData.splice(0, backupTableData.length, ...tableData)
  137. resolve(true)
  138. })
  139. .catch((err) => {
  140. console.log(err)
  141. reject(err)
  142. })
  143. .finally(() => {
  144. loading.value = false
  145. })
  146. } else {
  147. loading.value = false
  148. throw new Error('no match requestConfig')
  149. }
  150. }
  151. })
  152. }
  153. // 等待数据加载完成
  154. await loadTableData()
  155. .then(async () => {
  156. if (props.needAverage) {
  157. let rowData: any = {}
  158. let oldList: Array<any> = JSON.parse(JSON.stringify(tableData))
  159. Object.values(props.tableFieldsInfo).map((item, index) => {
  160. let sum = oldList
  161. .map((item) => item.count)
  162. .reduce((accumulator, currentValue) => accumulator + currentValue, 0)
  163. let averageList = oldList
  164. .map((val) => val[item.name])
  165. .filter((item) => item !== undefined)
  166. if (index === 0) rowData[item.name] = '均值'
  167. else if (item.name === 'count') rowData[item.name] = sum
  168. else {
  169. let num =
  170. averageList.reduce((accumulator, currentValue) => accumulator + currentValue, 0) /
  171. averageList.length
  172. rowData[item.name] = isNaN(num) ? 0 : num.toFixed(2)
  173. }
  174. })
  175. insertRow(0, rowData)
  176. }
  177. resolve(true)
  178. })
  179. .catch((err) => {
  180. console.log(err)
  181. reject(err)
  182. })
  183. } catch (err) {
  184. console.log(err)
  185. reject(err)
  186. }
  187. })
  188. }
  189. /**
  190. * @description: 清空表格数据
  191. * @return {*}
  192. */
  193. const resetTableData = () => {
  194. tableData.splice(0, tableData.length)
  195. }
  196. /**
  197. * @description: 按条件查询,如果开启了分页查询,那么会直接重新查询数据,否则,会根据现有数据进行查询
  198. * @return {*}
  199. */
  200. const queryTableData = () => {
  201. if (props.requestConfig) {
  202. reqconfig.otherOptions = { ...props.requestConfig.otherOptions, ...queryFormData }
  203. }
  204. if (props.openPageQuery) getData()
  205. else {
  206. let filteredTable = []
  207. // 过滤出来所有符合formData数据的条件
  208. filteredTable = backupTableData.filter((item) => {
  209. let state = true
  210. for (let [k, v] of Object.entries(queryFormData)) {
  211. // 模糊查询,看值是否跟表格中的数据匹配
  212. if (!fuzzySearch(v, item[k])) {
  213. state = false
  214. break
  215. }
  216. }
  217. return state
  218. })
  219. tableData.splice(0, tableData.length, ...filteredTable)
  220. }
  221. }
  222. /**
  223. * @description: 重置整个查询表单,重置后,再请求一次全部表格
  224. * @param {*} formEl 表单对象
  225. * @return {*}
  226. */
  227. const resetQueryForm = (formEl: FormInstance | undefined) => {
  228. if (!formEl) return
  229. // clearReactiveData(queryFormData)
  230. // queryFormData
  231. Object.assign(queryFormData, JSON.parse(JSON.stringify(backupQueryFormData)))
  232. queryTableData()
  233. }
  234. /**
  235. * @description: 在获取完数据后,插入均值行
  236. * @param {*} start 插入的位置
  237. * @param {*} rowData 插入的数据
  238. * @return {*}
  239. */
  240. const insertRow = (start: number, rowData: any) => {
  241. if (props.openPageQuery) {
  242. tableData[start].splice(0, 0, rowData)
  243. } else {
  244. tableData.splice(start, 0, rowData)
  245. }
  246. }
  247. /**
  248. * @description: 根据计算出来的值去返回对应的颜色深度
  249. * @return {*}
  250. */
  251. const getDecimalFromRange = (number: number) => {
  252. if (number === null || number === undefined) return 0
  253. if (number < 25) return 0.25
  254. else if (number < 50) return 0.5
  255. else if (number < 75) return 0.75
  256. else return 1.0 // 如果number >= 75,则直接返回1.00
  257. }
  258. /**
  259. * @description: 单独处理拥有均值行的表格每个单元格的样式,均值字段均加粗,其他需要比较的字段根据自身百分比显示颜色
  260. * 其中使用row-style无效,scope会导致无法覆盖样式
  261. * 同时由于我自定义了表格内容,哪里的样式会覆盖row的样式,所以只能单独对单元格设置
  262. * @param {*} info 每个单元格的信息
  263. * @return {*}
  264. */
  265. const tableCellStyle = (info: any) => {
  266. if (info.row.date === '均值')
  267. return {
  268. 'font-weight': 'bold'
  269. }
  270. else if (info.column.property != 'count' && info.column.property != 'date' && props.needAverage) {
  271. return {
  272. 'background-color': `rgba(59, 157, 247,${getDecimalFromRange(info.row[info.column.property])})`
  273. }
  274. } else return {}
  275. }
  276. /**
  277. * @description: 监听litmit,currentpage的变化,改变后去重新请求数据
  278. * 如果是limit的变化,则需要把当前页置为1
  279. *
  280. * 对于Gid需要去监听props的,而不是本地的,因为是外部的改变
  281. * @return {*}
  282. */
  283. const changePageLimit = watch(
  284. () => [paginationConfig2.limit, paginationConfig2.currentPage],
  285. ([newLimit, newCurPage], [oldLimit, oldCruPage]) => {
  286. if (newLimit != oldLimit) {
  287. // 需要给分页按钮加上:current-page.sync="current_page" 配置,不然不生效
  288. // 当改变每页大小时把之前的缓存全部清除,重新开始
  289. paginationConfig2.currentPage = 1
  290. // resetTableData()
  291. }
  292. if (newCurPage != oldCruPage) paginationConfig2.currentPage = newCurPage
  293. // if (newGid != oldGid) reqconfig.otherOptions.gid = newGid
  294. // || newGid != oldGid
  295. if (newLimit != oldLimit || !tableData[paginationConfig2.currentPage]) {
  296. getData()
  297. }
  298. },
  299. { deep: true }
  300. )
  301. /**
  302. * @description: 监听gid的变化,重新请求数据,这里很奇怪,跟上面的limit和page放到一起不起作用
  303. * @return {*}
  304. */
  305. watch(
  306. () => props.requestConfig?.otherOptions.gid,
  307. (newGid, oldGid) => {
  308. if (newGid != oldGid) {
  309. reqconfig.otherOptions.gid = newGid
  310. getData()
  311. }
  312. }
  313. )
  314. // 监听传入的datalist的变化,然后去更新数据
  315. const changeDataList = watch(
  316. () => [props.dataList],
  317. () => {
  318. getData()
  319. },
  320. {
  321. deep: true
  322. }
  323. )
  324. // 监听日期的变化,
  325. const watchDateChange = watch(
  326. () => [props.requestConfig?.otherOptions.startTime, props.requestConfig?.otherOptions.endTime],
  327. () => {
  328. getData()
  329. },
  330. { deep: true }
  331. )
  332. /**
  333. * @description: 创建row-key优化表格性能
  334. * @return {*}
  335. */
  336. const createRowKey = () => {
  337. return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
  338. }
  339. //如果没有日期就取消掉
  340. if (!props.requestConfig?.otherOptions.startTime && !props.requestConfig?.otherOptions.endTime) {
  341. watchDateChange()
  342. }
  343. // 没传入datalist则取消该监听
  344. if (!props.dataList) {
  345. changeDataList()
  346. }
  347. // 没有开启分页查询就关闭掉这个监听
  348. if (!props.openPageQuery) {
  349. changePageLimit()
  350. }
  351. /**
  352. * @description: 拷贝一份配置文件
  353. * @return {*}
  354. */
  355. const initpageConfig = () => {
  356. Object.assign(paginationConfig2, props.paginationConfig)
  357. }
  358. /**
  359. * @description: 初始化请求配置,用于把拷贝一份新的数据
  360. * @return {*}
  361. */
  362. const initReqConfig = () => {
  363. Object.assign(reqconfig, props.requestConfig)
  364. }
  365. /**
  366. * @description: 初始化查询框的数据
  367. * @return {*}
  368. */
  369. const initFormData = () => {
  370. props.queryInfo?.map((item: any) => {
  371. queryFormData[item.name] = item.default
  372. })
  373. // backupQueryFormData = JSON.parse(JSON.stringify(queryFormData))
  374. Object.assign(backupQueryFormData, JSON.parse(JSON.stringify(queryFormData)))
  375. }
  376. /**
  377. * @description: 表格排序
  378. * @param {*} data 获取到的数据
  379. * @return {*}
  380. */
  381. const tableSortChange = (data: { column: any; prop: string; order: any }) => {
  382. let { order } = { ...data }
  383. if (order === 'ascending') order = 'asc'
  384. else if (order === 'descending') order = 'desc'
  385. else order = ''
  386. reqconfig.otherOptions.order = order
  387. getData()
  388. }
  389. /**
  390. * @description: 删除行
  391. * @param {*} url 请求地址
  392. * @param {*} row 行数据
  393. * @return {*}
  394. */
  395. const deleteRow = (url: string, filedsInfo: any) => {
  396. axiosInstance
  397. .post(url, { ...filedsInfo })
  398. .then((data) => {
  399. analysisResCode(data).then(() => {
  400. getData()
  401. })
  402. })
  403. .catch((err) => {
  404. console.log(err)
  405. })
  406. }
  407. /**
  408. * @description: 下载表格数据
  409. * @return {*}
  410. */
  411. const downLoadTable = () => {
  412. emits('downLoad', JSON.parse(JSON.stringify(tableData)))
  413. }
  414. /**
  415. * @description: 外部获取数据
  416. * @return {*}
  417. */
  418. const outGetTableData = () => {
  419. return toRaw(tableData).flat()
  420. }
  421. // 定义暴露出去的方法
  422. defineExpose({
  423. getData,
  424. resetTableData,
  425. deleteRow,
  426. downLoadTable,
  427. outGetTableData
  428. })
  429. onMounted(() => {
  430. initpageConfig()
  431. initReqConfig()
  432. initFormData()
  433. if (props.loadingState !== undefined) {
  434. loading.value = props.loadingState
  435. }
  436. // if (!props.openPageQuery) {
  437. // getData()
  438. // }
  439. // 去加载所有需要的资源
  440. initLoadResouce(resourceInfo).then((data) => {
  441. Object.assign(blobUrlInfo, data)
  442. })
  443. })
  444. </script>
  445. <template>
  446. <div class="tableContent">
  447. <div class="filterBox" v-if="openFilterQuery">
  448. <!-- slot -->
  449. <div class="filterHeader">
  450. <span>查询条件</span>
  451. </div>
  452. <div class="filterBody">
  453. <el-form
  454. :inline="true"
  455. ref="queryFormRef"
  456. :model="queryFormData"
  457. class="queryForm"
  458. :label-position="'left'"
  459. >
  460. <!-- 所有的input查询框 -->
  461. <el-form-item :label="item.label" v-for="item in inputFieldsList" class="filterItem">
  462. <el-input
  463. v-model="queryFormData[item.name]"
  464. :placeholder="item.placeholder"
  465. clearable
  466. />
  467. </el-form-item>
  468. <!-- 所有选择框 -->
  469. <!-- <el-config-provider :value-on-clear="null" :empty-values="[undefined, null]"> -->
  470. <el-form-item :label="item.label" v-for="item in selectFieldsList" class="filterItem">
  471. <el-select
  472. :empty-values="[undefined, null]"
  473. v-model="queryFormData[item.name]"
  474. :placeholder="item.placeholder"
  475. :value-key="item.name"
  476. >
  477. <el-option v-for="val in item.otherOption" :label="val.cnName" :value="val.value" />
  478. </el-select>
  479. </el-form-item>
  480. <!-- </el-config-provider> -->
  481. <!-- 所有日期选择框 -->
  482. <el-form-item :label="item.label" v-for="item in dateFieldsList" class="filterItem">
  483. <el-date-picker
  484. v-model="queryFormData[item.name]"
  485. type="date"
  486. :placeholder="item.placeholder"
  487. clearable
  488. />
  489. </el-form-item>
  490. </el-form>
  491. <!-- 分割线 -->
  492. <!-- <el-divider class="queryPartition" content-position="center" direction="vertical" /> -->
  493. <div class="queryBox">
  494. <el-divider class="queryPartition" content-position="center" direction="vertical" />
  495. <div class="queryBtnBox">
  496. <el-button class="queryBtn" color="#165dff" @click="queryTableData">
  497. <el-icon><Search /></el-icon>查询
  498. </el-button>
  499. <el-button class="refreshBtn" color="#f2f3f5" @click="resetQueryForm(queryFormRef)">
  500. <el-icon><RefreshRight /></el-icon>重置
  501. </el-button>
  502. </div>
  503. </div>
  504. </div>
  505. </div>
  506. <!-- 分割线 -->
  507. <!-- <el-divider class="partition" content-position="center" /> -->
  508. <div class="tableTools">
  509. <div class="leftTools">
  510. <div class="leftToolsGroup" v-if="needLeftTools" style="display: flex">
  511. <el-button class="leftToolBtn" color="#165dff" @click="emits('addNewItem')">
  512. <el-icon><Plus /></el-icon>新增
  513. </el-button>
  514. <el-button
  515. class="leftToolBtn"
  516. color="#626aef"
  517. @click="emits('upload', outGetTableData())"
  518. v-if="needUpload"
  519. >
  520. <el-icon><Upload /></el-icon>上传
  521. </el-button>
  522. </div>
  523. </div>
  524. <div class="rightTools" v-if="needRightTools">
  525. <el-button
  526. v-if="needDownload"
  527. color="#f0f1f3"
  528. size="default"
  529. class="rightToolsItem"
  530. @click="downLoadTable"
  531. >
  532. <el-icon><Download /></el-icon>下载
  533. </el-button>
  534. <RegreshBtn @refresh-table="getData" :icon-size="toolsIconSize"></RegreshBtn>
  535. <FilterPopover
  536. :table-fields-info="tableFieldsInfo"
  537. :icon-size="toolsIconSize"
  538. ></FilterPopover>
  539. </div>
  540. </div>
  541. <div class="tableBox">
  542. <!-- 没有分页的时候需要重新计算一下data -->
  543. <el-table
  544. :data="openPageQuery ? tableData[paginationConfig2.currentPage] : tableDataNoPaging"
  545. style="width: 100%"
  546. class="tableBody"
  547. :cell-style="tableCellStyle"
  548. v-loading="loading"
  549. :row-key="createRowKey()"
  550. @sort-change="tableSortChange"
  551. >
  552. <el-table-column
  553. v-if="props.needRowindex"
  554. align="center"
  555. label="#"
  556. type="index"
  557. :index="computedRowIndex"
  558. />
  559. <template v-for="item in tableFieldsInfo">
  560. <el-table-column
  561. :prop="item.name"
  562. :label="item.cnName"
  563. :min-width="item.specialEffect?.type === FieldSpecialEffectType.DROPDOWN ? '170px' : ''"
  564. align="center"
  565. show-overflow-tooltip
  566. v-if="item.isShow"
  567. :sortable="item.needSort === true ? 'custorm' : false"
  568. >
  569. <template v-slot="scope">
  570. <!-- tag类 -->
  571. <el-tag
  572. v-if="item.specialEffect?.type === FieldSpecialEffectType.TAG"
  573. :type="scope.row[item.name] ? 'danger' : 'success'"
  574. >
  575. {{
  576. scope.row[item.name]
  577. ? item.specialEffect.othnerInfo.text[0]
  578. : item.specialEffect.othnerInfo.text[1]
  579. }}
  580. </el-tag>
  581. <!-- :src="loadResource(scope.row[item.name])" -->
  582. <!-- :src="scope.row[item.name]" -->
  583. <!-- 头像类 -->
  584. <el-image
  585. v-else-if="item.specialEffect?.type === FieldSpecialEffectType.IMG"
  586. :preview-teleported="true"
  587. :src="scope.row[item.name]"
  588. :preview-src-list="[scope.row[item.name]]"
  589. style="width: 35px; height: 35px"
  590. :fit="'fill'"
  591. :hide-on-click-modal="true"
  592. >
  593. <template #error>
  594. <!-- -->
  595. <img style="width: 35px; height: 35px" :src="blobUrlInfo.defaultHead" />
  596. </template>
  597. </el-image>
  598. <!-- 文字类 -->
  599. <el-text
  600. v-else-if="item.specialEffect?.type === FieldSpecialEffectType.TEXT"
  601. :type="
  602. scope.row[item.name]
  603. ? item.specialEffect.othnerInfo.color[0]
  604. : item.specialEffect.othnerInfo.color[1]
  605. "
  606. >
  607. {{ scope.row[item.name] }}
  608. </el-text>
  609. <!-- 翻译类 -->
  610. <el-text v-else-if="item.specialEffect?.type === FieldSpecialEffectType.TRANSLATE">
  611. <el-icon
  612. v-if="item.specialEffect.othnerInfo.icon"
  613. style="padding-right: 8px"
  614. :color="scope.row[item.name] ? '#409EFF' : '#F56C6C'"
  615. ><icon-tabler-point-filled></icon-tabler-point-filled
  616. ></el-icon>
  617. {{
  618. item.specialEffect.othnerInfo.translateText[scope.row[item.name]]
  619. ? item.specialEffect.othnerInfo.translateText[scope.row[item.name]]
  620. : '未知'
  621. }}
  622. </el-text>
  623. <!-- 状态类 -->
  624. <el-text v-else-if="item.specialEffect?.type === FieldSpecialEffectType.STATE">
  625. <span>
  626. <el-icon
  627. style="padding-right: 8px"
  628. :color="scope.row[item.name] ? '#409EFF' : '#F56C6C'"
  629. ><icon-tabler-point-filled></icon-tabler-point-filled
  630. ></el-icon>
  631. {{
  632. scope.row[item.name]
  633. ? item.specialEffect.othnerInfo.text[0]
  634. : item.specialEffect.othnerInfo.text[1]
  635. }}</span
  636. >
  637. </el-text>
  638. <!-- 开关类 -->
  639. <el-switch
  640. :active-value="1"
  641. :inactive-value="0"
  642. v-else-if="item.specialEffect?.type === FieldSpecialEffectType.SWITCH"
  643. v-model="scope.row[item.name]"
  644. :data="scope.row[item.name]"
  645. size="default"
  646. >
  647. </el-switch>
  648. <!-- 下拉菜单类 -->
  649. <el-dropdown
  650. trigger="click"
  651. v-else-if="item.specialEffect?.type === FieldSpecialEffectType.DROPDOWN"
  652. >
  653. <span
  654. class="el-dropdown-link"
  655. style="display: flex; align-items: center; cursor: pointer"
  656. >
  657. <el-icon
  658. style="padding-right: 8px"
  659. :color="scope.row[item.name] ? '#409EFF' : '#F56C6C'"
  660. ><icon-tabler-point-filled></icon-tabler-point-filled
  661. ></el-icon>
  662. {{
  663. scope.row[item.name]
  664. ? item.specialEffect.othnerInfo.text[0]
  665. : item.specialEffect.othnerInfo.text[1]
  666. }}
  667. <el-icon class="el-icon--right"><arrow-down /></el-icon>
  668. </span>
  669. <template #dropdown>
  670. <el-dropdown-menu>
  671. <el-dropdown-item :command="{ value: true }">使用中</el-dropdown-item>
  672. <el-dropdown-item :command="{ value: false }">已弃用</el-dropdown-item>
  673. </el-dropdown-menu>
  674. </template>
  675. </el-dropdown>
  676. <el-text v-else>
  677. <!-- 其他列按默认方式显示 -->
  678. {{
  679. props.needAverage &&
  680. scope.row[item.name] !== undefined &&
  681. item.name !== 'count' &&
  682. item.name !== 'date'
  683. ? scope.row[item.name] + '%'
  684. : scope.row[item.name]
  685. }}
  686. </el-text>
  687. </template>
  688. </el-table-column>
  689. </template>
  690. <slot name="tableOperation"></slot>
  691. </el-table>
  692. <div class="userTablePaginationBox">
  693. <el-pagination
  694. class="userTablePagination"
  695. background
  696. :page-size="paginationConfig2.limit"
  697. :page-sizes="paginationConfig2.pagesizeList"
  698. table-layout="fixed"
  699. layout="prev, pager, next ,jumper ,sizes,total,"
  700. :total="paginationConfig2.total"
  701. :current-page.sync="paginationConfig2.currentPage"
  702. @current-change="handleCurrentChange"
  703. @size-change="handleSizeChange"
  704. />
  705. </div>
  706. </div>
  707. </div>
  708. </template>
  709. <style scoped>
  710. .tableContent {
  711. margin: 10px auto 20px;
  712. width: 100%;
  713. /* height: 100%; */
  714. box-shadow:
  715. 0 4px 8px 0 rgba(0, 0, 0, 0.02),
  716. 0 1px 3px 0 rgba(0, 0, 0, 0.02);
  717. }
  718. .filterBox,
  719. .tableBox {
  720. width: 100%;
  721. }
  722. .filterBox {
  723. margin-top: 1%;
  724. min-height: 18%;
  725. display: flex;
  726. flex-direction: column;
  727. }
  728. .filterHeader,
  729. .filterBody {
  730. width: 98%;
  731. margin: 0 auto;
  732. }
  733. .filterHeader {
  734. display: flex;
  735. align-items: center;
  736. color: black;
  737. font-size: 16px;
  738. font-weight: bold;
  739. /* background-color: lightblue; */
  740. /* margin-bottom: 1%; */
  741. }
  742. .filterBody {
  743. display: flex;
  744. }
  745. .queryBox {
  746. width: 10%;
  747. display: flex;
  748. justify-content: space-around;
  749. }
  750. .queryBtnBox {
  751. width: 100%;
  752. display: flex;
  753. flex-direction: column;
  754. align-items: center;
  755. justify-content: center;
  756. }
  757. .refreshBtn {
  758. margin-top: 10%;
  759. margin-bottom: 10%;
  760. }
  761. .queryPartition {
  762. height: 90%;
  763. }
  764. .queryForm {
  765. width: 90%;
  766. display: flex;
  767. flex-wrap: wrap;
  768. /* justify-content: space-between; */
  769. }
  770. .filterItem {
  771. width: 20%;
  772. display: flex;
  773. align-items: center;
  774. }
  775. .partition {
  776. width: 98%;
  777. margin: 0 auto;
  778. }
  779. .tableTools {
  780. width: 98%;
  781. margin: 0 auto;
  782. display: flex;
  783. justify-content: space-between;
  784. margin-top: 1%;
  785. }
  786. .leftTools,
  787. .rightTools {
  788. width: 10%;
  789. display: flex;
  790. align-items: center;
  791. justify-content: space-between;
  792. }
  793. .rightTools {
  794. width: 5%;
  795. }
  796. .tableBox {
  797. width: 98%;
  798. /* height: 98%; */
  799. margin: 5px auto;
  800. box-shadow:
  801. 0 4px 8px 0 rgba(0, 0, 0, 0.02),
  802. 0 1px 3px 0 rgba(0, 0, 0, 0.02);
  803. /* margin-top: 0.5%;
  804. margin-bottom: 2%; */
  805. }
  806. .tableBody {
  807. box-shadow: 0 0 3px 0px rgba(0, 0, 0, 0.1);
  808. /* box-shadow:
  809. -4px -4px 8px 1px rgba(0, 0, 0, 0.02),
  810. -4px -4px 3px 1px rgba(0, 0, 0, 0.02); */
  811. }
  812. .userTablePaginationBox {
  813. box-sizing: border-box;
  814. width: 98%;
  815. margin: 0% auto;
  816. padding: 1% 0;
  817. display: flex;
  818. justify-content: center;
  819. }
  820. .averageItem {
  821. font-size: 14px;
  822. color: #515b6f;
  823. }
  824. .normalItem {
  825. font-size: 14px;
  826. color: #515b6f;
  827. font-weight: 400;
  828. }
  829. .leftToolBtn {
  830. margin-right: 5px;
  831. }
  832. </style>