Commit 5eb15c695e161b4b200f9c763265bfdb18b14431

Authored by 刘汉宸
1 parent 6ddd056d

feat: 完善Scheme支持接口对接与表格多选

Showing 1 changed file with 198 additions and 27 deletions   Show diff stats
packages/scheme/index.vue
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 display: flex; 13 display: flex;
14 flex-wrap: wrap; 14 flex-wrap: wrap;
15 align-items: center; 15 align-items: center;
16 - line-height: 1;  
17 justify-content: flex-start; 16 justify-content: flex-start;
  17 + line-height: 1;
18 .el-button + .el-button { 18 .el-button + .el-button {
19 margin-left: 0; 19 margin-left: 0;
20 } 20 }
@@ -23,6 +23,20 @@ @@ -23,6 +23,20 @@
23 margin-bottom: 10px; 23 margin-bottom: 10px;
24 } 24 }
25 } 25 }
  26 + &__table {
  27 + &-operation {
  28 + display: flex;
  29 + flex-wrap: wrap;
  30 + align-items: center;
  31 + justify-content: flex-start;
  32 + .el-button + .el-button {
  33 + margin-left: 0;
  34 + }
  35 + .el-button {
  36 + margin-right: 10px;
  37 + }
  38 + }
  39 + }
26 &__dialog-button { 40 &__dialog-button {
27 display: flex; 41 display: flex;
28 align-items: center; 42 align-items: center;
@@ -32,6 +46,27 @@ @@ -32,6 +46,27 @@
32 &__footer { 46 &__footer {
33 margin-top: 10px; 47 margin-top: 10px;
34 text-align: right; 48 text-align: right;
  49 + display: flex;
  50 + justify-content: space-between;
  51 + align-items: center;
  52 + .selection-info {
  53 + word-break: break-all;
  54 + white-space: nowrap;
  55 + font-size: 12px;
  56 + color: #606266;
  57 + .num {
  58 + color: #000;
  59 + font-weight: bold;
  60 + padding: 0 5px;
  61 + font-size: 16px;
  62 + }
  63 + .el-button {
  64 + margin-left: 5px;
  65 + }
  66 + }
  67 + .el-pagination {
  68 + flex: auto;
  69 + }
35 } 70 }
36 } 71 }
37 </style> 72 </style>
@@ -42,7 +77,7 @@ @@ -42,7 +77,7 @@
42 <slot name="header" :filterModel="filterModel" v-bind="_slotScope"></slot> 77 <slot name="header" :filterModel="filterModel" v-bind="_slotScope"></slot>
43 </div> 78 </div>
44 <div class="zee-scheme__filter"> 79 <div class="zee-scheme__filter">
45 - <z-filter v-if="filter" :value="_filterModel" :list="list | noRulesFilter" :size="size" @input="onFilterInput"></z-filter> 80 + <z-filter v-if="filter" :value="_filterModel" :list="list | noRulesFilter" :size="size" @input="onFilterInput" @search="search" :loading="loading"></z-filter>
46 </div> 81 </div>
47 <div v-if="action" class="zee-scheme__action"> 82 <div v-if="action" class="zee-scheme__action">
48 <slot v-if="hadSlot('action')" name="action" v-bind="_slotScope"></slot> 83 <slot v-if="hadSlot('action')" name="action" v-bind="_slotScope"></slot>
@@ -52,17 +87,38 @@ @@ -52,17 +87,38 @@
52 </template> 87 </template>
53 </div> 88 </div>
54 <div class="zee-scheme__table"> 89 <div class="zee-scheme__table">
55 - <z-table v-model="tableData" :list="list" :tableProps="{ border: true }" :size="size"> 90 + <z-table
  91 + ref="table"
  92 + v-model="tableData"
  93 + v-loading="loading"
  94 + :list="list"
  95 + :tableProps="{ border: true, 'row-key': 'id', ...tableProps }"
  96 + :size="size"
  97 + @selection-change="onTableSelectionChange"
  98 + @selection="onTableSelection"
  99 + >
  100 + <slot></slot>
56 <template #column-end> 101 <template #column-end>
57 <el-table-column prop="$operation" label="操作" :width="140" fixed="right"> 102 <el-table-column prop="$operation" label="操作" :width="140" fixed="right">
58 - <template slot-scope="slotScope"> 103 + <div class="zee-scheme__table-operation" slot-scope="slotScope">
59 <el-button type="text" icon="el-icon-edit" title="编辑" @click="openEdit(slotScope)"></el-button> 104 <el-button type="text" icon="el-icon-edit" title="编辑" @click="openEdit(slotScope)"></el-button>
60 - </template> 105 + <el-popconfirm confirmButtonText="确定" cancelButtonText="取消" title="确定删除吗?" placement="top" @onConfirm="handleDelete(slotScope)">
  106 + <el-button slot="reference" type="text" icon="el-icon-delete" title="删除"></el-button>
  107 + </el-popconfirm>
  108 + </div>
61 </el-table-column> 109 </el-table-column>
62 </template> 110 </template>
63 </z-table> 111 </z-table>
64 </div> 112 </div>
65 - <div class="zee-scheme__footer"> 113 + <div v-if="pagination" class="zee-scheme__footer">
  114 + <div v-if="selection.length > 0" class="selection-info">
  115 + <span>已选中</span>
  116 + <span class="num">{{ selection.length }}</span>
  117 + <span>项</span>
  118 + <el-popconfirm confirmButtonText="确定" cancelButtonText="取消" title="确定清除吗?" placement="top" @onConfirm="clearSelection">
  119 + <el-button slot="reference" :size="size" type="text">清除</el-button>
  120 + </el-popconfirm>
  121 + </div>
66 <el-pagination 122 <el-pagination
67 @size-change="handleSizeChange" 123 @size-change="handleSizeChange"
68 @current-change="handleCurrentChange" 124 @current-change="handleCurrentChange"
@@ -74,14 +130,14 @@ @@ -74,14 +130,14 @@
74 > 130 >
75 </el-pagination> 131 </el-pagination>
76 </div> 132 </div>
77 - <el-dialog :visible.sync="dialogVisible" :title="dialogTitle" destroy-on-close append-to-body :close-on-click-modal="false" @closed="onDialogClosed"> 133 + <el-dialog :visible.sync="dialogVisible" :title="dialogTitle" destroy-on-close append-to-body :lock-scroll="false" :close-on-click-modal="false" @closed="onDialogClosed">
78 <div v-loading="dialogLoading"> 134 <div v-loading="dialogLoading">
79 <slot v-if="hadSlot('dialog-title')" slot="title" name="dialog-title" :dialogType="dialogType" v-bind="_slotScope"></slot> 135 <slot v-if="hadSlot('dialog-title')" slot="title" name="dialog-title" :dialogType="dialogType" v-bind="_slotScope"></slot>
80 <template v-if="dialogRender"> 136 <template v-if="dialogRender">
81 <slot v-if="hadSlot(`dialog-${dialogType}`)" :name="`dialog-${dialogType}`" :model="_formModel" v-bind="_slotScope"></slot> 137 <slot v-if="hadSlot(`dialog-${dialogType}`)" :name="`dialog-${dialogType}`" :model="_formModel" v-bind="_slotScope"></slot>
82 <z-form v-else ref="form" :value="_formModel" :list="list" label-width="80px" :span="12" @input="onFormInput" @validate="onFormValidate"></z-form> 138 <z-form v-else ref="form" :value="_formModel" :list="list" label-width="80px" :span="12" @input="onFormInput" @validate="onFormValidate"></z-form>
83 <div class="zee-scheme__dialog-button" v-if="['new', 'edit'].includes(dialogType)"> 139 <div class="zee-scheme__dialog-button" v-if="['new', 'edit'].includes(dialogType)">
84 - <el-button :size="size" type="primary" @click="handleConfirm">确定</el-button> 140 + <el-button :size="size" type="primary" @click="handleConfirm" :loading="submitting">确定</el-button>
85 <el-button :size="size" plain @click="closeDialog">取消</el-button> 141 <el-button :size="size" plain @click="closeDialog">取消</el-button>
86 </div> 142 </div>
87 </template> 143 </template>
@@ -105,12 +161,26 @@ export default { @@ -105,12 +161,26 @@ export default {
105 type: Boolean, 161 type: Boolean,
106 default: true, 162 default: true,
107 }, 163 },
  164 + pagination: {
  165 + type: Boolean,
  166 + default: true,
  167 + },
108 size: { 168 size: {
109 type: String, 169 type: String,
110 default: 'mini', 170 default: 'mini',
111 }, 171 },
  172 + tableProps: {
  173 + type: Object,
  174 + default: () => ({}),
  175 + },
112 formModel: Object, 176 formModel: Object,
113 filterModel: Object, 177 filterModel: Object,
  178 + auto: Boolean,
  179 + realSelection: Boolean,
  180 + searchAPI: Function,
  181 + submitAPI: Function,
  182 + getAPI: Function,
  183 + deleteAPI: Function,
114 }, 184 },
115 data() { 185 data() {
116 return { 186 return {
@@ -121,17 +191,23 @@ export default { @@ -121,17 +191,23 @@ export default {
121 dialogType: 'none', 191 dialogType: 'none',
122 dialogLoading: false, 192 dialogLoading: false,
123 dialogTitle: '', 193 dialogTitle: '',
124 - dialogCloseCallback: undefined,  
125 currentPage: 1, 194 currentPage: 1,
126 - pageSize: 10, 195 + // pageSize: 10,
  196 + pageSize: 5,
127 total: 127, 197 total: 127,
128 - pageSizes: [10, 20, 50],  
129 - tableData: [  
130 - { name: '张三', age: 16, driver: { name: '王五', bank: { name: '中国银行' } } },  
131 - { name: '李四', age: 24 },  
132 - ], 198 + // pageSizes: [10, 20, 50],
  199 + pageSizes: [1, 2, 5],
  200 + tableData: [],
  201 + submitting: false,
  202 + loading: false,
  203 + selection: [],
133 }; 204 };
134 }, 205 },
  206 + created() {
  207 + if (this.auto) {
  208 + this.search();
  209 + }
  210 + },
135 filters: { 211 filters: {
136 noRulesFilter(val = []) { 212 noRulesFilter(val = []) {
137 let list = cloneDeep(val); 213 let list = cloneDeep(val);
@@ -163,17 +239,95 @@ export default { @@ -163,17 +239,95 @@ export default {
163 }, 239 },
164 }, 240 },
165 methods: { 241 methods: {
  242 + // 空Promise
  243 + emptyPromise() {
  244 + return new Promise(resolve => {
  245 + resolve();
  246 + });
  247 + },
  248 + // 设置第二行选中
  249 + toggleRowSelection() {
  250 + this.tableData.forEach(row => {
  251 + if (this.selection.find(item => item.id === row.id)) {
  252 + this.$refs.table && this.$refs.table.toggleRowSelection(row);
  253 + }
  254 + });
  255 + },
  256 + // 表格选中状态
  257 + onTableSelectionChange(selection, type) {
  258 + if (this.realSelection) {
  259 + if (type === 'check') {
  260 + const result = this.selection || [];
  261 + selection.forEach(item => {
  262 + if (!result.find(i => i.id === item.id)) {
  263 + result.push(item);
  264 + }
  265 + });
  266 + this.selection = result;
  267 + } else if (type === 'uncheck') {
  268 + selection.forEach(i => {
  269 + this.selection = this.selection.filter(item => item.id !== i.id);
  270 + });
  271 + }
  272 + }
  273 + },
  274 + // 表格选中
  275 + onTableSelection(selection) {
  276 + if (!this.realSelection) {
  277 + this.selection = selection;
  278 + }
  279 + },
  280 + // 清除表格选中
  281 + clearSelection() {
  282 + this.$refs.table && this.$refs.table.clearSelection();
  283 + this.selection = [];
  284 + },
  285 + // 搜索
  286 + async search() {
  287 + this.loading = true;
  288 + const params = {
  289 + ...this._filterModel,
  290 + currentPage: this.currentPage,
  291 + pageSize: this.pageSize,
  292 + };
  293 + const searchAPI = this.searchAPI || this.emptyPromise;
  294 + await searchAPI(params)
  295 + .then(response => {
  296 + const { result, totalCount } = response || {};
  297 + this.tableData = result;
  298 + this.total = totalCount;
  299 + this.$nextTick(() => {
  300 + this.toggleRowSelection();
  301 + });
  302 + })
  303 + .catch(() => {
  304 + this.$message.error('失败');
  305 + });
  306 + this.loading = false;
  307 + },
  308 + // 更新筛选model
166 onFilterInput(val) { 309 onFilterInput(val) {
167 this.filterForm = val || {}; 310 this.filterForm = val || {};
168 this.$emit('update:filterModel', val || {}); 311 this.$emit('update:filterModel', val || {});
169 }, 312 },
  313 + // 更新表单model
170 onFormInput(val) { 314 onFormInput(val) {
171 this.editForm = val || {}; 315 this.editForm = val || {};
172 this.$emit('update:formModel', val || {}); 316 this.$emit('update:formModel', val || {});
173 }, 317 },
174 - onFormValidate(valid, model) { 318 + // 表单提交且通过校验
  319 + async onFormValidate(valid, model) {
175 if (valid) { 320 if (valid) {
176 - console.log(model); 321 + this.submitting = true;
  322 + const submitAPI = this.submitAPI || this.emptyPromise;
  323 + await submitAPI(model, { type: this.dialogType })
  324 + .then(() => {
  325 + this.closeDialog();
  326 + })
  327 + .catch(() => {
  328 + this.$message.error('失败');
  329 + });
  330 + this.submitting = false;
177 } 331 }
178 }, 332 },
179 // 表单按钮确定 333 // 表单按钮确定
@@ -193,13 +347,31 @@ export default { @@ -193,13 +347,31 @@ export default {
193 this.openDialog('new', '新增'); 347 this.openDialog('new', '新增');
194 }, 348 },
195 // 打开编辑弹出框 349 // 打开编辑弹出框
196 - openEdit({ row }) { 350 + async openEdit({ row }) {
197 this.dialogLoading = true; 351 this.dialogLoading = true;
198 - setTimeout(() => {  
199 - this.editForm = { ...row };  
200 - this.dialogLoading = false;  
201 - }, 300);  
202 this.openDialog('edit', '编辑'); 352 this.openDialog('edit', '编辑');
  353 + const getRow = () => {
  354 + this.editForm = { ...row };
  355 + };
  356 + const getAPI = this.getAPI || getRow;
  357 + await getAPI(row).then(result => {
  358 + this.editForm = { ...result };
  359 + });
  360 + this.dialogLoading = false;
  361 + },
  362 + // 删除
  363 + async handleDelete({ row, $index }) {
  364 + const deleteAPI = this.deleteAPI || this.emptyPromise;
  365 + const loading = this.$loading({
  366 + text: '处理中',
  367 + spinner: 'el-icon-loading',
  368 + background: 'rgba(255, 255, 255, 0.5)',
  369 + });
  370 + await deleteAPI(row).then(() => {
  371 + this.tableData.splice($index, 1);
  372 + this.$message.success('删除成功');
  373 + });
  374 + loading.close();
203 }, 375 },
204 // 打开弹出框 376 // 打开弹出框
205 openDialog(type, title) { 377 openDialog(type, title) {
@@ -207,32 +379,31 @@ export default { @@ -207,32 +379,31 @@ export default {
207 this.dialogRender = true; 379 this.dialogRender = true;
208 this.dialogType = type; 380 this.dialogType = type;
209 this.dialogTitle = title; 381 this.dialogTitle = title;
210 - this.dialogCloseCallback = undefined;  
211 }, 382 },
212 // 关闭弹出框 383 // 关闭弹出框
213 - closeDialog(callback) { 384 + closeDialog() {
214 this.dialogVisible = false; 385 this.dialogVisible = false;
215 - this.dialogCloseCallback = callback instanceof Event ? undefined : callback;  
216 }, 386 },
217 // 清空表单 387 // 清空表单
218 clearEditForm() { 388 clearEditForm() {
219 this.editForm = {}; 389 this.editForm = {};
220 }, 390 },
221 - // 弹出框关闭 391 + // 弹出框关闭动画结束
222 onDialogClosed() { 392 onDialogClosed() {
223 this.clearEditForm(); 393 this.clearEditForm();
224 this.dialogRender = false; 394 this.dialogRender = false;
225 this.dialogType = 'none'; 395 this.dialogType = 'none';
226 - this.dialogCloseCallback && this.dialogCloseCallback();  
227 }, 396 },
228 // 分页-每页个数 397 // 分页-每页个数
229 handleSizeChange(val) { 398 handleSizeChange(val) {
230 this.pageSize = val; 399 this.pageSize = val;
231 this.currentPage = 1; 400 this.currentPage = 1;
  401 + this.$nextTick(this.search);
232 }, 402 },
233 // 分页-当前页数 403 // 分页-当前页数
234 handleCurrentChange(val) { 404 handleCurrentChange(val) {
235 this.currentPage = val; 405 this.currentPage = val;
  406 + this.$nextTick(this.search);
236 }, 407 },
237 }, 408 },
238 }; 409 };