Commit bf7244a861a8b4293017b6b6d668b5549faf0f02
1 parent
d09a3b67
Exists in
master
and in
1 other branch
完善Scheme组件请求
Showing
10 changed files
with
486 additions
and
98 deletions
Show diff stats
examples/main.js
| ... | ... | @@ -13,7 +13,89 @@ import '@/styles/theme/index.css'; |
| 13 | 13 | import '@/styles/nprogress.scss'; |
| 14 | 14 | import "highlight.js/styles/color-brewer.css"; |
| 15 | 15 | |
| 16 | -Vue.prototype.$axios = axios; | |
| 16 | +import { Notification } from 'element-ui'; | |
| 17 | + | |
| 18 | +const request = axios.create({ | |
| 19 | + baseURL: 'http://47.110.137.80:7101/', | |
| 20 | + timeout: 1000, | |
| 21 | + headers: { | |
| 22 | + 'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NTE4ODM0MTEsInN1YiI6ImFkbWluIiwiY3JlYXRlZCI6MTU1MTg4MzQxMTk2NX0.rocgsQq_EEbBDV-BcHpJCUS92KGjBH-0Pf47IrW9v3aj6xJCoFIrnKX4vtpPfYscTk1roBhR5s3I1DIvT8B9wg' | |
| 23 | + } | |
| 24 | +}); | |
| 25 | + | |
| 26 | +const codeMessage = { | |
| 27 | + 200: '服务器成功返回请求的数据', | |
| 28 | + 201: '新建或修改数据成功。', | |
| 29 | + 202: '一个请求已经进入后台排队(异步任务)', | |
| 30 | + 204: '删除数据成功。', | |
| 31 | + 400: '发出的请求有错误,服务器没有进行新建或修改数据,的操作。', | |
| 32 | + 401: '用户没有权限(令牌、用户名、密码错误)。', | |
| 33 | + 403: '用户得到授权,但是访问是被禁止的。', | |
| 34 | + 404: '发出的请求针对的是不存在的记录,服务器没有进行操作', | |
| 35 | + 406: '请求的格式不可得。', | |
| 36 | + 410: '请求的资源被永久删除,且不会再得到的。', | |
| 37 | + 422: '当创建一个对象时,发生一个验证错误。', | |
| 38 | + 500: '服务器发生错误,请检查服务器', | |
| 39 | + 502: '网关错误', | |
| 40 | + 503: '服务不可用,服务器暂时过载或维护', | |
| 41 | + 504: '网关超时' | |
| 42 | +}; | |
| 43 | + | |
| 44 | +const checkStatus = (response) => { | |
| 45 | + if (response.status >= 200 && response.status < 300) { | |
| 46 | + return response; | |
| 47 | + } | |
| 48 | + const errortext = codeMessage[response.status] || response.statusText; | |
| 49 | + const messageContent = ` | |
| 50 | + ${response.request.responseURL} | |
| 51 | + ${errortext} | |
| 52 | + `; | |
| 53 | + Notification.error({ | |
| 54 | + title: `请求错误 ${response.status}:`, | |
| 55 | + message: messageContent, | |
| 56 | + duration: 3000, | |
| 57 | + }); | |
| 58 | + const error = new Error(errortext); | |
| 59 | + error.name = response.status; | |
| 60 | + error.response = response; | |
| 61 | + return error; | |
| 62 | +} | |
| 63 | + | |
| 64 | +// respone 拦截器 | |
| 65 | +request.interceptors.response.use( | |
| 66 | + response => { | |
| 67 | + const { data = {} } = response; | |
| 68 | + const { businessException, errorCode, message, success } = data; | |
| 69 | + if (success) { | |
| 70 | + return data; | |
| 71 | + } else if (businessException) { | |
| 72 | + if (errorCode) { | |
| 73 | + Notification.error({ | |
| 74 | + title: '提示', | |
| 75 | + message, | |
| 76 | + duration: 3000, | |
| 77 | + }); | |
| 78 | + } | |
| 79 | + return { success: false }; | |
| 80 | + } else { | |
| 81 | + if (errorCode) { | |
| 82 | + Notification.error({ | |
| 83 | + title: '提示', | |
| 84 | + message: codeMessage[errorCode], | |
| 85 | + duration: 3000, | |
| 86 | + }); | |
| 87 | + } | |
| 88 | + return { success: false }; | |
| 89 | + } | |
| 90 | + }, | |
| 91 | + error => { | |
| 92 | + const e = checkStatus(error.response); | |
| 93 | + return { success: false }; | |
| 94 | + }); | |
| 95 | + | |
| 96 | +Vue.prototype.$axios = request; | |
| 97 | + | |
| 98 | + | |
| 17 | 99 | |
| 18 | 100 | // 进度条配置 |
| 19 | 101 | NProgress.configure({ showSpinner: false }); | ... | ... |
examples/router/routes.js
| ... | ... | @@ -54,24 +54,20 @@ const _components = [ |
| 54 | 54 | component: () => import('@/views/docs/scheme.md'), |
| 55 | 55 | }, |
| 56 | 56 | ] |
| 57 | + }, | |
| 58 | + { | |
| 59 | + group: '测试', | |
| 60 | + children: [ | |
| 61 | + { | |
| 62 | + path: 'test', | |
| 63 | + name: 'test', | |
| 64 | + meta: { title: 'Scheme 测试' }, | |
| 65 | + component: () => import('@/views/page/test'), | |
| 66 | + }, | |
| 67 | + ] | |
| 57 | 68 | } |
| 58 | 69 | ] |
| 59 | 70 | |
| 60 | -// const _components = [ | |
| 61 | -// { | |
| 62 | -// path: 'select', | |
| 63 | -// name: 'select', | |
| 64 | -// meta: { title: 'Select 选择器', group }, | |
| 65 | -// component: () => import('@/views/docs/select.md'), | |
| 66 | -// }, | |
| 67 | -// { | |
| 68 | -// path: 'form', | |
| 69 | -// name: 'form', | |
| 70 | -// meta: { title: 'Form 表单' }, | |
| 71 | -// component: () => import('@/views/docs/form.md'), | |
| 72 | -// }, | |
| 73 | -// ] | |
| 74 | - | |
| 75 | 71 | let _components_children = []; |
| 76 | 72 | _components.forEach(data => { |
| 77 | 73 | _components_children = [..._components_children, ...data.children] | ... | ... |
examples/views/docs/scheme.md
| ... | ... | @@ -11,6 +11,9 @@ Scheme是一个数æ®é©±åŠ¨çš„è§£å†³æ–¹æ¡ˆï¼Œé€šè¿‡æ—¢å®šçš„ä¸šåŠ¡é…ç½®å‚æ•°ï¼ |
| 11 | 11 | ```html |
| 12 | 12 | <template> |
| 13 | 13 | <eagle-scheme :list="schemeList"> |
| 14 | + <!-- <div slot="action-bar" slot-scope="{ handleNew }"> | |
| 15 | + <el-button type="warn" @click="handleNew">新增</el-button> | |
| 16 | + </div> --> | |
| 14 | 17 | <el-button slot="action-button" type="success" plain size="small">å¯ç”¨</el-button> |
| 15 | 18 | <el-button slot="action-button" type="danger" plain size="small">ç¦ç”¨</el-button> |
| 16 | 19 | <el-table-column type="selection" width="50" align="center"></el-table-column> |
| ... | ... | @@ -66,9 +69,9 @@ export default { |
| 66 | 69 | { type: 'el-input', key: 'name', label: 'åç§°', rules: [{ required: true, message: '请输入åç§°' }] }, |
| 67 | 70 | { type: 'el-input', key: 'code', label: 'ç¼–ç ', rules: [{ required: true, message: '请输入编ç ' }], |
| 68 | 71 | exclude: 'search', group: { label: '设置', key: 'setting', tip: { content: '哇哦', placement: 'left' } }, tip: 'ç¼–ç 为数å—' }, |
| 69 | - { type: 'el-input', key: 'type', label: '类型', group: { label: '设置', key: 'setting' }, tip: '类型éšä¾¿å¡«' }, | |
| 72 | + { type: 'el-input', key: 'type', label: '类型', group: { label: '设置', key: 'setting', icon: 'edit' }, formScheme: { tip: '类型éšä¾¿å¡«' } }, | |
| 70 | 73 | { type: 'el-input-number', key: 'sort', label: '排åº', include: ['form', 'table'], sortable: true }, |
| 71 | - { type: 'el-input', key: 'status', label: '状æ€', formScheme: { label: '状æ€ç ' } }, | |
| 74 | + { type: 'el-input', key: 'status', label: '状æ€', group: { label: 'ä¿¡æ¯', key: 'info', icon: 'info' }, formScheme: { label: '状æ€ç ' } }, | |
| 72 | 75 | ], |
| 73 | 76 | dataSource: [ |
| 74 | 77 | { label: '选项A', value: 'A' }, | ... | ... |
examples/views/docs/table.md
| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | ```html |
| 12 | 12 | <template> |
| 13 | - <eagle-table ref="table" :value="tableData" :list="tableList" :tableProps="tableProps"></eagle-table> | |
| 13 | + <eagle-table ref="table" :value="tableData" :list="tableList"></eagle-table> | |
| 14 | 14 | </template> |
| 15 | 15 | |
| 16 | 16 | <script> |
| ... | ... | @@ -23,9 +23,6 @@ export default { |
| 23 | 23 | { name: '项叔', address: '大楚小区', postcode: 555, number: '北城3号院' }, |
| 24 | 24 | { name: '项季', address: '大楚小区', postcode: 555, number: '北城4号院' }, |
| 25 | 25 | ], |
| 26 | - tableProps: { | |
| 27 | - border: true | |
| 28 | - }, | |
| 29 | 26 | tableList: [ |
| 30 | 27 | { key: 'name', label: '名称', |
| 31 | 28 | formatter(row, column) { |
| ... | ... | @@ -107,7 +104,7 @@ export default { |
| 107 | 104 | } |
| 108 | 105 | }, |
| 109 | 106 | mounted() { |
| 110 | - console.log(this.$refs.table.tableInstance); | |
| 107 | + console.log(this.$refs.table.instance); | |
| 111 | 108 | }, |
| 112 | 109 | methods: { |
| 113 | 110 | handleSubmit(value) { | ... | ... |
| ... | ... | @@ -0,0 +1,83 @@ |
| 1 | +<template> | |
| 2 | + <eagle-scheme | |
| 3 | + :option="{ $http: $axios, url: '/dataDictionary', detailMethod: 'queryById', getMethod: 'queryById', editMethod: 'modify' }" | |
| 4 | + :list="schemeList" | |
| 5 | + :formProps="{ span: 24, 'label-width': '60px' }" | |
| 6 | + :detailProps="{ span: 24, 'label-width': '50px' }" | |
| 7 | + :dialogProps="dialogProps" | |
| 8 | + @dialog-change="handleDialogChange" | |
| 9 | + ></eagle-scheme> | |
| 10 | +</template> | |
| 11 | + | |
| 12 | +<script> | |
| 13 | +export default { | |
| 14 | + name: 'test', | |
| 15 | + data() { | |
| 16 | + return { | |
| 17 | + schemeList: [ | |
| 18 | + { type: 'el-input', label: 'ID', key: 'id', include: 'form', visible: (model, { formMode } = {}) => { return formMode == 'edit' }, | |
| 19 | + props: { disabled: true }, | |
| 20 | + }, | |
| 21 | + { type: 'el-input', label: '编码', key: 'code', exclude: 'search', | |
| 22 | + rules: [{ required: true, message: '编码不能为空', trigger: 'blur' }], | |
| 23 | + props: { placeholder: '编码' }, | |
| 24 | + }, | |
| 25 | + { type: 'el-input', label: '名称', key: 'name', | |
| 26 | + rules: [{ required: true, message: '名称不能为空', trigger: 'blur' }], | |
| 27 | + props: { placeholder: '名称' }, | |
| 28 | + }, | |
| 29 | + { type: 'el-input', label: '备注', key: 'remark', include: 'table', | |
| 30 | + props: { placeholder: '备注' }, | |
| 31 | + }, | |
| 32 | + ], | |
| 33 | + dialogType: '', | |
| 34 | + } | |
| 35 | + }, | |
| 36 | + computed: { | |
| 37 | + dialogProps() { | |
| 38 | + return { width: this.dialogType === 'dialog-form' ? '500px' : '400px' }; | |
| 39 | + } | |
| 40 | + }, | |
| 41 | + methods: { | |
| 42 | + async searchAPI(param) { | |
| 43 | + return this.$axios.get(`/dataDictionary/page?current=1&size=10`) | |
| 44 | + .then((response) => { | |
| 45 | + const { result = [], totalCount = 0 } = response || {}; | |
| 46 | + return { result, totalCount }; | |
| 47 | + }).catch(() => { | |
| 48 | + return {}; | |
| 49 | + }); | |
| 50 | + }, | |
| 51 | + async getAPI(param) { | |
| 52 | + return this.$axios.get(`/dataDictionary/queryById?id=${param.id}`) | |
| 53 | + .then((response) => { | |
| 54 | + const { result = {} } = response || {}; | |
| 55 | + return result; | |
| 56 | + }).catch(() => { | |
| 57 | + return {}; | |
| 58 | + }); | |
| 59 | + }, | |
| 60 | + async newAPI(param) { | |
| 61 | + return this.$axios.post('/dataDictionary/add', param) | |
| 62 | + .then((response) => { | |
| 63 | + const { success = false } = response || {}; | |
| 64 | + return success; | |
| 65 | + }).catch(() => { | |
| 66 | + return false; | |
| 67 | + }); | |
| 68 | + }, | |
| 69 | + async editAPI(param) { | |
| 70 | + return this.$axios.post('/dataDictionary/modify', param) | |
| 71 | + .then((response) => { | |
| 72 | + const { success = false } = response || {}; | |
| 73 | + return success; | |
| 74 | + }).catch(() => { | |
| 75 | + return false; | |
| 76 | + }); | |
| 77 | + }, | |
| 78 | + handleDialogChange(type) { | |
| 79 | + this.dialogType = type; | |
| 80 | + } | |
| 81 | + } | |
| 82 | +} | |
| 83 | +</script> | |
| 0 | 84 | \ No newline at end of file | ... | ... |
packages/detail/index.vue
packages/form/index.vue
| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | </style> |
| 18 | 18 | |
| 19 | 19 | <template> |
| 20 | - <el-form class="eagle-form" ref="form" :model="model" v-bind="formProps"> | |
| 20 | + <el-form class="eagle-form" ref="form" :model="model" v-bind="{ size: 'small', 'label-width': '90px', ...formProps }"> | |
| 21 | 21 | <el-row :gutter="15"> |
| 22 | 22 | <template v-for="(data, index) in listOption.dataList"> |
| 23 | 23 | <template v-if="listOption.isGroup"> |
| ... | ... | @@ -72,12 +72,7 @@ export default { |
| 72 | 72 | // 表单参数 |
| 73 | 73 | formProps: { |
| 74 | 74 | type: Object, |
| 75 | - default() { | |
| 76 | - return { | |
| 77 | - size: 'small', | |
| 78 | - 'label-width': '70px' | |
| 79 | - } | |
| 80 | - } | |
| 75 | + default() { return {} } | |
| 81 | 76 | }, |
| 82 | 77 | // 纯净提交 |
| 83 | 78 | submitPure: { |
| ... | ... | @@ -87,13 +82,15 @@ export default { |
| 87 | 82 | // 底部样式 |
| 88 | 83 | footerStyle: { |
| 89 | 84 | type: [String, Object], |
| 90 | - default: 'text-align: center' | |
| 85 | + default: 'text-align: center;margin-top: 20px;' | |
| 91 | 86 | }, |
| 92 | 87 | // 表单项占位 |
| 93 | 88 | span: { |
| 94 | 89 | type: Number, |
| 95 | 90 | default: 24 |
| 96 | - } | |
| 91 | + }, | |
| 92 | + // 用于做动态判断的参数集 | |
| 93 | + params: Object, | |
| 97 | 94 | }, |
| 98 | 95 | data() { |
| 99 | 96 | return { |
| ... | ... | @@ -199,7 +196,7 @@ export default { |
| 199 | 196 | bindItemEvent(item) { |
| 200 | 197 | if (item.on) { |
| 201 | 198 | if (typeof item.on === 'function') { |
| 202 | - return item.on(this.model); | |
| 199 | + return item.on(this.model, this.params); | |
| 203 | 200 | } else { |
| 204 | 201 | return item.on |
| 205 | 202 | } |
| ... | ... | @@ -218,9 +215,9 @@ export default { |
| 218 | 215 | let visible = true; |
| 219 | 216 | const item = this.listKeySet[key] || {}; |
| 220 | 217 | if (typeof item.visible === 'function') { |
| 221 | - visible = item.visible({ ...this.model }); // 返回model的复制结果,判断类属性禁止改变model,防止循环导致内存溢出 | |
| 218 | + visible = item.visible({ ...this.model }, this.params); // 返回model的复制结果,判断类属性禁止改变model,防止循环导致内存溢出 | |
| 222 | 219 | } else { |
| 223 | - visible = item.visible === undefined ? true : item.visible; // 没有定义visible时返回true,否则返回visible定义的值。【注意:不可写成“ !item.visible ”】 | |
| 220 | + visible = item.visible === undefined ? true : item.visible; // 没有定义visible时返回true,否则返回visible定义的值(包括false)。【注意:不可写成“ !item.visible ”】 | |
| 224 | 221 | } |
| 225 | 222 | return visible; |
| 226 | 223 | }, |
| ... | ... | @@ -228,7 +225,7 @@ export default { |
| 228 | 225 | bindItemVisible(visible = true) { |
| 229 | 226 | let result = visible; |
| 230 | 227 | if (typeof visible === 'function') { |
| 231 | - result = visible(this.model); | |
| 228 | + result = visible(this.model, this.params); | |
| 232 | 229 | } |
| 233 | 230 | return result; |
| 234 | 231 | }, |
| ... | ... | @@ -236,7 +233,7 @@ export default { |
| 236 | 233 | bindItemShow(show = true) { |
| 237 | 234 | let result = show; |
| 238 | 235 | if (typeof show === 'function') { |
| 239 | - result = show(this.model); | |
| 236 | + result = show(this.model, this.params); | |
| 240 | 237 | } |
| 241 | 238 | return result; |
| 242 | 239 | }, |
| ... | ... | @@ -246,7 +243,7 @@ export default { |
| 246 | 243 | let result = { ...props }; |
| 247 | 244 | Object.keys(result).forEach(key => { |
| 248 | 245 | if (typeof result[key] === 'function') { |
| 249 | - result[key] = result[key](this.model); | |
| 246 | + result[key] = result[key](this.model, this.params); | |
| 250 | 247 | } |
| 251 | 248 | }); |
| 252 | 249 | return result; | ... | ... |
packages/scheme/index.vue
| ... | ... | @@ -33,9 +33,11 @@ |
| 33 | 33 | display: flex; |
| 34 | 34 | align-items: center; |
| 35 | 35 | } |
| 36 | -.eagle-scheme__table .eagle-scheme__table-btn:not(:first-child) { | |
| 37 | - padding-left: 10px; | |
| 36 | +.eagle-scheme__table .eagle-scheme__table-btn:not(:last-child) { | |
| 37 | + padding-left: 0px; | |
| 38 | + padding-right: 10px; | |
| 38 | 39 | margin-left: 0px; |
| 40 | + margin-right: 0px; | |
| 39 | 41 | } |
| 40 | 42 | .eagle-scheme__pagination { |
| 41 | 43 | text-align: right; |
| ... | ... | @@ -59,17 +61,20 @@ |
| 59 | 61 | </div> |
| 60 | 62 | <!-- 操作按钮栏 --> |
| 61 | 63 | <div v-if="!option.showActionBar" class="eagle-scheme__action" v-loading="tableLoading" element-loading-spinner="none" element-loading-background="rgba(255, 255, 255, 0.6)"> |
| 62 | - <el-button class="eagle-scheme__action-btn" type="primary" size="small" @click="handleNew">新增</el-button> | |
| 63 | - <el-button v-if="hasSelectionSlot" :disabled="tableSelection && tableSelection.length <= 0" class="eagle-scheme__action-btn" plain size="small" @click="handleDelete('more')">删除</el-button> | |
| 64 | - <slot v-if="$scopedSlots['action-button'] || $slots['action-button']" name="action-button" class="eagle-scheme__action-btn" :model="formModel" :selection="tableSelection" :setDialog="setDialog"></slot> | |
| 65 | - <div v-if="hasSelectionSlot && tableSelection && tableSelection.length > 0" class="eagle-scheme__action-btn eagle-scheme__text-selection">已选中<span class="eagle-scheme__text-selection-highlight">{{ tableSelection.length }}</span>项</div> | |
| 64 | + <slot v-if="$scopedSlots['action-bar'] || $slots['action-bar']" name="action-bar" :handleNew="handleNew" :handleDelete="handleDelete" :model="formModel" :selection="tableSelection" :setDialog="setDialog"></slot> | |
| 65 | + <template v-else> | |
| 66 | + <el-button class="eagle-scheme__action-btn" type="primary" size="small" @click="handleNew">新增</el-button> | |
| 67 | + <el-button v-if="hasSelectionSlot" :disabled="tableSelection && tableSelection.length <= 0" class="eagle-scheme__action-btn" plain size="small" @click="handleDelete('more')">删除</el-button> | |
| 68 | + <slot v-if="$scopedSlots['action-button'] || $slots['action-button']" name="action-button" class="eagle-scheme__action-btn" :model="formModel" :selection="tableSelection" :setDialog="setDialog"></slot> | |
| 69 | + <div v-if="hasSelectionSlot && tableSelection && tableSelection.length > 0" class="eagle-scheme__action-btn eagle-scheme__text-selection">已选中<span class="eagle-scheme__text-selection-highlight">{{ tableSelection.length }}</span>项</div> | |
| 70 | + </template> | |
| 66 | 71 | </div> |
| 67 | 72 | <div class="eagle-scheme__table"> |
| 68 | 73 | <!-- 表格 --> |
| 69 | 74 | <eagle-table ref="eagle-table" :list="_tableList" :value="tableData" |
| 70 | 75 | v-loading="tableLoading" |
| 71 | 76 | element-loading-background="rgba(255, 255, 255, 0.6)" |
| 72 | - :tableProps="{ size: 'small', border: true, 'row-key': 'id', ...tableProps }" | |
| 77 | + :tableProps="{ border: true, 'row-key': 'id', ...tableProps }" | |
| 73 | 78 | :tableEvents="{ |
| 74 | 79 | 'selection-change': handleTableSelectionChange, |
| 75 | 80 | ...tableEvents, |
| ... | ... | @@ -109,8 +114,8 @@ |
| 109 | 114 | :page-size="pageSize" :total="totalCount" v-bind="{ 'page-sizes': [10, 20, 50], layout: 'total, sizes, prev, pager, next, jumper', ...paginationProps }"></el-pagination> |
| 110 | 115 | </div> |
| 111 | 116 | </div> |
| 112 | - <el-dialog :custom-class="dialogProps['custom-class'] || 'eagle-scheme__dialog'" :title="dialogProps.title || dialogTitle" :visible.sync="dialogVisible" v-bind="{ width: '65%', ...dialogProps }"> | |
| 113 | - <eagle-form v-if="dialogType === 'dialog-form' && !$scopedSlots['dialog-form'] && !$slots['dialog-form']" :list="_formList" v-model="formModel" :span="formProps.span || 12" :formProps="{ size: 'small', 'label-width': '90px', ...formProps }" @submit="handleSubmit" @cancel="handleCancel"> | |
| 117 | + <el-dialog v-loading="dialogLoading" element-loading-background="rgba(255, 255, 255, 0.3)" :custom-class="dialogProps['custom-class'] || 'eagle-scheme__dialog'" :title="dialogProps.title || dialogTitle" :visible.sync="dialogVisible" v-bind="{ width: '65%', ...dialogProps }"> | |
| 118 | + <eagle-form v-if="dialogType === 'dialog-form' && !$scopedSlots['dialog-form'] && !$slots['dialog-form']" :list="_formList" v-model="formModel" :params="{ formMode }" :span="formProps.span || 12" :formProps="formProps" @submit="handleSubmit" @cancel="handleCancel"> | |
| 114 | 119 | <!-- 表单分组具名插槽 --> |
| 115 | 120 | <template v-for="key in formGroupSlotsKeys"> |
| 116 | 121 | <slot v-if="$scopedSlots[`form-${key}`] || $slots[`form-${key}`]" :name="`form-${key}`" :slot="key" :model="formModel"></slot> |
| ... | ... | @@ -120,7 +125,7 @@ |
| 120 | 125 | <slot v-if="$scopedSlots[`form-item-${item.key}`] || $slots[`form-item-${item.key}`]" :name="`form-item-${item.key}`" :slot="`item-${item.key}`" :model="formModel"></slot> |
| 121 | 126 | </template> |
| 122 | 127 | </eagle-form> |
| 123 | - <eagle-detail v-else-if="dialogType === 'dialog-view' && !$scopedSlots['dialog-view'] && !$slots['dialog-view']" v-model="formModel" :list="_formList"> | |
| 128 | + <eagle-detail v-else-if="dialogType === 'dialog-view' && !$scopedSlots['dialog-view'] && !$slots['dialog-view']" v-model="formModel" :list="list || detailList || _formList" :span="detailProps.span || 8" :detailProps="detailProps"> | |
| 124 | 129 | <!-- 表单分组具名插槽 --> |
| 125 | 130 | <template v-for="key in formGroupSlotsKeys"> |
| 126 | 131 | <slot v-if="$scopedSlots[`view-${key}`] || $slots[`view-${key}`]" :name="`view-${key}`" :slot="key" :model="formModel"></slot> |
| ... | ... | @@ -138,6 +143,9 @@ |
| 138 | 143 | |
| 139 | 144 | <script> |
| 140 | 145 | import { generateListSpace } from './parser'; |
| 146 | +import { stringify } from './utils'; | |
| 147 | + | |
| 148 | +let _$http = null; | |
| 141 | 149 | |
| 142 | 150 | export default { |
| 143 | 151 | name: 'Scheme', |
| ... | ... | @@ -155,6 +163,8 @@ export default { |
| 155 | 163 | formList: Array, |
| 156 | 164 | // 表格配置 |
| 157 | 165 | tableList: Array, |
| 166 | + // 详情配置 | |
| 167 | + detailList: Array, | |
| 158 | 168 | // 表格参数 |
| 159 | 169 | tableProps: { |
| 160 | 170 | type: Object, |
| ... | ... | @@ -170,6 +180,11 @@ export default { |
| 170 | 180 | type: Object, |
| 171 | 181 | default() { return {} } |
| 172 | 182 | }, |
| 183 | + // 详情参数 | |
| 184 | + detailProps: { | |
| 185 | + type: Object, | |
| 186 | + default() { return {} } | |
| 187 | + }, | |
| 173 | 188 | // 分页参数 |
| 174 | 189 | paginationProps: { |
| 175 | 190 | type: Object, |
| ... | ... | @@ -179,7 +194,7 @@ export default { |
| 179 | 194 | dialogProps: { |
| 180 | 195 | type: Object, |
| 181 | 196 | default() { return {} } |
| 182 | - } | |
| 197 | + }, | |
| 183 | 198 | }, |
| 184 | 199 | data() { |
| 185 | 200 | return { |
| ... | ... | @@ -191,6 +206,8 @@ export default { |
| 191 | 206 | _formList: [], |
| 192 | 207 | // 表单值 |
| 193 | 208 | formModel: {}, |
| 209 | + // 表单模式 新增(new)/编辑(edit)/详情(view) | |
| 210 | + formMode: 'new', | |
| 194 | 211 | // 表格配置 |
| 195 | 212 | _tableList: [], |
| 196 | 213 | // 当前页 |
| ... | ... | @@ -205,25 +222,10 @@ export default { |
| 205 | 222 | dialogTitle: '', |
| 206 | 223 | // 弹出框类型 |
| 207 | 224 | dialogType: '', |
| 225 | + // 弹出框加载状态 | |
| 226 | + dialogLoading: false, | |
| 208 | 227 | // 表格数据 |
| 209 | - tableData: [ | |
| 210 | - { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' }, | |
| 211 | - { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' }, | |
| 212 | - { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: 'active' }, | |
| 213 | - { name: '李季', code: 'U00004', type: 'user', sort: 3, status: 'active' }, | |
| 214 | - { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: '' }, | |
| 215 | - { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' }, | |
| 216 | - { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' }, | |
| 217 | - { name: '李季', code: 'U00004', type: 'user', sort: 3, status: 'active' }, | |
| 218 | - { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' }, | |
| 219 | - { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' }, | |
| 220 | - { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' }, | |
| 221 | - { name: '李季', code: 'U00004', type: 'user', sort: 3, status: '' }, | |
| 222 | - { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' }, | |
| 223 | - { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: '' }, | |
| 224 | - { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' }, | |
| 225 | - { name: '李季', code: 'U00004', type: 'user', sort: 3, status: '' }, | |
| 226 | - ], | |
| 228 | + tableData: [], | |
| 227 | 229 | // 表格选中项 |
| 228 | 230 | tableSelection: [], |
| 229 | 231 | // 表格加载状态 |
| ... | ... | @@ -244,13 +246,16 @@ export default { |
| 244 | 246 | this._tableList = this.tableList || []; |
| 245 | 247 | } |
| 246 | 248 | this.totalCount = this.tableData.length; |
| 249 | + // 传入axios标准的http库 | |
| 250 | + if (this.option.$http) { | |
| 251 | + _$http = this.option.$http; | |
| 252 | + } | |
| 247 | 253 | }, |
| 248 | 254 | mounted() { |
| 249 | - this.$axios.get('http://47.110.137.80:7102/article/categoryCode') | |
| 250 | - .then((response) => { | |
| 251 | - // handle success | |
| 252 | - console.log(response); | |
| 253 | - }); | |
| 255 | + // 设置自动加载数据 | |
| 256 | + if (!this.option.auto) { | |
| 257 | + this.handleSearch(); | |
| 258 | + } | |
| 254 | 259 | }, |
| 255 | 260 | computed: { |
| 256 | 261 | // 解析表单组件分组具名插槽名称 |
| ... | ... | @@ -274,17 +279,45 @@ export default { |
| 274 | 279 | }, |
| 275 | 280 | methods: { |
| 276 | 281 | // 查询数据 |
| 277 | - handleSearch(param) { | |
| 278 | - this.tableLoading = true; | |
| 279 | - setTimeout(() => { | |
| 280 | - this.tableLoading = false; | |
| 281 | - console.log({ | |
| 282 | - param, | |
| 283 | - searchModel: this.searchModel, | |
| 284 | - currentPage: this.currentPage, | |
| 285 | - pageSize: this.pageSize | |
| 282 | + async handleSearch(value) { | |
| 283 | + const param = { | |
| 284 | + ...this.searchModel, | |
| 285 | + ...value, | |
| 286 | + currentPage: this.currentPage, | |
| 287 | + pageSize: this.pageSize | |
| 288 | + }; | |
| 289 | + this.doSearch(param); | |
| 290 | + }, | |
| 291 | + // 查询数据逻辑 | |
| 292 | + async doSearch(param) { | |
| 293 | + if (this.option.searchAPI) { // 配置了自定义查询API的情况 | |
| 294 | + console.log('searchAPI'); | |
| 295 | + this.tableLoading = true; | |
| 296 | + try { | |
| 297 | + const { result = [], totalCount = 0 } = await this.option.searchAPI(param); | |
| 298 | + this.tableData = result; | |
| 299 | + this.totalCount = totalCount; | |
| 300 | + } catch (error) { | |
| 301 | + console.error(error); | |
| 302 | + } finally { | |
| 303 | + this.tableLoading = false; | |
| 304 | + } | |
| 305 | + } else if (_$http && this.option.url) { // 给定了http的情况 | |
| 306 | + console.log('_$http search'); | |
| 307 | + this.tableLoading = true; | |
| 308 | + _$http.get(`${this.option.url.trim('/')}/${this.option.searchMethod || 'page'}?${stringify(param)}`) | |
| 309 | + .then((response) => { | |
| 310 | + const { result = [], totalCount = 0 } = response || {}; | |
| 311 | + this.tableData = result; | |
| 312 | + this.totalCount = totalCount; | |
| 313 | + }) | |
| 314 | + .finally(() => { | |
| 315 | + this.tableLoading = false; | |
| 286 | 316 | }); |
| 287 | - }, 2000); | |
| 317 | + } else { | |
| 318 | + this.tableLoading = true; | |
| 319 | + setTimeout(() => { this.tableLoading = false; }, 1500); | |
| 320 | + } | |
| 288 | 321 | }, |
| 289 | 322 | // 查看按钮 |
| 290 | 323 | handleView({ row }) { |
| ... | ... | @@ -292,11 +325,43 @@ export default { |
| 292 | 325 | this.dialogType = 'dialog-view'; |
| 293 | 326 | this.tableCurrentRow = row; |
| 294 | 327 | this.formModel = {}; |
| 295 | - // 设置表单值 | |
| 296 | - Object.keys(row).forEach(key => { | |
| 297 | - this.formModel[key] = row[key]; | |
| 298 | - }); | |
| 328 | + this.formMode = "view"; | |
| 329 | + this.$emit('dialog-change', this.dialogType); | |
| 299 | 330 | this.showDialog(); |
| 331 | + this.doDetail(row); | |
| 332 | + }, | |
| 333 | + // 查询单项数据详情 | |
| 334 | + async doDetail(param) { | |
| 335 | + const { primaryKey = 'id', detailPrimaryKey } = this.option || {}; | |
| 336 | + if (this.option.detailAPI) { // 配置了自定义查询API的情况 | |
| 337 | + console.log('detailAPI'); | |
| 338 | + this.dialogLoading = true; | |
| 339 | + try { | |
| 340 | + const result = await this.option.detailAPI(param); | |
| 341 | + this.setFormModel(result); | |
| 342 | + } catch (error) { | |
| 343 | + console.error(error); | |
| 344 | + } finally { | |
| 345 | + this.dialogLoading = false; | |
| 346 | + } | |
| 347 | + } else if (_$http && this.option.url) { // 给定了http的情况 | |
| 348 | + console.log('_$http detail'); | |
| 349 | + this.dialogLoading = true; | |
| 350 | + const defaultDetailMethod = `info/${detailPrimaryKey || primaryKey}/${param[detailPrimaryKey] || param[primaryKey]}`; | |
| 351 | + const detailMethodFormat = this.option.detailMethod ? `${this.option.detailMethod.trim('/')}?${stringify({ [detailPrimaryKey || primaryKey]: param[detailPrimaryKey || primaryKey] })}` : undefined; | |
| 352 | + _$http.get(`${this.option.url.trim('/')}/${detailMethodFormat || defaultDetailMethod}`) | |
| 353 | + .then(response => { | |
| 354 | + const { result = {} } = response || {}; | |
| 355 | + this.setFormModel(result); | |
| 356 | + }) | |
| 357 | + .finally(() => { | |
| 358 | + this.dialogLoading = false; | |
| 359 | + }); | |
| 360 | + } else { | |
| 361 | + this.dialogLoading = true; | |
| 362 | + this.setFormModel(param); | |
| 363 | + setTimeout(() => { this.dialogLoading = false; }, 1500); | |
| 364 | + } | |
| 300 | 365 | }, |
| 301 | 366 | // 新增按钮 |
| 302 | 367 | handleNew({ row }) { |
| ... | ... | @@ -304,19 +369,53 @@ export default { |
| 304 | 369 | this.dialogType = 'dialog-form'; |
| 305 | 370 | this.tableCurrentRow = row; |
| 306 | 371 | this.formModel = {}; |
| 372 | + this.formMode = "new"; | |
| 373 | + this.$emit('dialog-change', this.dialogType); | |
| 307 | 374 | this.showDialog(); |
| 308 | 375 | }, |
| 309 | 376 | // 编辑按钮 |
| 310 | - handleEdit({ row }) { | |
| 377 | + async handleEdit({ row }) { | |
| 311 | 378 | this.dialogTitle = '编辑'; |
| 312 | 379 | this.dialogType = 'dialog-form'; |
| 313 | 380 | this.tableCurrentRow = row; |
| 314 | 381 | this.formModel = {}; |
| 315 | - // 设置表单值 | |
| 316 | - Object.keys(row).forEach(key => { | |
| 317 | - this.formModel[key] = row[key]; | |
| 318 | - }); | |
| 382 | + this.formMode = "edit"; | |
| 383 | + this.$emit('dialog-change', this.dialogType); | |
| 319 | 384 | this.showDialog(); |
| 385 | + this.doGet(row); | |
| 386 | + }, | |
| 387 | + // 查询单项数据 | |
| 388 | + async doGet(param) { | |
| 389 | + const { primaryKey = 'id', getPrimaryKey } = this.option || {}; | |
| 390 | + if (this.option.getAPI) { // 配置了自定义查询API的情况 | |
| 391 | + console.log('getAPI'); | |
| 392 | + this.dialogLoading = true; | |
| 393 | + try { | |
| 394 | + const result = await this.option.getAPI(param); | |
| 395 | + this.setFormModel(result); | |
| 396 | + } catch (error) { | |
| 397 | + console.error(error); | |
| 398 | + } finally { | |
| 399 | + this.dialogLoading = false; | |
| 400 | + } | |
| 401 | + } else if (_$http && this.option.url) { // 给定了http的情况 | |
| 402 | + console.log('_$http get'); | |
| 403 | + this.dialogLoading = true; | |
| 404 | + const defaultGetMethod = `get/${getPrimaryKey || primaryKey}/${param[getPrimaryKey] || param[primaryKey]}`; | |
| 405 | + const getMethodFormat = this.option.getMethod ? `${this.option.getMethod.trim('/')}?${stringify({ [getPrimaryKey || primaryKey]: param[getPrimaryKey || primaryKey] })}` : undefined; | |
| 406 | + _$http.get(`${this.option.url.trim('/')}/${getMethodFormat || defaultGetMethod}`) | |
| 407 | + .then(response => { | |
| 408 | + const { result = {} } = response || {}; | |
| 409 | + this.setFormModel(result); | |
| 410 | + }) | |
| 411 | + .finally(() => { | |
| 412 | + this.dialogLoading = false; | |
| 413 | + }); | |
| 414 | + } else { | |
| 415 | + this.dialogLoading = true; | |
| 416 | + this.setFormModel(param); | |
| 417 | + setTimeout(() => { this.dialogLoading = false; }, 1500); | |
| 418 | + } | |
| 320 | 419 | }, |
| 321 | 420 | // 删除按钮 |
| 322 | 421 | handleDelete(type, scope) { |
| ... | ... | @@ -326,6 +425,14 @@ export default { |
| 326 | 425 | console.log(type, this.tableSelection); |
| 327 | 426 | } |
| 328 | 427 | }, |
| 428 | + // 设置表单值 | |
| 429 | + setFormModel(value) { | |
| 430 | + if (value && value instanceof Object) { | |
| 431 | + Object.keys(value).forEach(key => { | |
| 432 | + this.formModel[key] = value[key]; | |
| 433 | + }); | |
| 434 | + } | |
| 435 | + }, | |
| 329 | 436 | // 改变每页总数大小 |
| 330 | 437 | handleSizeChange(val) { |
| 331 | 438 | this.currentPage = 1; |
| ... | ... | @@ -339,7 +446,85 @@ export default { |
| 339 | 446 | }, |
| 340 | 447 | // 表单提交 |
| 341 | 448 | handleSubmit(param) { |
| 342 | - console.log({ param }); | |
| 449 | + if (this.formMode === 'new') { | |
| 450 | + this.doNewSubmit(param); | |
| 451 | + } else if (this.formMode === 'edit') { | |
| 452 | + this.doEditSubmit(param); | |
| 453 | + } else { | |
| 454 | + this.hideDialog(); | |
| 455 | + this.handleSearch(); | |
| 456 | + } | |
| 457 | + }, | |
| 458 | + // 新增提交逻辑 | |
| 459 | + async doNewSubmit(param) { | |
| 460 | + const { primaryKey = 'id', formPrimaryKey } = this.option || {}; | |
| 461 | + if (this.option.newAPI) { // 配置了自定义查询API的情况 | |
| 462 | + console.log('newAPI'); | |
| 463 | + this.dialogLoading = true; | |
| 464 | + try { | |
| 465 | + const success = await this.option.newAPI(param); | |
| 466 | + if (success) { | |
| 467 | + this.hideDialog(); | |
| 468 | + this.handleSearch(); | |
| 469 | + if (this.$message) { this.$message({ message: '提交成功', type: 'success' }); } | |
| 470 | + } | |
| 471 | + } catch (error) { | |
| 472 | + console.error(error); | |
| 473 | + } finally { | |
| 474 | + this.dialogLoading = false; | |
| 475 | + } | |
| 476 | + } else if (_$http && this.option.url) { // 给定了http的情况 | |
| 477 | + console.log('_$http new'); | |
| 478 | + this.dialogLoading = true; | |
| 479 | + const postData = { ...param }; | |
| 480 | + delete postData[formPrimaryKey || primaryKey]; | |
| 481 | + _$http.post(`${this.option.url.trim('/')}/${this.option.newMethod || 'add'}`, postData) | |
| 482 | + .then(response => { | |
| 483 | + const { success = false } = response || {}; | |
| 484 | + if (success) { | |
| 485 | + this.hideDialog(); | |
| 486 | + this.handleSearch(); | |
| 487 | + if (this.$message) { this.$message({ message: '提交成功', type: 'success' }); } | |
| 488 | + } | |
| 489 | + }) | |
| 490 | + .finally(() => { | |
| 491 | + this.dialogLoading = false; | |
| 492 | + }); | |
| 493 | + } | |
| 494 | + }, | |
| 495 | + // 编辑提交逻辑 | |
| 496 | + async doEditSubmit(param) { | |
| 497 | + if (this.option.editAPI) { // 配置了自定义查询API的情况 | |
| 498 | + console.log('editAPI'); | |
| 499 | + this.dialogLoading = true; | |
| 500 | + try { | |
| 501 | + const success = await this.option.editAPI(param); | |
| 502 | + if (success) { | |
| 503 | + this.hideDialog(); | |
| 504 | + this.handleSearch(); | |
| 505 | + if (this.$message) { this.$message({ message: '编辑成功', type: 'success' }); } | |
| 506 | + } | |
| 507 | + } catch (error) { | |
| 508 | + console.error(error); | |
| 509 | + } finally { | |
| 510 | + this.dialogLoading = false; | |
| 511 | + } | |
| 512 | + } else if (_$http && this.option.url) { // 给定了http的情况 | |
| 513 | + console.log('_$http edit'); | |
| 514 | + this.dialogLoading = true; | |
| 515 | + _$http.post(`${this.option.url.trim('/')}/${this.option.editMethod || 'update'}`, param) | |
| 516 | + .then(response => { | |
| 517 | + const { success = false } = response || {}; | |
| 518 | + if (success) { | |
| 519 | + this.hideDialog(); | |
| 520 | + this.handleSearch(); | |
| 521 | + if (this.$message) { this.$message({ message: '编辑成功', type: 'success' }); } | |
| 522 | + } | |
| 523 | + }) | |
| 524 | + .finally(() => { | |
| 525 | + this.dialogLoading = false; | |
| 526 | + }); | |
| 527 | + } | |
| 343 | 528 | }, |
| 344 | 529 | // 表单取消 |
| 345 | 530 | handleCancel() { |
| ... | ... | @@ -368,6 +553,7 @@ export default { |
| 368 | 553 | setDialog({ title, type, model }) { |
| 369 | 554 | this.dialogTitle = title; |
| 370 | 555 | this.dialogType = type; |
| 556 | + this.$emit('dialog-change', type); | |
| 371 | 557 | if (model) { |
| 372 | 558 | Object.keys(model).forEach(key => { |
| 373 | 559 | this.formModel[key] = model[key]; | ... | ... |
| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | +export const stringify = (json) => { | |
| 2 | + const urlEncode = (param, key, encode) => { | |
| 3 | + if (param === null) return ''; | |
| 4 | + let paramStr = ''; | |
| 5 | + const t = typeof (param); | |
| 6 | + if (t === 'string' || t === 'number' || t === 'boolean') { | |
| 7 | + paramStr = `&${key}=${((encode === null || encode) ? encodeURIComponent(param) : param)}`; | |
| 8 | + } else { | |
| 9 | + for (const i in param) { | |
| 10 | + if (i) { | |
| 11 | + if (param[i] !== undefined && param[i] !== '' && !(param[i] && typeof param[i] === 'string' && /^\s+$/.test(param[i]))) { | |
| 12 | + const k = key == null ? i : `${key}${(param instanceof Array ? `[${i}]` : `.${i}`)}`; | |
| 13 | + paramStr += urlEncode(param[i], k, encode); | |
| 14 | + } | |
| 15 | + } | |
| 16 | + } | |
| 17 | + } | |
| 18 | + return paramStr; | |
| 19 | + }; | |
| 20 | + return urlEncode(json).substring(1); | |
| 21 | +} | |
| 22 | + | |
| 23 | +export const parse = (url) => { | |
| 24 | + let obj = {};// 创建一个Object | |
| 25 | + let reg = /[?&][^?&]+=[^?&]+/g;// 正则匹配 ?&开始 =拼接 非?&结束 的参数 | |
| 26 | + let arr = url.match(reg);// match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。 | |
| 27 | + // arr数组形式 ['?id=12345','&a=b'] | |
| 28 | + if (arr) { | |
| 29 | + arr.forEach((item) => { | |
| 30 | + /** | |
| 31 | + * tempArr数组 ['id','12345']和['a','b'] | |
| 32 | + * 第一个是key,第二个是value | |
| 33 | + * */ | |
| 34 | + let tempArr = item.substring(1).split('='); | |
| 35 | + let key = decodeURIComponent(tempArr[0]); | |
| 36 | + let val = decodeURIComponent(tempArr[1]); | |
| 37 | + obj[key] = val; | |
| 38 | + }); | |
| 39 | + } | |
| 40 | + return obj; | |
| 41 | +} | |
| 0 | 42 | \ No newline at end of file | ... | ... |
packages/table/index.vue
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | </style> |
| 6 | 6 | |
| 7 | 7 | <template> |
| 8 | - <el-table class="eagle-table" ref="table" :data="tableData" v-bind="tableProps" v-on="tableEvents"> | |
| 8 | + <el-table class="eagle-table" ref="table" :data="tableData" v-bind="{ size: 'small', ...tableProps }" v-on="tableEvents"> | |
| 9 | 9 | <slot></slot> |
| 10 | 10 | <template v-if="list && list.length > 0"> |
| 11 | 11 | <template v-for="(item, index) in list"> |
| ... | ... | @@ -32,11 +32,7 @@ export default { |
| 32 | 32 | // 表格参数 |
| 33 | 33 | tableProps: { |
| 34 | 34 | type: Object, |
| 35 | - default() { | |
| 36 | - return { | |
| 37 | - size: 'small', | |
| 38 | - } | |
| 39 | - } | |
| 35 | + default() { return {} } | |
| 40 | 36 | }, |
| 41 | 37 | // 表格事件 |
| 42 | 38 | tableEvents: Object, | ... | ... |