| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- <template>
- <div id="ym-table-search" class="ym-table-search">
- <div class="main-content">
- <el-form
- ref="form"
- :model="form"
- label-width="78px"
- :inline="false"
- size="small"
- >
- <div style="display: flex; flex-wrap: wrap">
- <!-- 操作栏 -->
- <!-- 常用表单渲染 -->
- <div
- v-for="(item, index) in renderSearchForm"
- :key="index"
- >
- <el-button
- v-if="item.type === 'button'"
- :type="item.danger ? 'danger' : 'primary'"
- size="small"
- @click="item.method"
- >{{ item.text }}</el-button>
- <el-form-item
- :label-width="item.labelWidth"
- :label="item.label"
- :prop="item.prop"
- :required="item.required"
- v-show="!item.isHide"
- >
- <el-input
- v-if="item.type === 'input'"
- v-model="form[item.prop]"
- style="width: 150px;margin-right: 16px;"
- :placeholder="item.placeholder || `请输入${item.label}`"
- :clearable="clearable(item)"
- />
- <el-select
- v-if="item.type === 'select'"
- v-model="form[item.prop]"
- :placeholder="item.placeholder || `请选择${item.label}`"
- :clearable="clearable(item)"
- @change="item.method?item.method(form[item.prop]):''"
- style="width: 150px;margin-right: 16px;"
- >
- <el-option
- v-for="(option, index) in item.options"
- :key="option.value + '' + index"
- :label="option.label"
- :value="option.value"
- />
- </el-select>
- <div style="margin-right: 16px;">
- <el-date-picker
- v-if="isDateType(item.type)"
- v-model="form[item.prop]"
- :value-format="item.valueFormat || dateValueFormat(item.type)"
- :format="item.format"
- :type="item.type"
- :placeholder="item.placeholder || `请选择${item.label}`"
- :picker-options="datePickerOptions(item)"
- :style="{
- width: (item.type === 'datetimerange' || item.type === 'daterange') ? '230px' : '150px'
- }"
- :start-placeholder="item.startPlaceholder || '开始日期'"
- :end-placeholder="item.endPlaceholder || '结束日期'"
- :clearable="clearable(item)"
- />
- </div>
- <el-cascader
- v-if="item.type === 'cascader'"
- ref="areaCascader"
- v-model="form[item.prop]"
- style="width: 150px;margin-right: 16px;"
- :options="item.options || areaOptions"
- :clearable="clearable(item)"
- filterable
- :props="
- Object.assign(
- {
- expandTrigger: 'hover',
- checkStrictly: true,
- label: 'label',
- value: 'value',
- children: 'children',
- },
- item.props
- )
- "
- @change="onAreaChange($event, item.prop)"
- />
- <slot :name="item.slotName" :form="form" :formItem="form[item.prop]" v-if="item.slotName && item.type === 'slot'"></slot>
- </el-form-item>
- </div>
- <!-- 查询操作 -->
- <el-col
- v-if="renderSearchForm.length"
- class="opts-item"
- :span="2"
- style="margin-left: auto;"
- >
- <el-form-item
- class="opts-item-btns"
- :class="{ 'flex-start': renderSearchForm.length === 1 }"
- >
- <el-button
- type="primary"
- :loading="loading"
- @click="onSubmit"
- >查询</el-button>
- <el-button
- v-if="renderSearchForm.length > 1"
- @click="onReset"
- >重置</el-button>
- <!-- <el-button
- v-if="searchForm.length > 5"
- class="dropdown-arrow"
- type="text"
- @click="dropdownAction = !dropdownAction"
- >
- {{ dropdownAction ? "收起" : "展开" }}
- <i
- class="el-icon-d-arrow-right"
- :class="{ active: dropdownAction }"
- />
- </el-button> -->
- </el-form-item>
- </el-col>
- <el-col v-else style="padding-bottom: 20px" :span="24">
- <el-alert
- title="无表单数据"
- type="warning"
- center
- :closable="false"
- show-icon
- />
- </el-col>
- </div>
- </el-form>
- </div>
- <div class="extra-content">
- <slot name="extra" />
- </div>
- </div>
- </template>
- <script>
- import request from '@/utils/request'
- export default {
- name: 'YMTableSearch',
- // inject: ["reload"],
- props: {
- searchForm: {
- type: Array,
- default: () => []
- },
- loading: {
- type: Boolean,
- default: false
- }
- },
- data() {
- return {
- initFlag: true,
- dropdownAction: false,
- form: {},
- areaOptions: [],
- areaListProp: '',
- searchHeight: 0,
- optsCols: 24,
- cancalDebounce: null
- }
- },
- computed: {
- clearable() {
- return item => {
- return item.clearable !== undefined ? item.clearable : true
- }
- },
- // 操作空间占用列数
- actionCols() {
- return this.optsCols
- },
- // 日期类型
- isDateType() {
- return (type) => {
- return (
- 'year/month/date/dates/months/years/week/datetime/datetimerange/daterange/monthrange'.indexOf(
- type
- ) !== -1
- )
- }
- },
- dateValueFormat() {
- return (type) => {
- const valueFormat = {
- year: 'yyyy',
- month: 'yyyy-MM',
- date: 'yyyy-MM-dd',
- dates: 'yyyy-MM-dd',
- months: 'yyyy-MM',
- years: 'yyyy',
- week: 'yyyy-ww',
- datetime: 'yyyy-MM-dd HH:mm:ss',
- datetimerange: 'yyyy-MM-dd HH:mm:ss',
- daterange: 'yyyy-MM-dd'
- }
- return valueFormat[type]
- }
- },
- // 日期选择器配置:默认禁止选择未来日期(当天整天可选),可用 item.pickerOptions 覆盖
- datePickerOptions() {
- return (item) => {
- const defaultDisabled = (time) => {
- const endOfToday = new Date()
- endOfToday.setHours(23, 59, 59, 999)
- return time.getTime() > endOfToday.getTime()
- }
- const itemOptions = item.pickerOptions || {}
- const itemDisabled = itemOptions.disabledDate
- return {
- ...itemOptions,
- disabledDate: itemDisabled || defaultDisabled
- }
- }
- },
- // 查询表单个数
- searchFormNum() {
- return this.renderSearchForm.length
- },
- // 操作表单列数
- colSpan() {
- if (!this.renderSearchForm) {
- this.$message.warning('请配置查询表单')
- return 24
- }
- const remainNum = 3 - (this.searchFormNum % 3)
- return remainNum * 8
- },
- /**
- * 渲染查询表单
- * 收起展开判断
- * @returns {Array}
- */
- renderSearchForm() {
- return this.searchForm.filter((item, index) => {
- return { ...item }
- // if (this.dropdownAction) {
- // return {
- // ...item
- // }
- // } else {
- // if (index < 5) {
- // return {
- // ...item
- // }
- // }
- // }
- })
- }
- },
- // 监听this.form
- watch: {
- form: {
- handler(val) {
- this.$emit('onValueChange', val)
- },
- deep: true
- }
- },
- mounted() {
- this.getWindowInfo()
- window.addEventListener('resize', this.cancalDebounce)
- },
- beforeDestroy() {
- window.removeEventListener('resize', this.cancalDebounce)
- },
- created() {
- this.initData()
- // 是否是区域展示
- const existCasader = this.renderSearchForm.find((item) => item.isArea)
- if (existCasader) {
- console.log('🚀 获取区域数据……')
- this.areaList(existCasader)
- }
- this.cancalDebounce = this.debounce(this.getWindowInfo, 500)
- window.addEventListener('resize', this.cancalDebounce)
- this.getWindowInfo()
- },
- methods: {
- /**
- * 监听元素的变化,刷新布局
- */
- getWindowInfo() {
- const { width } = document.body.getBoundingClientRect()
- // 两列,奇数则12,偶数则24
- if (width < 768) {
- this.optsCols = this.freeSpace(2)
- } else if (width >= 768 && width < 1920) {
- this.optsCols = this.freeSpace(3)
- } else {
- this.optsCols = this.freeSpace(4)
- }
- if (!this.initFlag) {
- console.log('刷新')
- // window.removeEventListener('resize', this.ancalDebounce)
- // this.reload();
- } else {
- this.initFlag = false
- }
- },
- // TODO: 添加显示下拉的判断
- freeSpace(cols) {
- const formLength = this.renderSearchForm.length
- const remainder = formLength % cols
- const eachColNum = 24 / cols
- const remianColNum = 24 - remainder * eachColNum
- return remianColNum
- },
- // 防抖
- debounce(fn, delay) {
- let timer
- return function() {
- if (timer) {
- clearTimeout(timer)
- }
- timer = setTimeout(() => {
- fn()
- }, delay)
- }
- },
- initData() {
- this.form = Object.assign(
- {},
- ...this.searchForm.map((item) => {
- return { [item.prop]: item.default || '' }
- })
- )
- console.table('🚀 初始化查询参数:', this.searchForm, this.form)
- },
- onSubmit() {
- const params = Object.assign({}, this.form, { page: 1 })
- this.$emit('submit', params)
- },
- // 只重置不查询
- resetFields() {
- console.log('🚀 重置查询')
- this.$refs.form.resetFields()
- },
- onReset() {
- this.resetFields()
- this.onSubmit()
- },
- areaList(existCasader) {
- const type = existCasader.isArea
- if (![true, 1, 2, 3, 4, 5].includes(type)) {
- this.$message.error('请设置isArea为1/2/3/4/5/true')
- return
- }
- request({
- url: `/lv/area_list`,
- method: 'get',
- params: {
- type: type === true ? 4 : type
- }
- }).then((res) => {
- // 由于获取出来的数据结构不一样,所以需要根据type来获取数据
- if ([true, 4].includes(type)) {
- this.areaOptions = this.areaOptions.concat(res.data[0].children)
- } else if ([1, 2, 3].includes(type)) {
- this.areaOptions = this.areaOptions.concat(res.data)
- if ([1, 3].includes(type)) {
- this.cascaderProps = Object.assign({}, this.cascaderProps, {
- label: 'name',
- value: 'id'
- })
- }
- }
- if (existCasader?.areaOptions) {
- this.areaOptions = [
- ...existCasader?.areaOptions,
- ...this.areaOptions
- ]
- }
- })
- },
- onAreaChange(value, prop) {
- console.log('🚀 区域变化值:', value, prop)
- this.form[prop] = value
- },
- // 获取地区选中对象
- getAreaValue() {
- if (!this.$refs.areaCascader) return
- return this.$refs.areaCascader[0].getCheckedNodes()
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .ym-table-search {
- flex: 1;
- margin: 0px 16px 16px 16px;
- padding: 12px 20px 0;
- border-radius: 8px;
- background-color: #fff;
- .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item{
- margin-bottom: 16px;
- }
- .el-icon-d-arrow-right {
- transform: rotate(90deg);
- &.active {
- transform: rotate(-90deg);
- }
- }
- .el-row {
- display: flex;
- flex-wrap: wrap;
- // justify-content: space-between;
- }
- // [class*="el-col-"]{
- // flex: 1/3;
- // }
- .el-col {
- padding-right: 24px;
- }
- ::v-deep.el-form-item__label {
- text-align-last: justify;
- }
- .el-form {
- .el-form-item:last-child {
- // margin-bottom: 0;
- }
- }
- ::v-deep .el-form-item__label{
- color: #000;
- font-weight: 500;
- font-size: 16px;
- }
- ::v-deep .opts-item-btns {
- .el-button:first-child {
- margin-left: 24px;
- }
- .el-form-item__content {
- display: flex;
- justify-content: flex-end;
- }
- &.flex-start {
- .el-form-item__content {
- justify-content: flex-start;
- margin-left: 0 !important;
- }
- }
- }
- }
- </style>
|