Skip to content

🐛 [Bug]: dialog-select 数据反查回显功能不太能用 #2570

Closed
@sunny-Fung

Description

@sunny-Fung

Version

3.19.0

Vue Version

3.4.27

Link to minimal reproduction

https://opentiny.design/vue-playground?cmpId=dialog-select&fileName=nest-grid-multi.vue&apiMode=Composition&mode=pc&theme=default

Step to reproduce

  1. 打开演练场,链接
  2. 输入以下代码
  3. 点击“打开窗口”按钮=》检查已选列表与左边表格的数据回显效果=》关闭窗口
  4. 点击“设置初始值”按钮,重复步骤3。可以看出来,初始值只能写死在配置里,不能动态设置(比如我用props传入一个初始值作为配置,是不会生效的)
<template>
  <div class="tiny-demo">
    <tiny-button @click="setValue">设置初始值</tiny-button>
    <tiny-button @click="state.visible = !state.visible">{{ `${state.visible ? '关闭' : '打开'}窗口` }}</tiny-button>
    <p>
      
    </p>
    <tiny-dialog-select
     
      ref="dialogSelect"
      class="tiny-demo-dialog-select"
      :visible="state.visible"
      @update:visible="state.visible = $event"
      popseletor="grid"
      :multi="state.multi"
      :dialog-op="state.dialogOp"
      :grid-op="state.gridOp"
      :pager-op="state.pagerOp"
      :selected-box-op="state.selectedBoxOp"
      :remote-search="remoteSearch"
      :lookup-method="lookupMethod"
      :before-close="beforeClose"
      @size-change="onSizeChange"
      @current-change="onCurrentChange"
      @change="onDialogSelectChange"
      value-field="id"
      text-field="name"
      :main-height="240"
    >
      <template #search>
        <div class="tiny-demo-search">
          <div class="tiny-demo-search-left">
            <tiny-search placeholder="公司名称" is-enter-search @search="onSearch"></tiny-search>
          </div>
          <div class="tiny-demo-search-right">
            <tiny-select
              v-model="state.searchData.city"
              placeholder="选择城市"
              :options="state.options"
              clearable
              @change="onCitySearch"
            ></tiny-select>
          </div>
        </div>
      </template>
    </tiny-dialog-select>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { TinyDialogSelect, TinyButton, TinySearch, TinySelect } from '@opentiny/vue'
import Sortable from 'sortablejs'

// 模拟服务侧数据
const datas = [
  { id: '1', name: 'GFD科技有限公司', city: '福州', province: '福建' },
  { id: '2', name: 'WWW科技有限公司', city: '深圳', province: '广东' },
  { id: '3', name: 'RFV有限责任公司', city: '中山', province: '广东' },
  { id: '4', name: 'TGB科技有限公司', city: '龙岩', province: '福建' },
  { id: '5', name: 'YHN科技有限公司', city: '韶关', province: '广东' },
  { id: '6', name: 'WSX科技有限公司', city: '黄冈', province: '湖北' },
  { id: '7', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
  { id: '8', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' },
  { id: '9', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
  { id: '10', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' }
]

// 接口1:根据一组数据id查询这组数据
const queryRowsByIds = (ids) => {
  console.log(1234)
  return datas.filter((row) => ~ids.indexOf(row.id))
}

// 接口2:分页过滤查询
const queryFilter = (pager, search) => {
  const { currentPage, pageSize } = pager
  const { name, city } = search
  const start = (currentPage - 1) * pageSize
  const end = currentPage * pageSize
  // 过滤:名称模糊匹配,城市精确匹配
  const filtered = datas.filter((row) => (!name || ~row.name.indexOf(name)) && (!city || row.city === city))
  // 分页
  const data = filtered.slice(start, end)

  return { data, total: datas.length }
}

const beforeClose = () => {
  return true
}

const state = reactive({
  multi: true,
  searchData: { name: '', city: '' },
  options: [
    { value: '福州', label: '福州' },
    { value: '深圳', label: '深圳' },
    { value: '赤壁', label: '赤壁' }
  ],
  visible: false,
  dialogOp: {
    top: '20vh',
    width: '800px',
    title: '选择公司',
    beforeClose,
    dialogClass: 'custom-dialog-class'
  },
  gridOp: {
    columns: [
      { field: 'id', title: 'ID', width: 50 },
      { field: 'name', title: '名称', showOverflow: 'tooltip' },
      { field: 'province', title: '省份', width: 80 },
      { field: 'city', title: '城市', width: 80 }
    ],
    data: [], // 多选时生效
    selectConfig: {
      reserve: true,
      checkRowKeys: ['1'] 
    },
    border: false, // 设置边框
    size: 'small', // 设置表格尺寸
    // 单选时生效
    radioConfig: { checkRowKey: '3' }
  },
  pagerOp: {
    currentPage: 1,
    pageSize: 5,
    pageSizes: [5, 10],
    total: 0,
    layout: 'prev, pager, next'
  },
  selectedBoxOp: {
    config: {
      pkField: 'id',
      pkFieldType: 'string',
      showField: ['name', 'city'],
      plugin: Sortable
    }
  }
})

const dialogSelect = ref('')

const onSizeChange = (pageSize) => {
  state.pagerOp.pageSize = pageSize

  dialogSelect.value.valuequeryGridData()
}

const onCurrentChange = (currentPage) => {
  state.pagerOp.currentPage = currentPage

  dialogSelect.value.queryGridData()
}

const onSearch = (key, value) => {
  state.searchData.name = value
  state.pagerOp.currentPage = 1
  dialogSelect.value.queryGridData()
}

const onCitySearch = (value) => {
  state.searchData.city = value
  state.pagerOp.currentPage = 1
  dialogSelect.value.queryGridData()
}

const remoteSearch = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      const res = queryFilter(state.pagerOp, state.searchData)
      // 序列化是为了模拟每次返回的都是新对象
      const copy = JSON.parse(JSON.stringify(res.data))

      state.gridOp.data = copy
      state.pagerOp.total = res.total
      // promise返回执行下一步
      resolve()
    }, 300)
  })
}

const lookupMethod = (values) => {
	console.log('lookupMethod', values)
  return new Promise((resolve) => {
    setTimeout(() => {
      const res = queryRowsByIds(values)
      // 序列化是为了模拟每次返回的都是新对象
      const copy = JSON.parse(JSON.stringify(res))
      resolve(copy)
    }, 300)
  })
}

const onDialogSelectChange = (values, texts, selectedDatas) => {
  // 打印change回调数据,控制台查看
  console.log({ values, texts, selectedDatas })
}

const setValue = () => {
  state.gridOp.selectConfig.checkRowKeys = ['1', '6']
}
</script>

<style scoped lang="less">
.tiny-demo-search {
  display: flex;

  .tiny-demo-search-left {
    flex: 1;
  }

  .tiny-demo-search-right {
    width: 216px;
    margin-left: 8px;
  }
}
</style>

What is expected

我需要对dialog-select做二次封装(固定部分配置),初始值会通过props传入(初始值场景使用普遍,例如编辑功能,需要带出已选的内容数据回显),是很重要的一个需求!!

What is actually happening

目前初始值效果鸡肋,没有人会直接把值写死。

What is your project name

111

Any additional comments (optional)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions