Commit b1fcdaebabecd8a0623b3be0a3c5424fa745a9f6

Authored by 刘汉宸
1 parent 441f73b9

feat: 优化Scheme自定义渲染及详情和删除接口

examples/styles/index.scss
@@ -53,6 +53,21 @@ body { @@ -53,6 +53,21 @@ body {
53 } 53 }
54 } 54 }
55 55
  56 +.zee-scheme__view {
  57 + .el-form-item {
  58 + font-weight: normal !important;
  59 + margin-bottom: 0 !important;
  60 + &__label {
  61 + line-height: 1.5 !important;
  62 + color: #595959 !important;
  63 + }
  64 + &__content {
  65 + line-height: 1.5 !important;
  66 + color: #000 !important;
  67 + }
  68 + }
  69 +}
  70 +
56 @media only screen and (min-width: 1400px) { 71 @media only screen and (min-width: 1400px) {
57 .code-snippet-box { 72 .code-snippet-box {
58 .code-snippet { 73 .code-snippet {
examples/views/docs/component/scheme.md
@@ -111,6 +111,18 @@ export default { @@ -111,6 +111,18 @@ export default {
111 <template> 111 <template>
112 <z-scheme ref="scheme" :list="list" url="/customer" :http="$http" :alias="{ getUrl: '/getCustomerByCode', getKey: 'code' }" auto real-selection> 112 <z-scheme ref="scheme" :list="list" url="/customer" :http="$http" :alias="{ getUrl: '/getCustomerByCode', getKey: 'code' }" auto real-selection>
113 <el-table-column type="selection" align="center" width="40"></el-table-column> 113 <el-table-column type="selection" align="center" width="40"></el-table-column>
  114 + <template #render-code="{ value, row, openView }">
  115 + <el-link type="primary" @click="openView(row)">{{ value }}</el-link>
  116 + </template>
  117 + <template #view-name="{ value }">
  118 + <el-tag size="mini">{{ value }}</el-tag>
  119 + </template>
  120 + <template #cell-name="{ value }">
  121 + <el-tag size="mini" type="danger">{{ value }}</el-tag>
  122 + </template>
  123 + <template #form-id="{ value }">
  124 + <el-tag size="mini">{{ value }}</el-tag>
  125 + </template>
114 </z-scheme> 126 </z-scheme>
115 </template> 127 </template>
116 128
packages/filter/index.vue
1 <template> 1 <template>
2 - <z-form v-model="model" class="zee-filter" :list="formattedList" :span="span" :labelWidth="labelWidth" :colClass="colVisibleRender" :size="size"> 2 + <z-form v-model="model" class="zee-filter" :list="formattedList" :span="span" :labelWidth="labelWidth" :colClass="colVisibleRender" :size="size" :formProps="formProps">
3 <div slot="$operation" class="zee-filter__button-group"> 3 <div slot="$operation" class="zee-filter__button-group">
4 <el-button-group :size="size"> 4 <el-button-group :size="size">
5 - <el-button type="primary" @click="handleSearch" :loading="loading"><span>查询</span></el-button> 5 + <el-button type="primary" @click="handleSearch" :loading="loading" icon="el-icon-search"><span>查询</span></el-button>
6 <el-button @click="handleReset"><span>重置</span></el-button> 6 <el-button @click="handleReset"><span>重置</span></el-button>
7 <el-button v-if="showCollapsed" @click="collapsed = !collapsed"> 7 <el-button v-if="showCollapsed" @click="collapsed = !collapsed">
8 <span>{{ collapsed ? '展开' : '收起' }}</span> 8 <span>{{ collapsed ? '展开' : '收起' }}</span>
9 - <!-- <i :class="`el-icon-arrow-${collapsed ? 'down' : 'up'}`" class="el-icon--right"></i> -->  
10 </el-button> 9 </el-button>
11 </el-button-group> 10 </el-button-group>
12 </div> 11 </div>
@@ -36,6 +35,10 @@ export default { @@ -36,6 +35,10 @@ export default {
36 default: 3, 35 default: 3,
37 }, 36 },
38 loading: Boolean, 37 loading: Boolean,
  38 + formProps: {
  39 + type: Object,
  40 + default: () => ({}),
  41 + },
39 }, 42 },
40 data() { 43 data() {
41 return { 44 return {
packages/form/form-render.vue
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 :class="colClassRender(item, index, colClass)" 47 :class="colClassRender(item, index, colClass)"
48 > 48 >
49 <el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.fullKey" :rules="item.rules" :class="itemClass || 'zee-form__item'"> 49 <el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.fullKey" :rules="item.rules" :class="itemClass || 'zee-form__item'">
50 - <slot v-if="$slots[item.fullKey]" :name="item.fullKey" :value="itemValue(item)" :model="value"></slot> 50 + <slot v-if="$scopedSlots[item.fullKey]" :name="item.fullKey" :value="itemValue(item)" :model1="value"></slot>
51 <template v-else> 51 <template v-else>
52 <!-- 自定义组件 --> 52 <!-- 自定义组件 -->
53 <dynamic-render 53 <dynamic-render
packages/form/index.vue
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 </style> 16 </style>
17 17
18 <template> 18 <template>
19 - <el-form ref="form" :size="size" :class="formClass" :model="formModel" :label-width="labelWidth" :label-position="labelPosition || labelWidth ? 'right' : 'top'"> 19 + <el-form ref="form" :size="size" :class="formClass" :model="formModel" :label-width="labelWidth" :label-position="labelPosition || labelWidth ? 'right' : 'top'" v-bind="formProps">
20 <form-render 20 <form-render
21 :title-class="titleClass" 21 :title-class="titleClass"
22 :content-class="contentClass" 22 :content-class="contentClass"
@@ -64,15 +64,23 @@ export default { @@ -64,15 +64,23 @@ export default {
64 type: Number, 64 type: Number,
65 default: 24, 65 default: 24,
66 }, 66 },
  67 + formProps: {
  68 + type: Object,
  69 + default: () => ({}),
  70 + },
67 }, 71 },
68 data() { 72 data() {
69 return { 73 return {
70 - slotKeys: Object.keys(this.$slots),  
71 model: {}, 74 model: {},
72 formModel: {}, 75 formModel: {},
73 formList: [], 76 formList: [],
74 }; 77 };
75 }, 78 },
  79 + computed: {
  80 + slotKeys() {
  81 + return Object.keys(this.$scopedSlots);
  82 + },
  83 + },
76 watch: { 84 watch: {
77 value: { 85 value: {
78 handler(val = {}) { 86 handler(val = {}) {
packages/scheme/index.vue
@@ -4,44 +4,80 @@ @@ -4,44 +4,80 @@
4 4
5 <template> 5 <template>
6 <div class="zee-scheme"> 6 <div class="zee-scheme">
  7 + <!-- 头部内容 -->
7 <div v-if="$scopedSlots.header || $slots.header" class="zee-scheme__header"> 8 <div v-if="$scopedSlots.header || $slots.header" class="zee-scheme__header">
8 <slot name="header" :filterModel="filterModel" v-bind="_slotScope"></slot> 9 <slot name="header" :filterModel="filterModel" v-bind="_slotScope"></slot>
9 </div> 10 </div>
  11 + <!-- 筛选组件 -->
10 <div class="zee-scheme__filter"> 12 <div class="zee-scheme__filter">
11 - <z-filter v-if="filter" :value="_filterModel" :list="listMap.filter | noRulesFilter" :size="size" @input="onFilterInput" @search="search" :loading="loading"></z-filter> 13 + <z-filter
  14 + v-if="filter"
  15 + :value="_filterModel"
  16 + :list="filterList || listMap.filter | noRulesFilter"
  17 + :size="size"
  18 + @input="onFilterInput"
  19 + @search="search"
  20 + :loading="loading"
  21 + v-bind="filterProps"
  22 + ></z-filter>
12 </div> 23 </div>
  24 + <!-- 按钮区 -->
13 <div v-if="action" class="zee-scheme__action"> 25 <div v-if="action" class="zee-scheme__action">
14 <slot v-if="hadSlot('action')" name="action" v-bind="_slotScope"></slot> 26 <slot v-if="hadSlot('action')" name="action" v-bind="_slotScope"></slot>
15 <template v-else> 27 <template v-else>
16 <el-button :size="size" type="primary" @click="openNew">新增</el-button> 28 <el-button :size="size" type="primary" @click="openNew">新增</el-button>
17 - <slot name="button" :size="size" v-bind="_slotScope"></slot> 29 + <el-button :size="size" plain :disabled="selection.length === 0" @click="handleDeleteMul(selection)">删除</el-button>
  30 + <slot name="button" v-bind="_slotScope"></slot>
18 </template> 31 </template>
19 </div> 32 </div>
  33 + <!-- 表格内容 -->
20 <div class="zee-scheme__table"> 34 <div class="zee-scheme__table">
21 <z-table 35 <z-table
22 ref="table" 36 ref="table"
23 v-model="tableData" 37 v-model="tableData"
24 v-loading="loading" 38 v-loading="loading"
25 - :list="listMap.table" 39 + :list="tableList || listMap.table"
26 :tableProps="{ border: true, 'row-key': 'id', ...tableProps }" 40 :tableProps="{ border: true, 'row-key': 'id', ...tableProps }"
27 :size="size" 41 :size="size"
28 @selection-change="onTableSelectionChange" 42 @selection-change="onTableSelectionChange"
29 @selection="onTableSelection" 43 @selection="onTableSelection"
30 > 44 >
31 <slot></slot> 45 <slot></slot>
  46 + <!-- 表格列内容渲染 -->
  47 + <template v-for="(item, index) in renderList">
  48 + <template v-if="$scopedSlots[`cell-${item.fullKey}`]">
  49 + <el-table-column :slot="item.fullKey" v-bind="item" :prop="item.agentKey || item.key" :key="`table-cell-${index}`">
  50 + <template slot-scope="{ row, column, $index }">
  51 + <slot :name="`cell-${item.fullKey}`" v-bind="{ ...item, ..._slotScope }" :row="row" :value="row[item.key]" :column="column" :index="$index"></slot>
  52 + </template>
  53 + </el-table-column>
  54 + </template>
  55 + <template v-else-if="$scopedSlots[`render-${item.fullKey}`]">
  56 + <el-table-column :slot="item.fullKey" v-bind="item" :prop="item.agentKey || item.key" :key="`table-render-${index}`">
  57 + <template slot-scope="{ row, column, $index }">
  58 + <slot :name="`render-${item.fullKey}`" v-bind="{ ...item, ..._slotScope }" :row="row" :value="row[item.key]" :column="column" :index="$index"></slot>
  59 + </template>
  60 + </el-table-column>
  61 + </template>
  62 + </template>
  63 + <slot slot="column-append" name="column-append" v-bind="_slotScope"></slot>
  64 + <!-- 表格尾追加操作列 -->
32 <template #column-end> 65 <template #column-end>
33 - <el-table-column prop="$operation" label="操作" :width="140" fixed="right"> 66 + <slot slot="column-end" name="column-end" v-bind="_slotScope"></slot>
  67 + <el-table-column v-if="operation" prop="$operation" label="操作" v-bind="{ width: 100, fixed: 'right', ...operationProps }">
34 <div class="zee-scheme__table-operation" slot-scope="slotScope"> 68 <div class="zee-scheme__table-operation" slot-scope="slotScope">
35 - <el-button type="text" icon="el-icon-edit" title="编辑" @click="openEdit(slotScope)"></el-button>  
36 - <el-popconfirm confirmButtonText="确定" cancelButtonText="取消" title="确定删除吗?" placement="top" @onConfirm="handleDelete(slotScope)"> 69 + <el-button type="text" icon="el-icon-edit" title="编辑" @click="openEdit(slotScope.row)"></el-button>
  70 + <el-popconfirm confirmButtonText="确定" cancelButtonText="取消" title="确定删除吗?" placement="top" @onConfirm="handleDelete([slotScope.row])">
37 <el-button slot="reference" type="text" icon="el-icon-delete" title="删除"></el-button> 71 <el-button slot="reference" type="text" icon="el-icon-delete" title="删除"></el-button>
38 </el-popconfirm> 72 </el-popconfirm>
  73 + <slot name="operation-button" v-bind="_slotScope"></slot>
39 </div> 74 </div>
40 </el-table-column> 75 </el-table-column>
41 </template> 76 </template>
42 </z-table> 77 </z-table>
43 </div> 78 </div>
44 - <div v-if="pagination" class="zee-scheme__footer"> 79 + <!-- 底部区域 -->
  80 + <div class="zee-scheme__footer">
45 <div v-if="selection.length > 0" class="selection-info"> 81 <div v-if="selection.length > 0" class="selection-info">
46 <span>已选中</span> 82 <span>已选中</span>
47 <span class="num">{{ selection.length }}</span> 83 <span class="num">{{ selection.length }}</span>
@@ -50,7 +86,9 @@ @@ -50,7 +86,9 @@
50 <el-button slot="reference" :size="size" type="text">清除</el-button> 86 <el-button slot="reference" :size="size" type="text">清除</el-button>
51 </el-popconfirm> 87 </el-popconfirm>
52 </div> 88 </div>
  89 + <!-- 分页器 -->
53 <el-pagination 90 <el-pagination
  91 + v-if="pagination"
54 @size-change="handleSizeChange" 92 @size-change="handleSizeChange"
55 @current-change="handleCurrentChange" 93 @current-change="handleCurrentChange"
56 :current-page="currentPage" 94 :current-page="currentPage"
@@ -61,12 +99,62 @@ @@ -61,12 +99,62 @@
61 > 99 >
62 </el-pagination> 100 </el-pagination>
63 </div> 101 </div>
64 - <el-dialog :visible.sync="dialogVisible" :title="dialogTitle" destroy-on-close append-to-body :lock-scroll="false" :close-on-click-modal="false" @closed="onDialogClosed"> 102 + <!-- 弹出框 -->
  103 + <el-dialog
  104 + :visible.sync="dialogVisible"
  105 + :title="dialogTitle"
  106 + destroy-on-close
  107 + append-to-body
  108 + :lock-scroll="false"
  109 + :close-on-click-modal="false"
  110 + @closed="onDialogClosed"
  111 + v-bind="dialogProps"
  112 + >
65 <div v-loading="dialogLoading"> 113 <div v-loading="dialogLoading">
  114 + <!-- 自定义弹出框标题 -->
66 <slot v-if="hadSlot('dialog-title')" slot="title" name="dialog-title" :dialogType="dialogType" v-bind="_slotScope"></slot> 115 <slot v-if="hadSlot('dialog-title')" slot="title" name="dialog-title" :dialogType="dialogType" v-bind="_slotScope"></slot>
67 <template v-if="dialogRender"> 116 <template v-if="dialogRender">
  117 + <!-- 自定义弹出框内容 -->
68 <slot v-if="hadSlot(`dialog-${dialogType}`)" :name="`dialog-${dialogType}`" :model="_formModel" v-bind="_slotScope"></slot> 118 <slot v-if="hadSlot(`dialog-${dialogType}`)" :name="`dialog-${dialogType}`" :model="_formModel" v-bind="_slotScope"></slot>
69 - <z-form v-else ref="form" :value="_formModel" :list="listMap.form" label-width="80px" :span="12" @input="onFormInput" @validate="onFormValidate"></z-form> 119 + <!-- 内置弹出框新增修改表单 -->
  120 + <template v-if="['new', 'edit'].includes(dialogType)">
  121 + <z-form
  122 + ref="form"
  123 + :value="_formModel"
  124 + :list="formList || listMap.form"
  125 + @input="onFormInput"
  126 + @validate="onFormValidate"
  127 + v-bind="{ span: 12, 'label-width': '80px', ...formProps }"
  128 + >
  129 + <!-- 表单自定义插槽 -->
  130 + <template v-for="item in renderList">
  131 + <template v-if="$scopedSlots[`form-${item.fullKey}`]">
  132 + <slot :slot="item.fullKey" :name="`form-${item.fullKey}`" :value="get(_formModel, item.fullKey)" :row="_formModel" :model="_formModel" v-bind="_slotScope"></slot>
  133 + </template>
  134 + </template>
  135 + </z-form>
  136 + </template>
  137 + <!-- 内置弹出框详情表单 -->
  138 + <template v-else>
  139 + <z-form
  140 + ref="form"
  141 + class="zee-scheme__view"
  142 + :value="_formModel"
  143 + :list="viewList || listMap.form | viewTypeFilter | noRulesFilter"
  144 + v-bind="{ span: 12, 'label-width': '80px', ...viewProps }"
  145 + >
  146 + <!-- 详情自定义插槽渲染 -->
  147 + <template v-for="item in renderList">
  148 + <template v-if="$scopedSlots[`view-${item.fullKey}`]">
  149 + <slot :slot="item.fullKey" :name="`view-${item.fullKey}`" :value="get(_formModel, item.fullKey)" :row="_formModel" :model="_formModel" v-bind="_slotScope"></slot>
  150 + </template>
  151 + <template v-else-if="$scopedSlots[`render-${item.fullKey}`]">
  152 + <slot :slot="item.fullKey" :name="`render-${item.fullKey}`" :value="get(_formModel, item.fullKey)" :row="_formModel" :model="_formModel" v-bind="_slotScope"></slot>
  153 + </template>
  154 + </template>
  155 + </z-form>
  156 + </template>
  157 + <!-- 内置弹出框新增修改按钮 -->
70 <div class="zee-scheme__dialog-button" v-if="['new', 'edit'].includes(dialogType)"> 158 <div class="zee-scheme__dialog-button" v-if="['new', 'edit'].includes(dialogType)">
71 <el-button :size="size" type="primary" @click="handleConfirm" :loading="submitting">确定</el-button> 159 <el-button :size="size" type="primary" @click="handleConfirm" :loading="submitting">确定</el-button>
72 <el-button :size="size" plain @click="closeDialog">取消</el-button> 160 <el-button :size="size" plain @click="closeDialog">取消</el-button>
@@ -78,47 +166,52 @@ @@ -78,47 +166,52 @@
78 </template> 166 </template>
79 167
80 <script> 168 <script>
81 -import { cloneDeep } from '../_utils'; 169 +import { cloneDeep, get } from '../_utils';
82 import { clear } from '../_utils/param'; 170 import { clear } from '../_utils/param';
83 171
  172 +let propsMap = {};
  173 +const propsKeys = ['tableProps', 'filterProps', 'formProps', 'viewProps', 'dialogProps', 'operationProps'];
  174 +propsKeys.forEach(key => {
  175 + propsMap[key] = {
  176 + type: Object,
  177 + default: function() {
  178 + return {};
  179 + },
  180 + };
  181 +});
  182 +const apiKeys = ['searchApi', 'submitApi', 'addApi', 'modifyApi', 'getApi', 'viewApi', 'deleteApi'];
  183 +apiKeys.forEach(key => {
  184 + propsMap[key] = {
  185 + type: Function,
  186 + };
  187 +});
  188 +const blockKeys = ['filter', 'action', 'pagination', 'operation'];
  189 +blockKeys.forEach(key => {
  190 + propsMap[key] = {
  191 + type: Boolean,
  192 + default: true,
  193 + };
  194 +});
  195 +
84 export default { 196 export default {
85 name: 'Scheme', 197 name: 'Scheme',
86 props: { 198 props: {
  199 + ...propsMap,
87 list: Array, 200 list: Array,
88 - filter: {  
89 - type: Boolean,  
90 - default: true,  
91 - },  
92 - action: {  
93 - type: Boolean,  
94 - default: true,  
95 - },  
96 - pagination: {  
97 - type: Boolean,  
98 - default: true,  
99 - }, 201 + filterList: Array,
  202 + tableList: Array,
  203 + formList: Array,
  204 + viewList: Array,
100 size: { 205 size: {
101 type: String, 206 type: String,
102 default: 'mini', 207 default: 'mini',
103 }, 208 },
104 - tableProps: {  
105 - type: Object,  
106 - default: () => ({}),  
107 - },  
108 formModel: Object, 209 formModel: Object,
109 filterModel: Object, 210 filterModel: Object,
110 auto: Boolean, 211 auto: Boolean,
111 realSelection: Boolean, 212 realSelection: Boolean,
112 - /* 模板API */  
113 url: String, // 请求地址 213 url: String, // 请求地址
114 http: [Function, Promise], // http库 214 http: [Function, Promise], // http库
115 - /* 自定义API */  
116 - searchApi: Function, // 搜索  
117 - submitApi: Function, // 提交  
118 - addApi: Function, // 新增  
119 - modifyApi: Function, // 修改  
120 - getApi: Function, // 查询详情  
121 - deleteApi: Function, // 删除  
122 alias: Object, // 别名配置 215 alias: Object, // 别名配置
123 }, 216 },
124 data() { 217 data() {
@@ -161,6 +254,17 @@ export default { @@ -161,6 +254,17 @@ export default {
161 clearRules(list); 254 clearRules(list);
162 return list; 255 return list;
163 }, 256 },
  257 + // 详情类型过滤器
  258 + viewTypeFilter(val = []) {
  259 + let list = cloneDeep(val);
  260 + const clearRules = list => {
  261 + list.forEach(item => {
  262 + item.type = (h, { model, config }) => h('span', config, model[item.key]);
  263 + });
  264 + };
  265 + clearRules(list);
  266 + return list;
  267 + },
164 }, 268 },
165 computed: { 269 computed: {
166 listMap() { 270 listMap() {
@@ -199,6 +303,28 @@ export default { @@ -199,6 +303,28 @@ export default {
199 }); 303 });
200 return array; 304 return array;
201 }, 305 },
  306 + renderList() {
  307 + // 深度克隆传入的列表,避免原始值被修改
  308 + const newList = cloneDeep(this.list);
  309 + // 生成列表值的全路径key,即列表项为对象时,对象内的key与上一级的key合并作为全路径key
  310 + const generateFullKey = (list, parentKey) => {
  311 + list.forEach(item => {
  312 + if (item.group && item.list) {
  313 + if (item.group.key) {
  314 + item.fullKey = `${parentKey ? `${parentKey}-${item.group.key}` : item.group.key}`;
  315 + } else {
  316 + item.fullKey = parentKey || item.key;
  317 + }
  318 + generateFullKey(item.list, item.fullKey);
  319 + } else {
  320 + item.fullKey = `${parentKey ? `${parentKey}-${item.key}` : item.key}`;
  321 + }
  322 + });
  323 + };
  324 + // 生成fullKey
  325 + generateFullKey(newList);
  326 + return newList;
  327 + },
202 _filterModel() { 328 _filterModel() {
203 return this.filterModel || this.filterForm || {}; 329 return this.filterModel || this.filterForm || {};
204 }, 330 },
@@ -209,6 +335,9 @@ export default { @@ -209,6 +335,9 @@ export default {
209 return { 335 return {
210 openDialog: this.openDialog, 336 openDialog: this.openDialog,
211 closeDialog: this.closeDialog, 337 closeDialog: this.closeDialog,
  338 + openView: this.openView,
  339 + handleDelete: this.handleDelete,
  340 + size: this.size,
212 }; 341 };
213 }, 342 },
214 _alias() { 343 _alias() {
@@ -221,6 +350,7 @@ export default { @@ -221,6 +350,7 @@ export default {
221 }, 350 },
222 }, 351 },
223 methods: { 352 methods: {
  353 + get,
224 // 空Promise 354 // 空Promise
225 emptyPromise() { 355 emptyPromise() {
226 return new Promise(resolve => resolve()); 356 return new Promise(resolve => resolve());
@@ -367,17 +497,44 @@ export default { @@ -367,17 +497,44 @@ export default {
367 return undefined; 497 return undefined;
368 }, 498 },
369 // 打开编辑弹出框 499 // 打开编辑弹出框
370 - openEdit({ row }) { 500 + openEdit(row) {
371 this.dialogLoading = true; 501 this.dialogLoading = true;
372 this.openDialog('edit', '编辑'); 502 this.openDialog('edit', '编辑');
373 const getRow = () => 503 const getRow = () =>
374 new Promise(resolve => { 504 new Promise(resolve => {
375 - resolve({ ...row }); 505 + resolve(row);
376 }); 506 });
377 const getAPI = this.getApi || this._getAPI || getRow; 507 const getAPI = this.getApi || this._getAPI || getRow;
378 getAPI(row) 508 getAPI(row)
379 .then(result => { 509 .then(result => {
380 - this.editForm = { ...result }; 510 + this.editForm = result;
  511 + })
  512 + .finally(() => {
  513 + this.dialogLoading = false;
  514 + });
  515 + },
  516 + // 内置查询详情接口
  517 + _viewAPI(row) {
  518 + if (this.url && (this.http || this.zHttp)) {
  519 + const _http = this.http || this.zHttp;
  520 + const _viewKey = this._alias.viewKey || this._alias.getKey || this._alias.primaryKey || 'id';
  521 + const _resultKey = this._alias.result || 'result';
  522 + return _http({ url: `${clear(this.url)}/${this._alias.getUrl || 'queryById'}`, params: { [_viewKey]: row[_viewKey] } }).then(response => response[_resultKey] || {});
  523 + }
  524 + return undefined;
  525 + },
  526 + // 打开详情弹出框
  527 + openView(row) {
  528 + this.dialogLoading = true;
  529 + this.openDialog('view', '详情');
  530 + const getRow = () =>
  531 + new Promise(resolve => {
  532 + resolve(row);
  533 + });
  534 + const viewAPI = this.viewApi || this.getApi || this._viewAPI || this._getAPI || getRow;
  535 + viewAPI(row)
  536 + .then(result => {
  537 + this.editForm = result;
381 }) 538 })
382 .finally(() => { 539 .finally(() => {
383 this.dialogLoading = false; 540 this.dialogLoading = false;
@@ -392,7 +549,7 @@ export default { @@ -392,7 +549,7 @@ export default {
392 return undefined; 549 return undefined;
393 }, 550 },
394 // 删除 551 // 删除
395 - handleDelete({ row, $index }) { 552 + handleDelete(selection) {
396 const loading = this.$loading({ 553 const loading = this.$loading({
397 text: '处理中', 554 text: '处理中',
398 spinner: 'el-icon-loading', 555 spinner: 'el-icon-loading',
@@ -400,7 +557,7 @@ export default { @@ -400,7 +557,7 @@ export default {
400 }); 557 });
401 const deleteAPI = this.deleteApi || this._deleteAPI || this.emptyPromise; 558 const deleteAPI = this.deleteApi || this._deleteAPI || this.emptyPromise;
402 const _deleteKey = this._alias.deleteKey || this._alias.primaryKey || 'id'; 559 const _deleteKey = this._alias.deleteKey || this._alias.primaryKey || 'id';
403 - const keys = [row[_deleteKey]]; 560 + const keys = selection.map(i => i[_deleteKey]);
404 deleteAPI(keys) 561 deleteAPI(keys)
405 .then(() => { 562 .then(() => {
406 this.search(); 563 this.search();
@@ -410,16 +567,30 @@ export default { @@ -410,16 +567,30 @@ export default {
410 loading.close(); 567 loading.close();
411 }); 568 });
412 }, 569 },
  570 + // 批量删除
  571 + handleDeleteMul(selection) {
  572 + this.$confirm(`是否删除这 [${selection.length}] 项?`, '提示', {
  573 + confirmButtonText: '确定',
  574 + cancelButtonText: '取消',
  575 + type: 'warning',
  576 + })
  577 + .then(() => {
  578 + this.handleDelete(selection);
  579 + })
  580 + .catch(() => {});
  581 + },
413 // 打开弹出框 582 // 打开弹出框
414 openDialog(type, title) { 583 openDialog(type, title) {
415 this.dialogVisible = true; 584 this.dialogVisible = true;
416 this.dialogRender = true; 585 this.dialogRender = true;
417 this.dialogType = type; 586 this.dialogType = type;
418 this.dialogTitle = title; 587 this.dialogTitle = title;
  588 + this.$emit('dialog-change', type);
419 }, 589 },
420 // 关闭弹出框 590 // 关闭弹出框
421 closeDialog() { 591 closeDialog() {
422 this.dialogVisible = false; 592 this.dialogVisible = false;
  593 + this.$emit('dialog-change', 'none');
423 }, 594 },
424 // 清空表单 595 // 清空表单
425 clearEditForm() { 596 clearEditForm() {
packages/table/index.vue
@@ -82,9 +82,7 @@ export default { @@ -82,9 +82,7 @@ export default {
82 // 表格参数 82 // 表格参数
83 tableProps: { 83 tableProps: {
84 type: Object, 84 type: Object,
85 - default() {  
86 - return {};  
87 - }, 85 + default: () => ({}),
88 }, 86 },
89 // 表格事件 87 // 表格事件
90 tableEvents: Object, 88 tableEvents: Object,