Showing
4 changed files
with
854 additions
and
0 deletions
src/components/YlForm/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div | ||
| 3 | + class="ylform" | ||
| 4 | + :class="inline == true ? 'the-form' : ''" | ||
| 5 | + :style="{ marginBottom: `${marginBottom}px` }" | ||
| 6 | + > | ||
| 7 | + <el-form | ||
| 8 | + :model="tempQueryForm" | ||
| 9 | + :inline="inline" | ||
| 10 | + :label-position="position" | ||
| 11 | + :label-width="formWidth" | ||
| 12 | + :loading="loading" | ||
| 13 | + ref="ruleForm" | ||
| 14 | + :size="size" | ||
| 15 | + > | ||
| 16 | + <el-row | ||
| 17 | + :gutter="rowGutter" | ||
| 18 | + :type="rowType" | ||
| 19 | + :justify="rowJustify" | ||
| 20 | + :align="rowAlign" | ||
| 21 | + :tag="rowTag" | ||
| 22 | + > | ||
| 23 | + <span v-for="item in tempFormConfig" :key="item.name"> | ||
| 24 | + <el-col | ||
| 25 | + v-if="!item.hidden" | ||
| 26 | + :span="item.span" | ||
| 27 | + :offset="item.offset" | ||
| 28 | + :tag="item.tag" | ||
| 29 | + :push="item.push" | ||
| 30 | + :pull="item.pull" | ||
| 31 | + :xs="item.xs" | ||
| 32 | + :sm="item.sm" | ||
| 33 | + :md="item.md" | ||
| 34 | + :lg="item.lg" | ||
| 35 | + :xl="item.xl" | ||
| 36 | + :style="{ width: item.colWidth }" | ||
| 37 | + > | ||
| 38 | + <el-form-item | ||
| 39 | + :label="item.label" | ||
| 40 | + :prop="item.prop" | ||
| 41 | + :rules="item.rules" | ||
| 42 | + :label-width="item.labelWidth" | ||
| 43 | + > | ||
| 44 | + <slot v-if="item.type === 'slot'"></slot> | ||
| 45 | + <!-- 输入框 --> | ||
| 46 | + <el-input | ||
| 47 | + v-if="item.type === 'Input'" | ||
| 48 | + v-model="tempQueryForm[item.prop]" | ||
| 49 | + :style="{ width: item.inputWidth }" | ||
| 50 | + :disabled="item.disable" | ||
| 51 | + :placeholder=" | ||
| 52 | + item.placeholder ? item.placeholder : '请输入' + item.label | ||
| 53 | + " | ||
| 54 | + v-on:[item.trigger]=" | ||
| 55 | + (e) => { | ||
| 56 | + inputEvent(e, item); | ||
| 57 | + } | ||
| 58 | + " | ||
| 59 | + @keyup.enter.native="toEnterSearch" | ||
| 60 | + clearable | ||
| 61 | + > | ||
| 62 | + </el-input> | ||
| 63 | + <template v-if="view"> | ||
| 64 | + <span v-text="tempQueryForm[item.prop]"></span> | ||
| 65 | + </template> | ||
| 66 | + <!-- 数字输入框 --> | ||
| 67 | + <el-input | ||
| 68 | + v-if="item.type === 'inputNumber'" | ||
| 69 | + type="number" | ||
| 70 | + :min="item.min" | ||
| 71 | + :max="item.max" | ||
| 72 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 73 | + :style="{ width: item.inputWidth }" | ||
| 74 | + :disabled="item.disable" | ||
| 75 | + :placeholder=" | ||
| 76 | + item.placeholder ? item.placeholder : '请输入' + item.label | ||
| 77 | + " | ||
| 78 | + v-on:keyup.enter="value = value.replace(/^-?[0-9]\d*$/, '')" | ||
| 79 | + clearable | ||
| 80 | + > | ||
| 81 | + </el-input> | ||
| 82 | + <!-- InputNumber 计数器 --> | ||
| 83 | + <el-input-number | ||
| 84 | + v-if="item.type === 'Number'" | ||
| 85 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 86 | + :min="0" | ||
| 87 | + :max="10" | ||
| 88 | + :size="item.size" | ||
| 89 | + :style="{ width: item.inputWidth }" | ||
| 90 | + label="描述文字" | ||
| 91 | + ></el-input-number> | ||
| 92 | + | ||
| 93 | + <template v-if="view"> | ||
| 94 | + <span v-text="tempQueryForm[item.prop]"></span> | ||
| 95 | + </template> | ||
| 96 | + | ||
| 97 | + <!-- 下拉选择 --> | ||
| 98 | + <el-select | ||
| 99 | + v-if="item.type === 'Select'" | ||
| 100 | + :multiple="item.multiple" | ||
| 101 | + :filterable="item.filterable" | ||
| 102 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 103 | + :style="{ width: item.inputWidth }" | ||
| 104 | + :disabled="item.disable" | ||
| 105 | + :loading="searchLoading" | ||
| 106 | + :placeholder=" | ||
| 107 | + item.placeholder ? item.placeholder : '请选择' + item.label | ||
| 108 | + " | ||
| 109 | + clearable | ||
| 110 | + > | ||
| 111 | + <el-option | ||
| 112 | + v-for="op in item.options.data" | ||
| 113 | + :label="op[item.options.label] || op.label" | ||
| 114 | + :value="op[item.options.value] || op.value" | ||
| 115 | + :key="op[item.options.value] || op.value" | ||
| 116 | + > | ||
| 117 | + </el-option> | ||
| 118 | + </el-select> | ||
| 119 | + | ||
| 120 | + <!-- 远程搜索 --> | ||
| 121 | + <template v-if="item.type === 'Search'"> | ||
| 122 | + <el-autocomplete | ||
| 123 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 124 | + :style="{ width: item.inputWidth }" | ||
| 125 | + :debounce="1500" | ||
| 126 | + :fetch-suggestions="querySearchAsync" | ||
| 127 | + :placeholder=" | ||
| 128 | + item.placeholder ? item.placeholder : '请选择' + item.label | ||
| 129 | + " | ||
| 130 | + @focus="focusKey(item)" | ||
| 131 | + @select="selectSearch" | ||
| 132 | + clearable | ||
| 133 | + ></el-autocomplete> | ||
| 134 | + </template> | ||
| 135 | + | ||
| 136 | + <!-- 日期 --> | ||
| 137 | + <el-date-picker | ||
| 138 | + v-if="item.type === 'Date'" | ||
| 139 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 140 | + :style="{ width: item.inputWidth }" | ||
| 141 | + :disabled="item.disable" | ||
| 142 | + :placeholder=" | ||
| 143 | + item.placeholder ? item.placeholder : '请选择日期' | ||
| 144 | + " | ||
| 145 | + :value-format="item.format" | ||
| 146 | + clearable | ||
| 147 | + > | ||
| 148 | + </el-date-picker> | ||
| 149 | + | ||
| 150 | + <!-- 时间 --> | ||
| 151 | + <el-time-select | ||
| 152 | + v-if="item.type === 'Time'" | ||
| 153 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 154 | + :style="{ width: item.inputWidth }" | ||
| 155 | + :disabled="item.disable" | ||
| 156 | + :placeholder=" | ||
| 157 | + item.placeholder ? item.placeholder : '请选择时间' | ||
| 158 | + " | ||
| 159 | + clearable | ||
| 160 | + > | ||
| 161 | + </el-time-select> | ||
| 162 | + | ||
| 163 | + <!-- 日期时间 --> | ||
| 164 | + <el-date-picker | ||
| 165 | + v-if="item.type === 'DateTime'" | ||
| 166 | + type="datetime" | ||
| 167 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 168 | + :disabled="item.disable" | ||
| 169 | + :placeholder=" | ||
| 170 | + item.placeholder ? item.placeholder : '请选择日期' | ||
| 171 | + " | ||
| 172 | + clearable | ||
| 173 | + > | ||
| 174 | + </el-date-picker> | ||
| 175 | + | ||
| 176 | + <!-- 日期范围 --> | ||
| 177 | + <el-date-picker | ||
| 178 | + v-if="item.type === 'datetimerange'" | ||
| 179 | + type="datetimerange" | ||
| 180 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 181 | + :style="{ width: item.inputWidth }" | ||
| 182 | + :disabled="item.disable" | ||
| 183 | + range-separator="至" | ||
| 184 | + start-placeholder="开始日期" | ||
| 185 | + end-placeholder="结束日期" | ||
| 186 | + clearable | ||
| 187 | + > | ||
| 188 | + </el-date-picker> | ||
| 189 | + | ||
| 190 | + <!-- 单选框 普通的样式 Radio 的尺寸,仅在 border 为真时有效--> | ||
| 191 | + <template v-if="item.type === 'radio'"> | ||
| 192 | + <el-radio | ||
| 193 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 194 | + v-for="op in item.options.data" | ||
| 195 | + :disabled="item.disable" | ||
| 196 | + :border="tempQueryForm[item.border]" | ||
| 197 | + :size="tempQueryForm[item.size]" | ||
| 198 | + :label="op[item.options.label] || op.label" | ||
| 199 | + :value="op[item.options.value] || op.value" | ||
| 200 | + :key="op[item.options.value] || op.value" | ||
| 201 | + ></el-radio> | ||
| 202 | + </template> | ||
| 203 | + | ||
| 204 | + <!-- 单选框 按钮样式 --> | ||
| 205 | + <el-radio-group | ||
| 206 | + v-if="item.type === 'radioButtom'" | ||
| 207 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 208 | + :size="tempQueryForm[item.size]" | ||
| 209 | + :disabled="item.disable" | ||
| 210 | + > | ||
| 211 | + <el-radio-button | ||
| 212 | + v-for="op in item.options.data" | ||
| 213 | + :label="op[item.options.label] || op.label" | ||
| 214 | + :value="op[item.options.value] || op.value" | ||
| 215 | + :key="op[item.options.value] || op.value" | ||
| 216 | + ></el-radio-button> | ||
| 217 | + </el-radio-group> | ||
| 218 | + | ||
| 219 | + <!-- 文本框 --> | ||
| 220 | + <el-input | ||
| 221 | + v-if="item.type === 'textarea'" | ||
| 222 | + v-model.trim="tempQueryForm[item.prop]" | ||
| 223 | + type="textarea" | ||
| 224 | + :style="{ width: item.inputWidth }" | ||
| 225 | + :disabled="item.disable" | ||
| 226 | + :rows="item.row" | ||
| 227 | + :autosize="item.autosize" | ||
| 228 | + :placeholder=" | ||
| 229 | + item.placeholder ? item.placeholder : '请输入' + item.label | ||
| 230 | + " | ||
| 231 | + clearable | ||
| 232 | + > | ||
| 233 | + </el-input> | ||
| 234 | + | ||
| 235 | + <!-- 多选框 --> | ||
| 236 | + <template v-if="item.type === 'Checkbox'"> | ||
| 237 | + <el-checkbox | ||
| 238 | + v-model="tempQueryForm[item.prop]" | ||
| 239 | + :disabled="item.disabled" | ||
| 240 | + ></el-checkbox> | ||
| 241 | + </template> | ||
| 242 | + </el-form-item> | ||
| 243 | + </el-col> | ||
| 244 | + </span> | ||
| 245 | + <!-- 查询按钮 de--> | ||
| 246 | + <span v-show="inline & hiddenFormBtn"> | ||
| 247 | + <el-form-item v-show="show"> | ||
| 248 | + <el-button | ||
| 249 | + type="primary" | ||
| 250 | + @click="handleSearch('ruleForm')" | ||
| 251 | + :btnLoading="btnLoading" | ||
| 252 | + > | ||
| 253 | + {{ formBtn }} | ||
| 254 | + </el-button> | ||
| 255 | + </el-form-item> | ||
| 256 | + </span> | ||
| 257 | + <span v-show="inline & hiddenFormBtn"> | ||
| 258 | + <el-form-item v-show="show"> | ||
| 259 | + <el-button @click="resetFields('ruleForm')">重置</el-button> | ||
| 260 | + </el-form-item> | ||
| 261 | + </span> | ||
| 262 | + </el-row> | ||
| 263 | + </el-form> | ||
| 264 | + </div> | ||
| 265 | +</template> | ||
| 266 | + | ||
| 267 | +<script> | ||
| 268 | +import request from "@/utils/request"; | ||
| 269 | +import { deepClone } from "@/utils"; | ||
| 270 | +export default { | ||
| 271 | + name: "YlForm", | ||
| 272 | + props: { | ||
| 273 | + rowGutter: { | ||
| 274 | + type: Number, | ||
| 275 | + default: 24, | ||
| 276 | + }, | ||
| 277 | + rowType: { | ||
| 278 | + type: String, | ||
| 279 | + default: "", | ||
| 280 | + }, | ||
| 281 | + rowJustify: { | ||
| 282 | + type: String, | ||
| 283 | + default: "", | ||
| 284 | + }, | ||
| 285 | + rowAlign: { | ||
| 286 | + type: String, | ||
| 287 | + default: "", | ||
| 288 | + }, | ||
| 289 | + rowTag: { | ||
| 290 | + type: String, | ||
| 291 | + default: "div", | ||
| 292 | + }, | ||
| 293 | + // 由inline属性决定form表单是普通表单,还是行内表单 | ||
| 294 | + inline: { | ||
| 295 | + //排列方式 | ||
| 296 | + type: Boolean, | ||
| 297 | + default: true, | ||
| 298 | + }, | ||
| 299 | + searchLoading: { | ||
| 300 | + type: Boolean, | ||
| 301 | + default: false, | ||
| 302 | + }, | ||
| 303 | + hiddenFormBtn: { | ||
| 304 | + //是否展示搜索按钮 | ||
| 305 | + type: Boolean, | ||
| 306 | + default: false, | ||
| 307 | + }, | ||
| 308 | + formWidth: { | ||
| 309 | + //form表单宽度 | ||
| 310 | + type: String, | ||
| 311 | + default: "auto", | ||
| 312 | + }, | ||
| 313 | + position: { | ||
| 314 | + type: String, | ||
| 315 | + default: "", | ||
| 316 | + }, | ||
| 317 | + formConfig: { | ||
| 318 | + type: Array, | ||
| 319 | + default: [], | ||
| 320 | + }, | ||
| 321 | + queryForm: { | ||
| 322 | + type: Object, | ||
| 323 | + default: () => {}, | ||
| 324 | + }, | ||
| 325 | + // 用于控制该表单内组件的尺寸 medium / small / mini | ||
| 326 | + size: { | ||
| 327 | + type: String, | ||
| 328 | + default: "small", | ||
| 329 | + }, | ||
| 330 | + marginBottom: { | ||
| 331 | + type: Number, | ||
| 332 | + default: 0, | ||
| 333 | + }, | ||
| 334 | + view: { | ||
| 335 | + type: Boolean, | ||
| 336 | + default: false, | ||
| 337 | + }, | ||
| 338 | + formBtn: { | ||
| 339 | + type: String, | ||
| 340 | + default: "查询", | ||
| 341 | + }, | ||
| 342 | + btnLoading: { | ||
| 343 | + type: Boolean, | ||
| 344 | + default: false, | ||
| 345 | + }, | ||
| 346 | + loading: { | ||
| 347 | + //加载 | ||
| 348 | + type: Boolean, | ||
| 349 | + default: false, | ||
| 350 | + }, | ||
| 351 | + isBtnSave: { | ||
| 352 | + type: Boolean, | ||
| 353 | + default: false, | ||
| 354 | + }, | ||
| 355 | + }, | ||
| 356 | + data() { | ||
| 357 | + return { | ||
| 358 | + show: true, | ||
| 359 | + tempQueryForm: {}, | ||
| 360 | + tempFormConfig: [], | ||
| 361 | + fetchResult: [], | ||
| 362 | + timeout: null, | ||
| 363 | + searchMark: {}, // 搜索 | ||
| 364 | + }; | ||
| 365 | + }, | ||
| 366 | + mounted() {}, | ||
| 367 | + computed: {}, | ||
| 368 | + methods: { | ||
| 369 | + // input事件绑定和注册 | ||
| 370 | + inputEvent(e, item) { | ||
| 371 | + this.$emit(item.trigger, this.tempQueryForm); | ||
| 372 | + }, | ||
| 373 | + // 回车事件 | ||
| 374 | + toEnterSearch() { | ||
| 375 | + this.$emit("keyup", this.tempQueryForm); | ||
| 376 | + }, | ||
| 377 | + // selectSearch 聚焦获取当前input绑定的数据 | ||
| 378 | + focusKey(item) { | ||
| 379 | + this.searchMark = item; | ||
| 380 | + }, | ||
| 381 | + // selectSearch 下拉选中获取当前input绑定的数据 | ||
| 382 | + selectSearch(item) { | ||
| 383 | + console.log(item); | ||
| 384 | + }, | ||
| 385 | + // 远程搜索查询 | ||
| 386 | + querySearchAsync(queryString, cb) { | ||
| 387 | + let result = this.formConfig.filter((item) => { | ||
| 388 | + if (item.hasOwnProperty("http")) { | ||
| 389 | + if (item.prop === this.searchMark.prop) { | ||
| 390 | + return item; | ||
| 391 | + } | ||
| 392 | + } | ||
| 393 | + }); | ||
| 394 | + // 在搜索关键词不为空时发送http请求 | ||
| 395 | + if (queryString) { | ||
| 396 | + if (queryString.split(" ").length > 0) { | ||
| 397 | + if (result[0].http.method == "post") { | ||
| 398 | + result[0].http.data[result[0].prop] = queryString.split(" ")[0]; | ||
| 399 | + } else { | ||
| 400 | + result[0].http.params[result[0].prop] = queryString.split(" ")[0]; | ||
| 401 | + } | ||
| 402 | + } | ||
| 403 | + request(result[0].http).then((res) => { | ||
| 404 | + if (res.code == 200) { | ||
| 405 | + if (res.data.list.length) { | ||
| 406 | + res.data.list.map((item) => { | ||
| 407 | + item.value = `${item[result[0].prop]} ${item[result[0].name]}`; | ||
| 408 | + }); | ||
| 409 | + this.fetchResult = res.data.list; | ||
| 410 | + var results = queryString.split(" ")[0] | ||
| 411 | + ? this.fetchResult.filter( | ||
| 412 | + this.createStateFilter(queryString.split(" ")[0]) | ||
| 413 | + ) | ||
| 414 | + : this.fetchResult; | ||
| 415 | + clearTimeout(this.timeout); | ||
| 416 | + this.timeout = setTimeout(() => { | ||
| 417 | + cb(results); | ||
| 418 | + }, 1500 * Math.random()); | ||
| 419 | + } | ||
| 420 | + } | ||
| 421 | + }); | ||
| 422 | + } | ||
| 423 | + }, | ||
| 424 | + // 远程搜索匹配查询 | ||
| 425 | + createStateFilter(queryString) { | ||
| 426 | + return (state) => { | ||
| 427 | + return ( | ||
| 428 | + state[this.searchMark.prop] | ||
| 429 | + .toLowerCase() | ||
| 430 | + .indexOf(queryString.toLowerCase()) === 0 | ||
| 431 | + ); | ||
| 432 | + }; | ||
| 433 | + }, | ||
| 434 | + // 行内表单搜索事件 | ||
| 435 | + handleSearch(formName, cb) { | ||
| 436 | + this.$refs[formName].validate((valid) => { | ||
| 437 | + if (valid) { | ||
| 438 | + cb(valid); | ||
| 439 | + } else { | ||
| 440 | + console.log("error submit!!"); | ||
| 441 | + return false; | ||
| 442 | + } | ||
| 443 | + }); | ||
| 444 | + this.$emit("handleSearch"); | ||
| 445 | + }, | ||
| 446 | + // 清空ruleForm表单事件 | ||
| 447 | + resetFields(formName = "ruleForm") { | ||
| 448 | + this.$refs[formName].resetFields(); | ||
| 449 | + }, | ||
| 450 | + }, | ||
| 451 | + watch: { | ||
| 452 | + queryForm: { | ||
| 453 | + handler(val) { | ||
| 454 | + this.tempQueryForm = val; | ||
| 455 | + }, | ||
| 456 | + deep: true, | ||
| 457 | + immediate: true, | ||
| 458 | + }, | ||
| 459 | + formConfig: { | ||
| 460 | + handler(val) { | ||
| 461 | + this.tempFormConfig = deepClone(val); | ||
| 462 | + }, | ||
| 463 | + deep: true, | ||
| 464 | + immediate: true, | ||
| 465 | + }, | ||
| 466 | + // | ||
| 467 | + }, | ||
| 468 | +}; | ||
| 469 | +</script> | ||
| 470 | +<style lang="scss" scoped></style> |
src/components/YlInput/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-input | ||
| 3 | + v-bind="$attrs" | ||
| 4 | + clearable | ||
| 5 | + @input="handleInput" | ||
| 6 | + @focus="handleFocus" | ||
| 7 | + @blur="handleBlur" | ||
| 8 | + @change="handleChange" | ||
| 9 | + class="yl-input" | ||
| 10 | + ></el-input> | ||
| 11 | +</template> | ||
| 12 | + | ||
| 13 | +<script> | ||
| 14 | +export default { | ||
| 15 | + props: { | ||
| 16 | + rules: { | ||
| 17 | + type: Array, | ||
| 18 | + default: () => [], | ||
| 19 | + }, | ||
| 20 | + }, | ||
| 21 | + data() { | ||
| 22 | + return {}; | ||
| 23 | + }, | ||
| 24 | + computed: {}, | ||
| 25 | + created() {}, | ||
| 26 | + mounted() {}, | ||
| 27 | + methods: { | ||
| 28 | + handleInput(event) { | ||
| 29 | + // v-bind="$attrs" v-on="$listeners" | ||
| 30 | + this.$emit("input", event); | ||
| 31 | + }, | ||
| 32 | + handleFocus(event) { | ||
| 33 | + this.$emit("focus", event); | ||
| 34 | + }, | ||
| 35 | + handleBlur(event) { | ||
| 36 | + this.$emit("blur", event); | ||
| 37 | + }, | ||
| 38 | + handleChange(event) { | ||
| 39 | + this.$emit("change", event); | ||
| 40 | + }, | ||
| 41 | + }, | ||
| 42 | +}; | ||
| 43 | +</script> | ||
| 44 | +<style lang='scss'> | ||
| 45 | + | ||
| 46 | +</style> |
src/components/YlTable/column.vue
0 → 100644
| 1 | +<script> | ||
| 2 | +/** | ||
| 3 | + * 动态渲染 el-table-column | ||
| 4 | + */ | ||
| 5 | +export default { | ||
| 6 | + name: 'column', | ||
| 7 | + props: { | ||
| 8 | + attrs: { | ||
| 9 | + type: Object, | ||
| 10 | + default: () => ({}), | ||
| 11 | + required: true | ||
| 12 | + } | ||
| 13 | + }, | ||
| 14 | + render: function(h) { | ||
| 15 | + let attrs = this.attrs; | ||
| 16 | + let scopedSlots = {}; | ||
| 17 | + if (attrs.render) { | ||
| 18 | + scopedSlots.default = scope => attrs.render(h, scope); | ||
| 19 | + } | ||
| 20 | + return h('el-table-column', { | ||
| 21 | + attrs, | ||
| 22 | + scopedSlots | ||
| 23 | + }); | ||
| 24 | + } | ||
| 25 | +}; | ||
| 26 | +</script> |
src/components/YlTable/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="table-container"> | ||
| 3 | + <el-row | ||
| 4 | + v-if="attrs.btnCofig.isBtn" | ||
| 5 | + style="margin-bottom: 15px" | ||
| 6 | + id="group-btn" | ||
| 7 | + > | ||
| 8 | + <el-col> | ||
| 9 | + <span | ||
| 10 | + v-for="(item, i) in attrs.btnCofig.btnGroup" | ||
| 11 | + :key="item.btnName" | ||
| 12 | + :class="i == 0 ? 'first-span' : 'span'" | ||
| 13 | + > | ||
| 14 | + <el-button | ||
| 15 | + :type="item.type" | ||
| 16 | + :icon="item.icon" | ||
| 17 | + :round="item.round" | ||
| 18 | + :size="item.size" | ||
| 19 | + :loading="item.loading" | ||
| 20 | + @click="handleClick(item, i)" | ||
| 21 | + v-if="item.btnName !== '导入' && item.btnName !== '增加'" | ||
| 22 | + >{{ item.btnName }}</el-button | ||
| 23 | + > | ||
| 24 | + <el-upload | ||
| 25 | + v-else | ||
| 26 | + ref="upload" | ||
| 27 | + :action="item.action" | ||
| 28 | + :fileName="item.fileName" | ||
| 29 | + :http-request="toUpload" | ||
| 30 | + :on-remove="onRemoveUpload" | ||
| 31 | + :limit="item.limit" | ||
| 32 | + :accept="item.accept" | ||
| 33 | + :show-file-list="false" | ||
| 34 | + class="upload" | ||
| 35 | + > | ||
| 36 | + <el-button | ||
| 37 | + :type="item.type" | ||
| 38 | + :icon="item.icon" | ||
| 39 | + :round="item.round" | ||
| 40 | + :size="item.size" | ||
| 41 | + :loading="item.loading" | ||
| 42 | + >{{ item.btnName }}</el-button | ||
| 43 | + > | ||
| 44 | + </el-upload> | ||
| 45 | + </span> | ||
| 46 | + </el-col> | ||
| 47 | + </el-row> | ||
| 48 | + <el-table | ||
| 49 | + :max-height="attrs.maxHeight" | ||
| 50 | + :empty-text="emptyText" | ||
| 51 | + v-bind="attrs" | ||
| 52 | + v-loading="loadingTable" | ||
| 53 | + :data="tableData" | ||
| 54 | + @selection-change="selectionChange" | ||
| 55 | + ref="tableRef" | ||
| 56 | + row-key="id" | ||
| 57 | + :header-cell-class-name="headerCellClassName" | ||
| 58 | + > | ||
| 59 | + <template v-if="columns.length"> | ||
| 60 | + <template v-for="item in columns"> | ||
| 61 | + <column v-if="!item.hidden" :key="item.id" :attrs="item"></column> | ||
| 62 | + </template> | ||
| 63 | + </template> | ||
| 64 | + <slot name="column" v-else></slot> | ||
| 65 | + </el-table> | ||
| 66 | + <!-- 分页 --> | ||
| 67 | + <div | ||
| 68 | + v-if="pageConfig.isPagination" | ||
| 69 | + id="pagination" | ||
| 70 | + class="pagination-container" | ||
| 71 | + :style="{ textAlign: pageConfig.position || 'right' }" | ||
| 72 | + ref="paginationRef" | ||
| 73 | + > | ||
| 74 | + <el-pagination | ||
| 75 | + background | ||
| 76 | + :hide-on-single-page="false" | ||
| 77 | + :current-page="pageConfig.pageData.page" | ||
| 78 | + :page-sizes="[10, 15, 20, 25, 30, 35, 40]" | ||
| 79 | + :page-size="pageConfig.pageData.size" | ||
| 80 | + layout="total,prev, pager, next, jumper, ->, sizes" | ||
| 81 | + :total="pageConfig.total" | ||
| 82 | + @size-change="handleSizeChange" | ||
| 83 | + @current-change="handleCurrentChange" | ||
| 84 | + > | ||
| 85 | + </el-pagination> | ||
| 86 | + </div> | ||
| 87 | + </div> | ||
| 88 | +</template> | ||
| 89 | + | ||
| 90 | +<script> | ||
| 91 | +import Sortable from "sortablejs"; | ||
| 92 | +import { objectMerge, debounce } from "@/utils"; | ||
| 93 | +import column from "./column"; | ||
| 94 | +export default { | ||
| 95 | + props: { | ||
| 96 | + attrs: { | ||
| 97 | + type: Object, | ||
| 98 | + default: { | ||
| 99 | + border: true, | ||
| 100 | + isDragSort: false, | ||
| 101 | + btnCofig: { | ||
| 102 | + isBtn: true, | ||
| 103 | + btnGroup: [ | ||
| 104 | + { | ||
| 105 | + type: "primary", // text、primary、danger | ||
| 106 | + icon: "el-icon-search", // el-icon-edit 、el-icon-delete、el-icon-plus、el-icon-download、el-icon-upload el-icon--right | ||
| 107 | + btnName: "搜索", | ||
| 108 | + size: "mini", // medium / small / mini | ||
| 109 | + round: false, | ||
| 110 | + loading: false, | ||
| 111 | + event: "searchBtn", | ||
| 112 | + }, | ||
| 113 | + ], | ||
| 114 | + }, | ||
| 115 | + }, | ||
| 116 | + }, | ||
| 117 | + emptyText: { | ||
| 118 | + type: String, | ||
| 119 | + default: "暂无数据", | ||
| 120 | + }, | ||
| 121 | + loadingTable: { | ||
| 122 | + type: Boolean, | ||
| 123 | + default: false, | ||
| 124 | + }, | ||
| 125 | + columns: { | ||
| 126 | + type: Array, | ||
| 127 | + default: () => [], | ||
| 128 | + }, | ||
| 129 | + tableData: { | ||
| 130 | + type: Array, | ||
| 131 | + default: () => [], | ||
| 132 | + }, | ||
| 133 | + pageConfig: { | ||
| 134 | + type: Object, | ||
| 135 | + default: { | ||
| 136 | + isPagination: true, | ||
| 137 | + }, | ||
| 138 | + required: true, | ||
| 139 | + }, | ||
| 140 | + }, | ||
| 141 | + components: { | ||
| 142 | + column, | ||
| 143 | + }, | ||
| 144 | + data() { | ||
| 145 | + return { | ||
| 146 | + dropCol: objectMerge({}, this.columns), | ||
| 147 | + trHeight: 4, | ||
| 148 | + }; | ||
| 149 | + }, | ||
| 150 | + computed: { | ||
| 151 | + _attrs() { | ||
| 152 | + //默认table 参数 | ||
| 153 | + const defaultParams = {}; | ||
| 154 | + return Object.assign(defaultParams, this.attrs); | ||
| 155 | + }, | ||
| 156 | + isHasAttr() {}, | ||
| 157 | + }, | ||
| 158 | + created() { | ||
| 159 | + if (this.attrs.isDragSort) { | ||
| 160 | + // 有没有复选框、有没有render | ||
| 161 | + // this.columns | ||
| 162 | + } | ||
| 163 | + }, | ||
| 164 | + | ||
| 165 | + mounted() { | ||
| 166 | + //阻止火狐拖拽新建新页面 | ||
| 167 | + document.body.addEventListener( | ||
| 168 | + "drop", | ||
| 169 | + (event) => { | ||
| 170 | + event.preventDefault(); | ||
| 171 | + event.stopPropagation(); | ||
| 172 | + }, | ||
| 173 | + false | ||
| 174 | + ); | ||
| 175 | + this.getTrCurrentHeight(); | ||
| 176 | + window.addEventListener("resize", this.getTrCurrentHeight); | ||
| 177 | + }, | ||
| 178 | + destroyed() { | ||
| 179 | + if (this.tableData.length) { | ||
| 180 | + window.removeEventListener("resize", this.getTrCurrentHeight); | ||
| 181 | + } | ||
| 182 | + }, | ||
| 183 | + | ||
| 184 | + methods: { | ||
| 185 | + getTrCurrentHeight: debounce(function () { | ||
| 186 | + this.$nextTick(() => { | ||
| 187 | + // const trEl = | ||
| 188 | + // this.$refs.tableRef.$refs.bodyWrapper.children[0].children[1] | ||
| 189 | + // .children[0]; | ||
| 190 | + // console.log(trEl) | ||
| 191 | + // if (trEl) { | ||
| 192 | + // this.trHeight = trEl.clientHeight; | ||
| 193 | + // } | ||
| 194 | + }); | ||
| 195 | + }, 800), | ||
| 196 | + // 给表头列添加className | ||
| 197 | + headerCellClassName({ row, column, rowIndex, columnIndex }) { | ||
| 198 | + if (columnIndex !== 0) { | ||
| 199 | + return "el-table_1_column"; | ||
| 200 | + } | ||
| 201 | + }, | ||
| 202 | + useTableFunc(FuncName, ...params) { | ||
| 203 | + if (!this.$refs["el-table"]) { | ||
| 204 | + return console.warn("访问不到el-table"); | ||
| 205 | + } | ||
| 206 | + if (!FuncName) { | ||
| 207 | + return console.error("请传入tabel方法名字"); | ||
| 208 | + } | ||
| 209 | + this.$refs["el-table"][FuncName](params[0]); | ||
| 210 | + }, | ||
| 211 | + // table复选框事件 | ||
| 212 | + selectionChange(e) { | ||
| 213 | + console.log(e); | ||
| 214 | + this.$emit("selectionEvent", e); | ||
| 215 | + }, | ||
| 216 | + // 条数变化 | ||
| 217 | + handleSizeChange(e) { | ||
| 218 | + this.$emit("sizeChange", e); | ||
| 219 | + }, | ||
| 220 | + // 页码变化 | ||
| 221 | + handleCurrentChange(e) { | ||
| 222 | + this.$emit("currentChange", e); | ||
| 223 | + }, | ||
| 224 | + // btn点击事件注册 | ||
| 225 | + handleClick(item, i) { | ||
| 226 | + this.$emit(item.event, item, i); | ||
| 227 | + }, | ||
| 228 | + // 拖拽行更新排序 | ||
| 229 | + rowDrop() { | ||
| 230 | + const wrapperTr = document.querySelector(".el-table__header-wrapper tr"); | ||
| 231 | + // console.log("wrapperTr:", wrapperTr); | ||
| 232 | + this.sortable = Sortable.create(wrapperTr, { | ||
| 233 | + sort: this.attrs.isDragSort, | ||
| 234 | + animation: 100, | ||
| 235 | + delay: 0, | ||
| 236 | + handle: ".move", // 只有带move类名的元素才能拖动,多选框禁止拖动 | ||
| 237 | + onEnd: (evt) => { | ||
| 238 | + // 因为手动加了一个多选框, 不在表头循环数组内, 所以这里减1 | ||
| 239 | + let oldIndx = evt.oldIndex - 1; | ||
| 240 | + let newIndx = evt.newIndex - 1; | ||
| 241 | + const oldItem = this.dropCol[oldIndx]; | ||
| 242 | + // 真正改变列数据--变化列头,就能实现列拖动 列数据按列头索引取值 {{ scope.row[dropCol[index].prop] }} | ||
| 243 | + this.dropCol.splice(oldIndx, 1); // 删除旧一行 删除为1 | ||
| 244 | + this.dropCol.splice(newIndx, 0, oldItem); // 插入新一行 插入为0 | ||
| 245 | + }, | ||
| 246 | + }); | ||
| 247 | + }, | ||
| 248 | + // 拖拽列更新排序 | ||
| 249 | + columnDrop() { | ||
| 250 | + const tbody = document.querySelector(".el-table__body-wrapper tbody"); | ||
| 251 | + const _this = this; | ||
| 252 | + Sortable.create(tbody, { | ||
| 253 | + sort: this.attrs.isDragSort, | ||
| 254 | + animation: 100, | ||
| 255 | + delay: 0, | ||
| 256 | + onStart(evt) { | ||
| 257 | + // console.log("onStart:", evt); | ||
| 258 | + evt.oldIndex; | ||
| 259 | + }, | ||
| 260 | + onEnd({ newIndex, oldIndex }) { | ||
| 261 | + // console.log("onEnd:", newIndex, oldIndex); | ||
| 262 | + const currRow = _this.tableData.splice(oldIndex, 1)[0]; | ||
| 263 | + _this.tableData.splice(newIndex, 0, currRow); | ||
| 264 | + }, | ||
| 265 | + }); | ||
| 266 | + }, | ||
| 267 | + // 选择上传 | ||
| 268 | + toUpload(options) { | ||
| 269 | + this.$refs.upload.map((item) => { | ||
| 270 | + item.clearFiles(); //上传成功之后清除历史记录 | ||
| 271 | + }); | ||
| 272 | + this.$emit("upload", options); | ||
| 273 | + }, | ||
| 274 | + //移除上传 | ||
| 275 | + onRemoveUpload(file, fileList) { | ||
| 276 | + this.$emit("rmfile", { file, fileList }); | ||
| 277 | + }, | ||
| 278 | + }, | ||
| 279 | + watch: { | ||
| 280 | + data() { | ||
| 281 | + this.$nextTick(() => { | ||
| 282 | + this.useTableFunc("doLayout"); | ||
| 283 | + }); | ||
| 284 | + }, | ||
| 285 | + tableData() { | ||
| 286 | + if (this.tableData.length && this.attrs.isDragSort) { | ||
| 287 | + // 拖拽行更新排序 | ||
| 288 | + // this.rowDrop(); | ||
| 289 | + // 拖拽列更新排序 | ||
| 290 | + this.columnDrop(); | ||
| 291 | + } | ||
| 292 | + }, | ||
| 293 | + }, | ||
| 294 | +}; | ||
| 295 | +</script> | ||
| 296 | +<style lang="scss"> | ||
| 297 | +.el-table { | ||
| 298 | + th { | ||
| 299 | + padding: 0; | ||
| 300 | + } | ||
| 301 | + td { | ||
| 302 | + padding: 0; | ||
| 303 | + } | ||
| 304 | +} | ||
| 305 | +.first-span, | ||
| 306 | +.span { | ||
| 307 | + display: inline-block; | ||
| 308 | +} | ||
| 309 | +.span { | ||
| 310 | + margin-left: 6px; | ||
| 311 | +} | ||
| 312 | +</style> |
-
Please register or login to post a comment