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 13 display: flex;
14 14 flex-wrap: wrap;
15 15 align-items: center;
16   - line-height: 1;
17 16 justify-content: flex-start;
  17 + line-height: 1;
18 18 .el-button + .el-button {
19 19 margin-left: 0;
20 20 }
... ... @@ -23,6 +23,20 @@
23 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 40 &__dialog-button {
27 41 display: flex;
28 42 align-items: center;
... ... @@ -32,6 +46,27 @@
32 46 &__footer {
33 47 margin-top: 10px;
34 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 72 </style>
... ... @@ -42,7 +77,7 @@
42 77 <slot name="header" :filterModel="filterModel" v-bind="_slotScope"></slot>
43 78 </div>
44 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 81 </div>
47 82 <div v-if="action" class="zee-scheme__action">
48 83 <slot v-if="hadSlot('action')" name="action" v-bind="_slotScope"></slot>
... ... @@ -52,17 +87,38 @@
52 87 </template>
53 88 </div>
54 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 101 <template #column-end>
57 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 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 109 </el-table-column>
62 110 </template>
63 111 </z-table>
64 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 122 <el-pagination
67 123 @size-change="handleSizeChange"
68 124 @current-change="handleCurrentChange"
... ... @@ -74,14 +130,14 @@
74 130 >
75 131 </el-pagination>
76 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 134 <div v-loading="dialogLoading">
79 135 <slot v-if="hadSlot('dialog-title')" slot="title" name="dialog-title" :dialogType="dialogType" v-bind="_slotScope"></slot>
80 136 <template v-if="dialogRender">
81 137 <slot v-if="hadSlot(`dialog-${dialogType}`)" :name="`dialog-${dialogType}`" :model="_formModel" v-bind="_slotScope"></slot>
82 138 <z-form v-else ref="form" :value="_formModel" :list="list" label-width="80px" :span="12" @input="onFormInput" @validate="onFormValidate"></z-form>
83 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 141 <el-button :size="size" plain @click="closeDialog">取消</el-button>
86 142 </div>
87 143 </template>
... ... @@ -105,12 +161,26 @@ export default {
105 161 type: Boolean,
106 162 default: true,
107 163 },
  164 + pagination: {
  165 + type: Boolean,
  166 + default: true,
  167 + },
108 168 size: {
109 169 type: String,
110 170 default: 'mini',
111 171 },
  172 + tableProps: {
  173 + type: Object,
  174 + default: () => ({}),
  175 + },
112 176 formModel: Object,
113 177 filterModel: Object,
  178 + auto: Boolean,
  179 + realSelection: Boolean,
  180 + searchAPI: Function,
  181 + submitAPI: Function,
  182 + getAPI: Function,
  183 + deleteAPI: Function,
114 184 },
115 185 data() {
116 186 return {
... ... @@ -121,17 +191,23 @@ export default {
121 191 dialogType: 'none',
122 192 dialogLoading: false,
123 193 dialogTitle: '',
124   - dialogCloseCallback: undefined,
125 194 currentPage: 1,
126   - pageSize: 10,
  195 + // pageSize: 10,
  196 + pageSize: 5,
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 211 filters: {
136 212 noRulesFilter(val = []) {
137 213 let list = cloneDeep(val);
... ... @@ -163,17 +239,95 @@ export default {
163 239 },
164 240 },
165 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 309 onFilterInput(val) {
167 310 this.filterForm = val || {};
168 311 this.$emit('update:filterModel', val || {});
169 312 },
  313 + // 更新表单model
170 314 onFormInput(val) {
171 315 this.editForm = val || {};
172 316 this.$emit('update:formModel', val || {});
173 317 },
174   - onFormValidate(valid, model) {
  318 + // 表单提交且通过校验
  319 + async onFormValidate(valid, model) {
175 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 347 this.openDialog('new', '新增');
194 348 },
195 349 // 打开编辑弹出框
196   - openEdit({ row }) {
  350 + async openEdit({ row }) {
197 351 this.dialogLoading = true;
198   - setTimeout(() => {
199   - this.editForm = { ...row };
200   - this.dialogLoading = false;
201   - }, 300);
202 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 377 openDialog(type, title) {
... ... @@ -207,32 +379,31 @@ export default {
207 379 this.dialogRender = true;
208 380 this.dialogType = type;
209 381 this.dialogTitle = title;
210   - this.dialogCloseCallback = undefined;
211 382 },
212 383 // 关闭弹出框
213   - closeDialog(callback) {
  384 + closeDialog() {
214 385 this.dialogVisible = false;
215   - this.dialogCloseCallback = callback instanceof Event ? undefined : callback;
216 386 },
217 387 // 清空表单
218 388 clearEditForm() {
219 389 this.editForm = {};
220 390 },
221   - // 弹出框关闭
  391 + // 弹出框关闭动画结束
222 392 onDialogClosed() {
223 393 this.clearEditForm();
224 394 this.dialogRender = false;
225 395 this.dialogType = 'none';
226   - this.dialogCloseCallback && this.dialogCloseCallback();
227 396 },
228 397 // 分页-每页个数
229 398 handleSizeChange(val) {
230 399 this.pageSize = val;
231 400 this.currentPage = 1;
  401 + this.$nextTick(this.search);
232 402 },
233 403 // 分页-当前页数
234 404 handleCurrentChange(val) {
235 405 this.currentPage = val;
  406 + this.$nextTick(this.search);
236 407 },
237 408 },
238 409 };
... ...