首屏加载的CSS移动到行内

增加了scss变量:$dialog-top
abstract-from-item的dense属性改为thin
search-form增加了重置功能
行政区域的数据请求地址从@/config移动到组件内(@/component/RegionSelector)
路由根节点的redirect优先使用预设值
@/util/index.js中的mergeObj方法不再将function类型的转为字符串
master
toesbieya 6 years ago
parent 7532c837a1
commit 061c0a4b46
  1. 3
      vue/public/index.html
  2. 2
      vue/src/asset/style/element-ui.scss
  3. 5
      vue/src/asset/style/variables.scss
  4. 2
      vue/src/component/RegionSelector/Tab/index.vue
  5. 2
      vue/src/component/RegionSelector/Tree/TreeDialog.vue
  6. 17
      vue/src/component/RegionSelector/index.vue
  7. 3
      vue/src/component/RegionSelector/mixin.js
  8. 5
      vue/src/component/RegionSelector/store.js
  9. 8
      vue/src/component/abstract/Dialog/index.vue
  10. 12
      vue/src/component/abstract/Form/item.vue
  11. 10
      vue/src/component/form/Search/index.vue
  12. 5
      vue/src/config/index.js
  13. 2
      vue/src/mixin/docTableMixin.js
  14. 6
      vue/src/router/util.js
  15. 28
      vue/src/util/index.js
  16. 20
      vue/src/view/message/manage/EditDialog.vue
  17. 5
      vue/src/view/stock/current/indexPage.vue

@ -7,11 +7,10 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link href="<%= BASE_URL %>favicon.ico" rel="icon">
<title><%= webpackConfig.name %></title>
<style>#loader-wrapper {position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 999;color: #ffffff;background-color: #283443;display: flex;flex-direction: column;justify-content: center;align-items: center;}</style>
</head>
<body>
<div id="app">
<div id="loader-wrapper">
<div style="position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 999;color: #ffffff;background-color: #283443;display: flex;flex-direction: column;justify-content: center;align-items: center;">
<img src="data:image/svg+xml;base64,PCEtLSBCeSBTYW0gSGVyYmVydCAoQHNoZXJiKSwgZm9yIGV2ZXJ5b25lLiBNb3JlIEAgaHR0cDovL2dvby5nbC83QUp6YkwgLS0+Cjxzdmcgd2lkdGg9IjU1IiBoZWlnaHQ9IjgwIiB2aWV3Qm94PSIwIDAgNTUgODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0iI0ZGRiI+CiAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDgwKSI+CiAgICAgICAgPHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjIwIiByeD0iMyI+CiAgICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9ImhlaWdodCIKICAgICAgICAgICAgICAgICBiZWdpbj0iMHMiIGR1cj0iNC4zcyIKICAgICAgICAgICAgICAgICB2YWx1ZXM9IjIwOzQ1OzU3OzgwOzY0OzMyOzY2OzQ1OzY0OzIzOzY2OzEzOzY0OzU2OzM0OzM0OzI7MjM7NzY7Nzk7MjAiIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgPC9yZWN0PgogICAgICAgIDxyZWN0IHg9IjE1IiB3aWR0aD0iMTAiIGhlaWdodD0iODAiIHJ4PSIzIj4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IgogICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIycyIKICAgICAgICAgICAgICAgICB2YWx1ZXM9IjgwOzU1OzMzOzU7NzU7MjM7NzM7MzM7MTI7MTQ7NjA7ODAiIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgPC9yZWN0PgogICAgICAgIDxyZWN0IHg9IjMwIiB3aWR0aD0iMTAiIGhlaWdodD0iNTAiIHJ4PSIzIj4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IgogICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIxLjRzIgogICAgICAgICAgICAgICAgIHZhbHVlcz0iNTA7MzQ7Nzg7MjM7NTY7MjM7MzQ7NzY7ODA7NTQ7MjE7NTAiIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgPC9yZWN0PgogICAgICAgIDxyZWN0IHg9IjQ1IiB3aWR0aD0iMTAiIGhlaWdodD0iMzAiIHJ4PSIzIj4KICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IgogICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIycyIKICAgICAgICAgICAgICAgICB2YWx1ZXM9IjMwOzQ1OzEzOzgwOzU2OzcyOzQ1Ozc2OzM0OzIzOzY3OzMwIiBjYWxjTW9kZT0ibGluZWFyIgogICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiAvPgogICAgICAgIDwvcmVjdD4KICAgIDwvZz4KPC9zdmc+">
<p>资源加载中......</p>
</div>

@ -78,7 +78,7 @@
.el-scrollbar__wrap {
//53 for dialog header,53 for dialog footer
max-height: calc(100vh - 53px - 53px - #{$nav-height * 2});
max-height: calc(100vh - 53px - 53px - #{$dialog-top * 2});
}
}

@ -80,6 +80,9 @@ $page-header-padding: 12px;
//路由页面的margin
$page-view-margin: 24px;
//dialog距离顶部的距离用于<el-dialog>的top属性<el-dialog>中滚动区域的最大高度
$dialog-top: 100px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
@ -88,5 +91,5 @@ $page-view-margin: 24px;
success: $--color-success;
danger: $--color-danger;
warning: $--color-warning;
navHeight: $nav-height;
dialogTop: $dialog-top;
}

@ -271,7 +271,7 @@ export default {
init() {
this.loading = true
const hasInit = this.regionTree.length > 0
const promise = () => hasInit ? Promise.resolve() : init()
const promise = () => hasInit ? Promise.resolve() : init(this.regionDataUrl)
return promise()
.then(() => this.limit ? this.limitApi() : Promise.resolve())
.then(data => {

@ -46,7 +46,7 @@ export default {
init() {
this.loading = true
const hasInit = this.regionTree.length > 0
const promise = () => hasInit ? Promise.resolve() : init()
const promise = () => hasInit ? Promise.resolve() : init(this.regionDataUrl)
return promise()
.then(() => this.limit ? this.limitApi() : Promise.resolve())
.then(data => data && (this.limitTree = createLimitTree(this.regionTree, data)))

@ -8,10 +8,25 @@ export default {
functional: true,
props: {
type: {type: String, default: 'tab', validator: v => ['tree', 'tab'].includes(v)}
type: {
type: String,
default: 'tab',
validator: v => ['tree', 'tab'].includes(v)
},
//json
regionDataUrl: {
type: String,
default: `${process.env.BASE_URL}static/json/region-pca.json`
}
},
render(h, context) {
if (!context.data.props) {
context.data.props = {}
}
context.data.props.regionDataUrl = context.props.regionDataUrl
return h(context.props.type === 'tree' ? Tree : Tab, context.data)
}
}

@ -5,6 +5,7 @@ export default {
size: String,
getChildrenOnSelect: Boolean,
limit: Boolean,
limitApi: Function
limitApi: Function,
regionDataUrl: String
}
}

@ -1,12 +1,11 @@
import Vue from 'vue'
import {regionDataUrl} from '@/config'
export const store = Vue.observable({
data: []
})
export function init() {
return fetch(regionDataUrl)
export function init(url) {
return fetch(url)
.then(r => r.json())
.then(r => store.data = r || [])
}

@ -11,16 +11,16 @@ export default {
value: Boolean,
title: String,
loading: {type: Boolean, default: true},
top: {type: String, default: variables['navHeight']},
top: {type: String, default: variables['dialogTop']},
width: {type: String, default: '30%'}
},
render(h, context) {
const {data, children, listeners, props: {value, title, loading, top, width}} = context
function onClose() {
listeners.input && listeners.input(false)
}
const onClose = function () {
return listeners.close ? () => listeners.close(false) : () => ({})
}()
return (
<el-dialog

@ -4,17 +4,17 @@ export default {
functional: true,
props: {full: Boolean, dense: Boolean, label: String, prop: String},
props: {full: Boolean, thin: Boolean, label: String, prop: String},
render(h, context) {
const {full, dense, label, prop} = context.props
let attrs = {xs: 24, sm: 12, lg: 8}
const {full, thin, label, prop} = context.props
let props = {xs: 24, sm: 12, lg: 8}
if (full) attrs = {span: 24}
else if (dense) attrs.lg = 12
if (full) props = {span: 24}
else if (thin) props.lg = 12
return (
<el-col {...{attrs}}>
<el-col {...{props}}>
<el-form-item label={label} prop={prop}>
{context.children}
</el-form-item>

@ -1,9 +1,15 @@
<script type="text/jsx">
import {deepClone} from "@/util"
import {getElementInnerWidth} from '@/util/browser'
export default {
name: "SearchForm",
model: {
prop: 'model',
event: 'reset'
},
props: {
model: Object,
labelWidth: {type: String, default: '120px'},
@ -38,7 +44,7 @@ export default {
return
}
this.$emit('reset')
this.$emit('reset', deepClone(this.initialModel))
},
getElementNumInRow() {
@ -93,7 +99,7 @@ export default {
mounted() {
//
this.initialModel = this.model
this.initialModel = deepClone(this.model)
this.resize()
this.resizeObserver = new ResizeObserver(() => this.resize())

@ -61,8 +61,5 @@ module.exports = {
//读写时是否进行压缩的默认值
zip: !isDev
},
//省市地区json数据请求地址
regionDataUrl: `${contextPath}static/json/region-pca.json`
}
}

@ -81,7 +81,7 @@ export default {
dataLoading: this.config.loading,
search: {
props: {model: this.searchForm},
on: {search: this.search}
on: {search: this.search, reset: v => this.searchForm = v}
},
table: {
props: {data: this.tableData},

@ -50,7 +50,7 @@ export function generateRoutes(jsonTree) {
if (!Array.isArray(routes)) return
for (let i = routes.length - 1; i >= 0; i--) {
const {path, component, children, meta = {}} = routes[i]
const {path, redirect, component, children, meta = {}} = routes[i]
//剔除外链节点以及无component且非iframe的节点
if (isExternal(path) || !component && !meta.iframe) {
@ -82,8 +82,8 @@ export function generateRoutes(jsonTree) {
if (!children || children.length <= 0) {
routes[i].props = true
}
//设置根节点的redirect
else if (depth === 1) {
//仅在根节点未设置redirect时,将其第一个子节点的路径设为redirect
else if (depth === 1 && isEmpty(redirect)) {
const rootPath = path.endsWith('/') ? path : `${path}/`
routes[i].redirect = `${rootPath}${children[0].path}`
}

@ -37,25 +37,31 @@ export function resetObj(obj) {
//简单合并对象
export function mergeObj(target, source) {
Object.keys(target).forEach(key => {
if (!isEmpty(source) && key in source) {
if (isEmpty(target, source)) return
for (const key of Object.keys(target)) {
if (!(key in source)) continue
//数组类型直接赋值,不做深拷贝
if (Array.isArray(target[key])) {
target[key] = source[key] || []
continue
}
else if (typeof target[key] === 'number') {
//number类型不考虑NaN
if (typeof target[key] === 'number') {
target[key] = source[key] || 0
continue
}
else if (target[key] !== null && typeof target[key] === 'object') {
//非空对象递归处理
if (target[key] !== null && typeof target[key] === 'object') {
mergeObj(target[key], source[key])
continue
}
else {
if (typeof source[key] === 'function') {
target[key] = source[key].toString()
}
else target[key] = source[key]
}
target[key] = source[key]
}
})
}
export function timeFormat(fmt, date = new Date()) {

@ -1,40 +1,40 @@
<template>
<abstract-dialog :loading="loading" :title="title" :value="value" width="50%" @close="cancel" @open="open">
<abstract-form :model="form" :rules="rules">
<abstract-form-item label="标 题" prop="title" dense>
<abstract-form-item label="标 题" prop="title" thin>
<el-input v-model="form.title" maxlength="100" :readonly="!canSave"/>
</abstract-form-item>
<abstract-form-item label="消息类型" prop="type" dense>
<abstract-form-item label="消息类型" prop="type" thin>
<el-select v-model="form.type" :disabled="!canSave">
<el-option :value="0" label="通知提醒"/>
<el-option :value="1" label="系统公告"/>
</el-select>
</abstract-form-item>
<abstract-form-item v-if="type!=='add'" label="创建人" dense>
<abstract-form-item v-if="type!=='add'" label="创建人" thin>
<el-input :value="form.cname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="type!=='add'" label="创建时间" dense>
<abstract-form-item v-if="type!=='add'" label="创建时间" thin>
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item label="通知对象" prop="broadcast" dense>
<abstract-form-item label="通知对象" prop="broadcast" thin>
<el-select v-model="form.broadcast" :disabled="!canSave">
<el-option :value="false" label="指定用户"/>
<el-option :value="true" label="全体用户"/>
</el-select>
</abstract-form-item>
<abstract-form-item v-if="!form.broadcast" label="选择用户" prop="recipient" dense>
<abstract-form-item v-if="!form.broadcast" label="选择用户" prop="recipient" thin>
<user-selector v-model="form.recipient" :disabled="!canSave"/>
</abstract-form-item>
<abstract-form-item v-if="form.pname" label="发布人" dense>
<abstract-form-item v-if="form.pname" label="发布人" thin>
<el-input :value="form.pname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="form.ptime" label="发布时间" dense>
<abstract-form-item v-if="form.ptime" label="发布时间" thin>
<el-date-picker :value="form.ptime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item v-if="form.status===2" label="撤回人" dense>
<abstract-form-item v-if="form.status===2" label="撤回人" thin>
<el-input :value="form.wname" readonly/>
</abstract-form-item>
<abstract-form-item v-if="form.status===2" label="撤回时间" dense>
<abstract-form-item v-if="form.status===2" label="撤回时间" thin>
<el-date-picker :value="form.wtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</abstract-form-item>
<abstract-form-item label="内 容" full>

@ -14,7 +14,7 @@
<category-tree ref="tree" :filter-node-method="filterNode" @node-click="nodeClick"/>
</template>
<search-form>
<search-form v-model="searchForm" @search="search" @reset="clearCidSearch">
<el-form-item label="商品分类">
<el-input :value="temp.cname" maxlength="100" clearable @clear="clearCidSearch"/>
</el-form-item>
@ -36,8 +36,7 @@
</search-form>
<el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="primary" @click="search"> </el-button>
<el-button icon="el-icon-download" size="small" type="info" @click="downloadExcel"> </el-button>
<el-button icon="el-icon-download" size="small" type="primary" @click="downloadExcel"> </el-button>
</el-row>
<el-row v-loading="config.loading" class="table-container">

Loading…
Cancel
Save