123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <template>
- <div class="select-table">
- <div class="select-table-box" :style="{flexDirection: direction}">
- <page-layout-list class="dialog-table">
- <template #filter v-if="searchFieldList && searchFieldList.length>0">
- <cip-search-form v-model:model="searchFilter" v-model:defaultModel="defaultSearchModel" :field-list="searchFieldList" @search="handleSearch" :hideSearch="hideSearch"></cip-search-form>
- </template>
- <cip-table v-if="checkType === 'radio'"
- :hide-index="hideIndex"
- :data="itemList"
- :columns="tableColumns"
- :offset="offset"
- ref="tableRef"
- size="small"
- :select-type="checkType"
- :select-radio="selectRadio"
- :select-label="optionProps.value"
- @current-change="currentChange"
- v-loading="listLoading">
- </cip-table>
- <cip-table v-if="checkType === 'checkbox'"
- :hide-index="hideIndex"
- :data="itemList"
- :columns="tableColumns"
- :offset="offset"
- ref="tableRef"
- size="small"
- :select-type="checkType"
- @select="onSelect"
- @select-all="onSelectAll"
- :selectable="selectable"
- v-loading="listLoading">
- </cip-table>
- <template #pagination v-if="withPagination">
- <cip-pagination v-model:offset="offset"
- v-model:limit="limit"
- :total="total"
- :current-page="currentPage"
- layout="total, sizes, prev, next, jumper"
- prev-text="上一页"
- next-text="下一页"
- @refresh="getItemList"></cip-pagination>
- </template>
- </page-layout-list>
- <slot name="group"></slot>
- <tags :class="{'limited-height': direction.indexOf('column') !== -1}" v-if="!$slots.group && withTags" class="dialog-tags" :style="{flexBasis: direction.includes('row')?'220px':'100px'}" :options="checkOptions" :keyProp="optionProps" @update:options="changeOptions"></tags>
- </div>
- </div>
- </template>
- <script>
- import { useCurd } from '@cip/hooks/use-curd'
- import { useTableCacheSelect } from '@cip/components/hooks/table-cache-select'
- import { ref, computed, nextTick, watch, watchEffect } from 'vue'
- import { ElLoading } from 'element-plus'
- import PageLayoutList from '@cip/components/page-layout/list'
- import CipSearchForm from '@cip/components/cip-search-form'
- import CipTable from '@cip/components/cip-table'
- import CipPagination from '@cip/components/cip-pagination'
- import Tags from './tags'
- import { isEmpty } from '@cip/utils/util'
- export default {
- components: { Tags, PageLayoutList, CipSearchForm, CipTable, CipPagination },
- directives: {
- loading: ElLoading.directive
- },
- props: {
- entity: {},
- curdFn: {},
- tableColumns: {},
- searchFieldList: {},
- modelValue: [String, Object],
- otherValue: String,
- checkedItem: {},
- searchCustomize: {
- type: Boolean,
- default: false
- },
- optionProps: {
- type: Object,
- default: () => ({ label: 'label', value: 'value' })
- },
- defaultSearchFilter: {
- type: Object
- },
- checkType: {
- type: String,
- default: 'radio'
- },
- hideSearch: Boolean,
- withPagination: { // 是否显示分页
- type: Boolean,
- default: true
- },
- hideIndex: { type: Boolean, default: undefined },
- withTags: { type: Boolean, default: true },
- direction: { type: String, default: 'row' } // 布局方向
- },
- emits: ['selectValue', 'customizeSearch'],
- setup (props, { emit }) {
- const checkOptions = computed(() => {
- return cacheSelectedList.value.length === 0 ? props.checkedItem : cacheSelectedList.value
- })
- // 右侧数据改变
- const changeOptions = (item) => {
- cacheSelectedList.value = item
- updateSelectValue(item)
- handleSelectShow()
- }
- const updateSelectValue = (item) => {
- emit('selectValue', item)
- }
- const tableRef = ref()
- const CURD = useCurd(props.entity, { ...props.curdFn, itemType: props.itemType })
- const { itemList, getItemList, searchFilter, search } = CURD
- const defaultSearchModel = ref()
- if (props.defaultSearchFilter) {
- defaultSearchModel.value = { ...props.defaultSearchFilter }
- searchFilter.value = { ...defaultSearchModel.value }
- }
- getItemList()
- const primaryKey = ref(props.optionProps.value)
- const { cacheSelectedList, onSelect, onSelectAll } = useTableCacheSelect(itemList, primaryKey.value, val => {
- // 不为空的值才进行更新
- const selectRows = val.filter(v => v[primaryKey.value])
- if (selectRows.length > 0) {
- updateSelectValue(val)
- }
- })
- // 外层触发请求
- const getTableList = (item = {}) => {
- searchFilter.value = item
- getItemList()
- }
- // 已选择的radio
- const selectRadio = computed(() => {
- return props.checkedItem[primaryKey.value] || radioCache.value
- })
- // radio类型时的缓存
- const radioCache = computed(() => {
- const cache = itemList.value.find(v => v[primaryKey.value] === props.modelValue)
- return cache ? cache[primaryKey.value] : undefined
- })
- const currentChange = (currentRow, oldCurrentRow) => {
- // 单选不能取消,只能有值时才填入
- if (currentRow) {
- updateSelectValue(currentRow)
- }
- }
- // checkbox类型更新选中视图
- const showSelectedView = (rows, select) => {
- nextTick(() => {
- rows.forEach(row => {
- tableRef.value.cipTableRef.toggleRowSelection(row, select)
- })
- })
- }
- // tag组件传入值需要更新table选中视图
- // 目前暂按照String化处理,后续想一下如何处理
- const handleSelectShow = () => {
- const selectedPropsCode = cacheSelectedList.value.map(button => button[primaryKey.value])
- const rows = itemList.value.filter(item => {
- return !selectedPropsCode.map(v => String(v)).includes(String(item[primaryKey.value]))
- })
- showSelectedView(rows, false)
- }
- if (props.checkType === 'checkbox') {
- // 分页切换时缓存数据处理
- watch(itemList, list => {
- cacheHandle()
- })
- } else {
- const unWatch = watchEffect(() => {
- if (props.checkedItem[primaryKey.value]) {
- const checkItem = itemList.value.filter(item => item[primaryKey.value] === props.checkedItem[primaryKey.value])[0]
- if (checkItem) {
- updateSelectValue(checkItem)
- unWatch()
- }
- }
- })
- }
- // 缓存数据处理
- const cacheHandle = () => {
- if (cacheSelectedList.value.length === 0) {
- cacheSelectedList.value = props.checkedItem
- }
- const cacheSelectButtonCode = cacheSelectedList.value.map(button => button[primaryKey.value])
- const rows = itemList.value.filter(item => {
- const selectList = props.checkedItem || cacheSelectButtonCode.includes(item[primaryKey])
- // 从列表中匹配已选中或者缓存中的值
- return selectList.findIndex(v => {
- // primaryKey.value匹配不上的时候,默认为未选中
- if (isEmpty(v[primaryKey.value]) || isEmpty(item[primaryKey.value])) {
- return false
- } else {
- return String(v[primaryKey.value]) === String(item[primaryKey.value])
- }
- }) !== -1
- })
- // 匹配上的值进行选中操作
- showSelectedView(rows, true)
- }
- // 所有column可选
- const selectable = () => () => true
- // 搜索
- const handleSearch = () => {
- search()
- }
- return {
- changeOptions,
- checkOptions,
- getTableList,
- handleSearch,
- ...CURD,
- defaultSearchModel,
- tableRef,
- selectable,
- selectRadio,
- currentChange,
- onSelect,
- onSelectAll,
- cacheSelectedList
- }
- }
- }
- </script>
- <style lang="less" scoped>
- .select-table{
- flex: 1;
- .select-table-box{
- display: flex;
- background: @background;
- padding: 20px;
- }
- .dialog-table{
- flex: 1;
- margin: 0 15px 15px 0;
- padding: 0;
- }
- .dialog-tags{
- padding: 8px 0;
- flex-basis: 220px;
- }
- .limited-height{
- max-height: 200px;
- overflow: auto;
- }
- }
- </style>
|