TableCom.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <template>
  2. <div>
  3. <div class="search">
  4. <div>
  5. <div class="structure">
  6. <slot name="Uploads"></slot>
  7. <slot name="integration"></slot>
  8. <el-input v-model="fuzzyValue" placeholder="请输入内容" suffix-icon="el-icon-search"></el-input>
  9. <slot name="switch"></slot>
  10. </div>
  11. <!-- 插入开关 -->
  12. <slot name="function"></slot>
  13. </div>
  14. <div>
  15. <!-- 自定义option -->
  16. <el-popover placement="right" width="330" trigger="click">
  17. <span class="el-icon-s-tools" slot="reference"></span>
  18. <div class="option">
  19. <div class="title">
  20. <p v-for="(item, index) in choiceArray" :key="index" @click="handleChoiceClick(index)">
  21. {{ item.name }}
  22. </p>
  23. </div>
  24. <el-input v-model="inputValue" placeholder="请输入内容" suffix-icon="el-icon-search"
  25. @input="handleSearch"></el-input>
  26. <div class="custom-select">
  27. <div class="option" v-for="option in filteredOptions" :key="option.value">
  28. <label @click="toggleOption(option)">
  29. <span>{{ option.label }}</span>
  30. <i class="el-icon-check" v-if="option.selected"></i>
  31. </label>
  32. </div>
  33. </div>
  34. </div>
  35. </el-popover>
  36. </div>
  37. </div>
  38. <!-- .......表格......... -->
  39. <el-table :data="filteredTableData" style="width: 100%">
  40. <!-- 插入多选 -->
  41. <slot name="multiple"></slot>
  42. <!-- 表格列 -->
  43. <el-table-column v-for="(column, index) in filteredColumns" :key="index" :prop="column.prop" :label="column.label"
  44. :sortable="column.sortable" :width="column.width">
  45. <template slot-scope="scope">
  46. <div v-if="column.template">
  47. <component :is="column.template" :row="scope.row"></component>
  48. </div>
  49. <div v-else>
  50. <span v-if="column.prop === 'check'">
  51. {{ scope.row[column.prop] }}
  52. <el-popover placement="top-start" width="200" trigger="hover" content="这是一段内容,这是一段内容,这是一段内容,这是一段内容。"
  53. v-if="scope.row.check">
  54. <i class="el-icon-warning-outline" name="check" color="green" slot="reference"></i>
  55. </el-popover>
  56. </span>
  57. <span v-else>
  58. {{ scope.row[column.prop] }}
  59. </span>
  60. </div>
  61. </template>
  62. </el-table-column>
  63. <!-- 插入操作 -->
  64. <slot name="center"></slot>
  65. </el-table>
  66. <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  67. :current-page.sync="currentPage" :page-sizes="[5, 10]" :page-size="pageSize" :total="totalRows"
  68. layout="total, sizes, prev, pager, next">
  69. </el-pagination>
  70. </div>
  71. </template>
  72. <script>
  73. export default {
  74. props: {
  75. choiceArray: {
  76. type: Array,
  77. default: () => [],
  78. },
  79. options: {
  80. type: Array,
  81. default: () => [],
  82. },
  83. displayedData: {
  84. type: Array,
  85. default: () => [],
  86. },
  87. tableColumns: {
  88. type: Array,
  89. default: () => [],
  90. },
  91. },
  92. data() {
  93. return {
  94. fuzzyValue: "",
  95. inputValue: "",
  96. currentPage: 1,
  97. pageSize: 5,
  98. pageSizes: [5, 10, 20],
  99. };
  100. },
  101. computed: {
  102. // 表格模糊查询
  103. filteredTableData() {
  104. const searchTerm = this.fuzzyValue.toLowerCase();
  105. const filteredData = this.displayedData.filter((row) =>
  106. Object.values(row).some((value) =>
  107. value.toLowerCase().includes(searchTerm)
  108. )
  109. );
  110. const startIndex = (this.currentPage - 1) * this.pageSize;
  111. const endIndex = startIndex + this.pageSize;
  112. return filteredData.slice(startIndex, endIndex);
  113. },
  114. // 分页过滤
  115. totalRows() {
  116. const searchTerm = this.fuzzyValue.toLowerCase();
  117. const filteredData = this.displayedData.filter((row) =>
  118. Object.values(row).some((value) =>
  119. value.toLowerCase().includes(searchTerm)
  120. )
  121. );
  122. return filteredData.length;
  123. },
  124. // 模糊查询
  125. filteredOptions() {
  126. const searchTerm = this.inputValue.toLowerCase();
  127. return this.options.filter((option) =>
  128. option.label.toLowerCase().includes(searchTerm)
  129. );
  130. },
  131. // 过滤选项未被选择的列
  132. filteredColumns() {
  133. return this.tableColumns.filter((column) => {
  134. const option = this.options.find((opt) => opt.label === column.label);
  135. return option && option.selected;
  136. });
  137. },
  138. },
  139. methods: {
  140. // Option显影
  141. toggleOption(option) {
  142. option.selected = !option.selected;
  143. },
  144. // 全部
  145. selectAllOptions() {
  146. this.options.forEach((option) => {
  147. option.selected = true;
  148. });
  149. },
  150. // 默认
  151. restoreDefaultSelection() {
  152. this.options.forEach((option, index) => {
  153. option.selected = index < 999; // Select first two options, assuming they are default
  154. });
  155. },
  156. // 重置全部
  157. deselectAllOptions() {
  158. this.options.forEach((option) => {
  159. option.selected = false;
  160. });
  161. },
  162. // 执行上面三个方法
  163. handleChoiceClick(index) {
  164. switch (index) {
  165. case 0:
  166. this.selectAllOptions();
  167. break;
  168. case 1:
  169. this.restoreDefaultSelection();
  170. break;
  171. case 2:
  172. this.deselectAllOptions();
  173. break;
  174. default:
  175. break;
  176. }
  177. },
  178. // 分页
  179. handleSizeChange(val) {
  180. this.pageSize = val;
  181. },
  182. // 分页
  183. handleCurrentChange(val) {
  184. this.currentPage = val;
  185. },
  186. // 这里不需要做任何事情,因为computed属性负责过滤
  187. handleSearch() {
  188. // No need to do anything here as the computed property takes care of filtering
  189. },
  190. handleClick(row) {
  191. this.$router.push({ path: '/detailpage' });
  192. }
  193. },
  194. };
  195. </script>
  196. <style lang="scss" scoped>
  197. .el-input {
  198. margin-top: 0;
  199. }
  200. .el-table {
  201. margin: 20px 0;
  202. }
  203. .el-pagination {
  204. text-align: center;
  205. }
  206. .search {
  207. display: flex;
  208. justify-content: space-between;
  209. }
  210. .el-icon-s-tools {
  211. position: relative;
  212. }
  213. .option {
  214. .title {
  215. display: flex;
  216. justify-content: space-around;
  217. p {
  218. font-size: 16px;
  219. font-weight: 600;
  220. margin: 15px 0;
  221. border-bottom: 1px solid #606266;
  222. }
  223. p:hover {
  224. color: rgb(13, 83, 141);
  225. border-bottom: 1px solid rgb(13, 83, 141);
  226. }
  227. }
  228. .custom-select {
  229. padding: 10px 0;
  230. .option {
  231. width: 100%;
  232. line-height: 40px;
  233. label {
  234. display: flex;
  235. justify-content: space-between;
  236. span {
  237. font-size: 18px;
  238. font-weight: 600;
  239. color: #6b6b6b;
  240. }
  241. }
  242. label:hover {
  243. background: rgb(238, 238, 238);
  244. }
  245. }
  246. .el-icon-check {
  247. color: rgb(49, 192, 97);
  248. line-height: 40px;
  249. margin-right: 5px;
  250. font-size: 16px;
  251. font-weight: 600;
  252. }
  253. }
  254. }
  255. .el-icon-warning-outline {
  256. font-size: 16px;
  257. margin: 0 10px;
  258. }
  259. .structure{
  260. display: flex;
  261. }
  262. </style>