parent
65d1e6a879
commit
7f30a186df
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
.cm-s-idea span.cm-meta{color:olive}.cm-s-idea span.cm-number{color:#00f}.cm-s-idea span.cm-keyword{line-height:1em;font-weight:700;color:navy}.cm-s-idea span.cm-atom{font-weight:700;color:navy}.cm-s-idea span.cm-def{color:#000}.cm-s-idea span.cm-variable{color:#000}.cm-s-idea span.cm-variable-2{color:#000}.cm-s-idea span.cm-type,.cm-s-idea span.cm-variable-3{color:#000}.cm-s-idea span.cm-property{color:#000}.cm-s-idea span.cm-operator{color:#000}.cm-s-idea span.cm-comment{color:grey}.cm-s-idea span.cm-string{color:green}.cm-s-idea span.cm-string-2{color:green}.cm-s-idea span.cm-qualifier{color:#555}.cm-s-idea span.cm-error{color:red}.cm-s-idea span.cm-attribute{color:#00f}.cm-s-idea span.cm-tag{color:navy}.cm-s-idea span.cm-link{color:#00f}.cm-s-idea .CodeMirror-activeline-background{background:#fffae3}.cm-s-idea span.cm-builtin{color:#30a}.cm-s-idea span.cm-bracket{color:#cc7}.cm-s-idea{font-family:Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif}.cm-s-idea .CodeMirror-matchingbracket{outline:1px solid grey;color:#000!important}.CodeMirror-hints.idea{font-family:Menlo,Monaco,Consolas,'Courier New',monospace;color:#616569;background-color:#ebf3fd!important}.CodeMirror-hints.idea .CodeMirror-hint-active{background-color:#a2b8c9!important;color:#5c6065!important}
|
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<a-time-picker
|
||||
:disabled="disabled || readOnly"
|
||||
:placeholder="placeholder"
|
||||
:value="momVal"
|
||||
:format="dateFormat"
|
||||
:getCalendarContainer="getCalendarContainer"
|
||||
@change="handleTimeChange"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
export default {
|
||||
name: 'JTime',
|
||||
props: {
|
||||
placeholder:{
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
value:{
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
dateFormat:{
|
||||
type: String,
|
||||
default: 'HH:mm:ss',
|
||||
required: false
|
||||
},
|
||||
readOnly:{
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
disabled:{
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
getCalendarContainer: {
|
||||
type: Function,
|
||||
default: (node) => node.parentNode
|
||||
}
|
||||
},
|
||||
data () {
|
||||
let timeStr = this.value;
|
||||
return {
|
||||
decorator:"",
|
||||
momVal:!timeStr?null:moment(timeStr,this.dateFormat)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
if(!val){
|
||||
this.momVal = null
|
||||
}else{
|
||||
this.momVal = moment(val,this.dateFormat)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moment,
|
||||
handleTimeChange(mom,timeStr){
|
||||
this.$emit('change', timeStr);
|
||||
}
|
||||
},
|
||||
//2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型 这个牛逼
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<j-modal
|
||||
title="详细信息"
|
||||
:width="1200"
|
||||
:visible="visible"
|
||||
@ok="handleOk"
|
||||
@cancel="close"
|
||||
switch-fullscreen
|
||||
:fullscreen.sync="fullscreen"
|
||||
>
|
||||
|
||||
<transition name="fade">
|
||||
<div v-if="visible">
|
||||
<slot name="mainForm" :row="row" :column="column"/>
|
||||
<slot name="subForm" :row="row" :column="column"/>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</j-modal>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { cloneObject } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
name: 'JVxeDetailsModal',
|
||||
inject: ['superTrigger'],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
fullscreen: false,
|
||||
row: null,
|
||||
column: null,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
|
||||
open(event) {
|
||||
let {row, column} = event
|
||||
this.row = cloneObject(row)
|
||||
this.column = column
|
||||
this.visible = true
|
||||
},
|
||||
|
||||
close() {
|
||||
this.visible = false
|
||||
},
|
||||
|
||||
handleOk() {
|
||||
this.superTrigger('detailsConfirm', {
|
||||
row: this.row,
|
||||
column: this.column,
|
||||
callback: (success) => {
|
||||
this.visible = !success
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
opacity: 1;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div :class="boxClass">
|
||||
<a-pagination
|
||||
:disabled="disabled"
|
||||
v-bind="bindProps"
|
||||
@change="handleChange"
|
||||
@showSizeChange="handleShowSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PropTypes from 'ant-design-vue/es/_util/vue-types'
|
||||
|
||||
export default {
|
||||
name: 'JVxePagination',
|
||||
props: {
|
||||
size: String,
|
||||
disabled: PropTypes.bool,
|
||||
pagination: PropTypes.object.def({}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultPagination: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
pageSizeOptions: ['10', '20', '30'],
|
||||
showTotal: (total, range) => {
|
||||
return range[0] + '-' + range[1] + ' 共 ' + total + ' 条'
|
||||
},
|
||||
showQuickJumper: true,
|
||||
showSizeChanger: true,
|
||||
total: 100
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bindProps() {
|
||||
return {
|
||||
...this.defaultPagination,
|
||||
...this.pagination,
|
||||
size: this.size === 'tiny' ? 'small' : ''
|
||||
}
|
||||
},
|
||||
boxClass() {
|
||||
return {
|
||||
'j-vxe-pagination': true,
|
||||
'show-quick-jumper': !!this.bindProps.showQuickJumper
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleChange(current, pageSize) {
|
||||
this.$set(this.pagination, 'current', current)
|
||||
this.$emit('change', {current, pageSize})
|
||||
},
|
||||
handleShowSizeChange(current, pageSize) {
|
||||
this.$set(this.pagination, 'pageSize', pageSize)
|
||||
this.$emit('change', {current, pageSize})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div :class="boxClass">
|
||||
<!-- 工具按钮 -->
|
||||
<div class="j-vxe-tool-button div" :size="btnSize">
|
||||
<slot v-if="showPrefix" name="toolbarPrefix" :size="btnSize"/>
|
||||
|
||||
<a-button v-if="showAdd" icon="plus" @click="trigger('add')" :disabled="disabled" type="primary">新增</a-button>
|
||||
<a-button v-if="showSave" icon="save" @click="trigger('save')" :disabled="disabled">保存</a-button>
|
||||
<template v-if="selectedRowIds.length > 0">
|
||||
<a-popconfirm
|
||||
v-if="showRemove"
|
||||
:title="`确定要删除这 ${selectedRowIds.length} 项吗?`"
|
||||
@confirm="trigger('remove')"
|
||||
>
|
||||
<a-button icon="minus" :disabled="disabled">删除</a-button>
|
||||
</a-popconfirm>
|
||||
<template v-if="showClearSelection">
|
||||
<a-button icon="delete" @click="trigger('clearSelection')">清空选择</a-button>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<slot v-if="showSuffix" name="toolbarSuffix" :size="btnSize"/>
|
||||
<a v-if="showCollapse" @click="toggleCollapse" style="margin-left: 4px">
|
||||
<span>{{ collapsed ? '展开' : '收起' }}</span>
|
||||
<a-icon :type="collapsed ? 'down' : 'up'"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'JVxeToolbar',
|
||||
props: {
|
||||
toolbarConfig: Object,
|
||||
excludeCode: Array,
|
||||
size: String,
|
||||
disabled: Boolean,
|
||||
disabledRows: Object,
|
||||
selectedRowIds: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 是否收起
|
||||
collapsed: true,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
boxClass() {
|
||||
return {
|
||||
'j-vxe-toolbar': true,
|
||||
'j-vxe-toolbar-collapsed': this.collapsed,
|
||||
}
|
||||
},
|
||||
|
||||
btns() {
|
||||
let arr = this.toolbarConfig.btn || ['add', 'remove', 'clearSelection']
|
||||
let exclude = [...this.excludeCode]
|
||||
// TODO 需要将remove替换batch_delete
|
||||
// 系统默认的批量删除编码配置为 batch_delete 此处需要转化一下
|
||||
if(exclude.indexOf('batch_delete')>=0){
|
||||
exclude.add('remove')
|
||||
}
|
||||
// 按钮权限 需要去掉不被授权的按钮
|
||||
return arr.filter(item=>{
|
||||
return exclude.indexOf(item)<0
|
||||
})
|
||||
},
|
||||
slots() {
|
||||
return this.toolbarConfig.slot || ['prefix', 'suffix']
|
||||
},
|
||||
showPrefix() {
|
||||
return this.slots.includes('prefix')
|
||||
},
|
||||
showSuffix() {
|
||||
return this.slots.includes('suffix')
|
||||
},
|
||||
showAdd() {
|
||||
return this.btns.includes('add')
|
||||
},
|
||||
showSave() {
|
||||
return this.btns.includes('save')
|
||||
},
|
||||
showRemove() {
|
||||
return this.btns.includes('remove')
|
||||
},
|
||||
showClearSelection() {
|
||||
if (this.btns.includes('clearSelection')) {
|
||||
// 有禁用行时才显示清空选择按钮
|
||||
// 因为禁用行会阻止选择行,导致无法取消全选
|
||||
let length = Object.keys(this.disabledRows).length
|
||||
return length > 0
|
||||
}
|
||||
return false
|
||||
},
|
||||
showCollapse() {
|
||||
return this.btns.includes('collapse')
|
||||
},
|
||||
|
||||
btnSize() {
|
||||
return this.size === 'tiny' ? 'small' : null
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/** 触发事件 */
|
||||
trigger(name) {
|
||||
this.$emit(name)
|
||||
},
|
||||
// 切换展开收起
|
||||
toggleCollapse() {
|
||||
this.collapsed = !this.collapsed
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.j-vxe-toolbar-collapsed {
|
||||
[data-collapse] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.j-vxe-tool-button.div .ant-btn {
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,59 @@
|
||||
@import "size/tiny";
|
||||
|
||||
.j-vxe-table-box {
|
||||
|
||||
// 工具栏
|
||||
.j-vxe-toolbar {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
// 分页器
|
||||
.j-vxe-pagination {
|
||||
margin-top: 8px;
|
||||
text-align: right;
|
||||
|
||||
.ant-pagination-options-size-changer.ant-select {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.show-quick-jumper {
|
||||
.ant-pagination-options-size-changer.ant-select {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更改 header 底色
|
||||
.vxe-table.border--default .vxe-table--header-wrapper,
|
||||
.vxe-table.border--full .vxe-table--header-wrapper,
|
||||
.vxe-table.border--outer .vxe-table--header-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 更改 tooltip 校验失败的颜色
|
||||
.vxe-table--tooltip-wrapper.vxe-table--valid-error {
|
||||
background-color: #f5222d !important;
|
||||
}
|
||||
|
||||
// 更改 输入框 校验失败的颜色
|
||||
.col--valid-error > .vxe-cell > .ant-input,
|
||||
.col--valid-error > .vxe-cell > .ant-select .ant-input,
|
||||
.col--valid-error > .vxe-cell > .ant-select .ant-select-selection,
|
||||
.col--valid-error > .vxe-cell > .ant-input-number,
|
||||
.col--valid-error > .vxe-cell > .ant-cascader-picker .ant-cascader-input,
|
||||
.col--valid-error > .vxe-cell > .ant-calendar-picker .ant-calendar-picker-input,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-input,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-select .ant-input,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-select .ant-select-selection,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-input-number,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-cascader-picker .ant-cascader-input,
|
||||
.col--valid-error > .vxe-tree-cell > .ant-calendar-picker .ant-calendar-picker-input {
|
||||
border-color: #f5222d !important;
|
||||
}
|
||||
|
||||
// 拖拽排序列样式
|
||||
.vxe-table .col--row-drag-sort .vxe-cell {
|
||||
height: 100%;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
.j-vxe-reload-effect-box {
|
||||
|
||||
&,
|
||||
.j-vxe-reload-effect-span {
|
||||
display: inline;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.j-vxe-reload-effect-span {
|
||||
|
||||
&.layer-top {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
background-color: white;
|
||||
|
||||
transform-origin: 0 0;
|
||||
animation: reload-effect 1.5s forwards;
|
||||
}
|
||||
|
||||
&.layer-bottom {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 定义动画
|
||||
@keyframes reload-effect {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: rotateX(0);
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,332 @@
|
||||
.j-vxe-table-box {
|
||||
|
||||
@height: 24px;
|
||||
@lineHeight: 1.5;
|
||||
@spacing: 4px;
|
||||
@fontSize: 14px;
|
||||
@borderRadius: 2px;
|
||||
|
||||
&.size--tiny {
|
||||
|
||||
.vxe-table--header .vxe-cell--checkbox {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.vxe-table--body .vxe-cell--checkbox {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.vxe-cell {
|
||||
padding: 0 5px;
|
||||
font-size: @fontSize;
|
||||
line-height: @lineHeight;
|
||||
}
|
||||
|
||||
.vxe-table .vxe-header--column .vxe-cell {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.vxe-body--column.col--actived {
|
||||
padding: 0;
|
||||
|
||||
.vxe-cell {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ant输入框
|
||||
.ant-input,
|
||||
// ant下拉框
|
||||
.ant-select-selection {
|
||||
padding: 2px @spacing;
|
||||
height: @height;
|
||||
font-size: @fontSize;
|
||||
border-radius: @borderRadius;
|
||||
line-height: @lineHeight;
|
||||
}
|
||||
|
||||
// 输入框图标对齐
|
||||
.ant-input-affix-wrapper {
|
||||
& .ant-input-prefix {
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
& .ant-input:not(:first-child) {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// 按钮 addon
|
||||
.ant-input-group-addon {
|
||||
border-color: transparent;
|
||||
border-radius: @borderRadius;
|
||||
}
|
||||
|
||||
|
||||
// ant下拉多选框
|
||||
.ant-select-selection--multiple {
|
||||
min-height: @height;
|
||||
|
||||
& .ant-select-selection__rendered > ul > li {
|
||||
height: calc(@height - 6px);
|
||||
font-size: calc(@fontSize - 2px);
|
||||
margin-top: 0;
|
||||
line-height: @lineHeight;
|
||||
padding: 0 18px 0 4px;
|
||||
|
||||
}
|
||||
|
||||
& .ant-select-selection__clear,
|
||||
& .ant-select-arrow {
|
||||
top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ant按钮
|
||||
.ant-upload {
|
||||
width: 100%;
|
||||
|
||||
.ant-btn {
|
||||
width: 100%;
|
||||
height: @height;
|
||||
padding: 0 8px;
|
||||
font-size: @fontSize;
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
border-radius: @borderRadius;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-selection__rendered {
|
||||
line-height: @lineHeight;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
// 工具栏
|
||||
.j-vxe-toolbar {
|
||||
margin-bottom: 4px;
|
||||
|
||||
.ant-form-item-label,
|
||||
.ant-form-item-control {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.ant-form-inline .ant-form-item {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** 内置属性 */
|
||||
|
||||
.vxe-table.size--tiny {
|
||||
& .vxe-table--expanded {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
& .vxe-body--expanded-cell {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.size--tiny .vxe-loading .vxe-loading--spinner {
|
||||
width: 38px;
|
||||
height: 38px
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-body--column.col--ellipsis,
|
||||
.vxe-table.size--tiny .vxe-footer--column.col--ellipsis,
|
||||
.vxe-table.size--tiny .vxe-header--column.col--ellipsis,
|
||||
.vxe-table.vxe-editable.size--tiny .vxe-body--column {
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-table--empty-block,
|
||||
.vxe-table.size--tiny .vxe-table--empty-placeholder {
|
||||
min-height: @height;
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-body--column:not(.col--ellipsis),
|
||||
.vxe-table.size--tiny .vxe-footer--column:not(.col--ellipsis),
|
||||
.vxe-table.size--tiny .vxe-header--column:not(.col--ellipsis) {
|
||||
padding: 4px 0
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-cell .vxe-default-input,
|
||||
.vxe-table.size--tiny .vxe-cell .vxe-default-select,
|
||||
.vxe-table.size--tiny .vxe-cell .vxe-default-textarea {
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-cell .vxe-default-input[type=date]::-webkit-inner-spin-button {
|
||||
margin-top: 1px
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny.virtual--x .col--ellipsis .vxe-cell,
|
||||
.vxe-table.size--tiny.virtual--y .col--ellipsis .vxe-cell,
|
||||
.vxe-table.size--tiny .vxe-body--column.col--ellipsis .vxe-cell,
|
||||
.vxe-table.size--tiny .vxe-footer--column.col--ellipsis .vxe-cell,
|
||||
.vxe-table.size--tiny .vxe-header--column.col--ellipsis .vxe-cell {
|
||||
max-height: @height;
|
||||
}
|
||||
|
||||
.vxe-table.size--tiny .vxe-cell--checkbox .vxe-checkbox--icon,
|
||||
.vxe-table.size--tiny .vxe-cell--radio .vxe-radio--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
|
||||
.vxe-table.size--tiny .vxe-table--filter-option > .vxe-checkbox--icon,
|
||||
.vxe-table.size--small .vxe-table--filter-option > .vxe-checkbox--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.vxe-modal--wrapper.size--tiny .vxe-export--panel-column-option > .vxe-checkbox--icon,
|
||||
.vxe-modal--wrapper.size--small .vxe-export--panel-column-option > .vxe-checkbox--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.vxe-grid.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-toolbar.size--tiny {
|
||||
font-size: 12px;
|
||||
height: 46px
|
||||
}
|
||||
|
||||
.vxe-toolbar.size--tiny .vxe-custom--option > .vxe-checkbox--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.vxe-pager.size--tiny {
|
||||
font-size: 12px;
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-checkbox.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-checkbox.size--tiny .vxe-checkbox--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.vxe-radio-button.size--tiny .vxe-radio--label {
|
||||
line-height: 26px
|
||||
}
|
||||
|
||||
.vxe-radio.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-radio.size--tiny .vxe-radio--icon {
|
||||
font-size: 14px
|
||||
}
|
||||
|
||||
.vxe-input.size--tiny {
|
||||
font-size: 12px;
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-input.size--tiny .vxe-input--inner[type=date]::-webkit-inner-spin-button,
|
||||
.vxe-input.size--tiny .vxe-input--inner[type=month]::-webkit-inner-spin-button,
|
||||
.vxe-input.size--tiny .vxe-input--inner[type=week]::-webkit-inner-spin-button {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
.vxe-dropdown--panel.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-textarea--autosize.size--tiny,
|
||||
.vxe-textarea.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-textarea.size--tiny:not(.is--autosize) {
|
||||
min-height: @height;
|
||||
}
|
||||
|
||||
.vxe-button.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-button.size--tiny.type--button {
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-button.size--tiny.type--button.is--circle {
|
||||
min-width: @height;
|
||||
}
|
||||
|
||||
.vxe-button.size--tiny.type--button.is--round {
|
||||
border-radius: 14px
|
||||
}
|
||||
|
||||
.vxe-button.size--tiny .vxe-button--icon,
|
||||
.vxe-button.size--tiny .vxe-button--loading-icon {
|
||||
min-width: 12px
|
||||
}
|
||||
|
||||
.vxe-modal--wrapper.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-form.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-form.size--tiny .vxe-form--item-inner {
|
||||
min-height: 30px
|
||||
}
|
||||
|
||||
.vxe-form.size--tiny .vxe-default-input[type=reset],
|
||||
.vxe-form.size--tiny .vxe-default-input[type=submit] {
|
||||
line-height: 26px
|
||||
}
|
||||
|
||||
.vxe-form.size--tiny .vxe-default-input,
|
||||
.vxe-form.size--tiny .vxe-default-select {
|
||||
height: @height;
|
||||
}
|
||||
|
||||
.vxe-select--panel.size--tiny,
|
||||
.vxe-select.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.vxe-select--panel.size--tiny .vxe-optgroup--title,
|
||||
.vxe-select--panel.size--tiny .vxe-select-option {
|
||||
height: 24px;
|
||||
line-height: 24px
|
||||
}
|
||||
|
||||
.vxe-switch.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
|
||||
.vxe-pulldown--panel.size--tiny,
|
||||
.vxe-pulldown.size--tiny {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<div class="tinymce-containerty" :style="{width:containerWidth}">
|
||||
<textarea :id="tinymceId" class="tinymce-textarea" @change="ada"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* docs:
|
||||
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
|
||||
*/
|
||||
import load from './load'
|
||||
//const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
|
||||
//const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
|
||||
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
|
||||
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
|
||||
|
||||
export default {
|
||||
name: 'JEditorDyn',
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
toolbar: {
|
||||
type: [String, Array],
|
||||
required: false,
|
||||
default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link unlink image media table | removeformat | fullscreen',
|
||||
},
|
||||
menubar: {
|
||||
type: String,
|
||||
default: 'file edit insert view format table'
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: 360
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: 'auto'
|
||||
},
|
||||
plugins: {
|
||||
type: [String, Array],
|
||||
default: 'lists image link media table textcolor wordcount contextmenu fullscreen'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasChange: false,
|
||||
hasInit: false,
|
||||
tinymceId: this.id,
|
||||
fullscreen: false,
|
||||
languageTypeList: {
|
||||
'en': 'en',
|
||||
'zh': 'zh_CN',
|
||||
'es': 'es_MX',
|
||||
'ja': 'ja'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerWidth() {
|
||||
const width = this.width
|
||||
if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
|
||||
return `${width}px`
|
||||
}
|
||||
return width
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
this.$nextTick(() =>
|
||||
window.tinymce.get(this.tinymceId).setContent(val || ''))
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
activated() {
|
||||
if (window.tinymce) {
|
||||
this.initTinymce()
|
||||
}
|
||||
},
|
||||
deactivated() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
methods: {
|
||||
ada() {
|
||||
console.log('change')
|
||||
},
|
||||
init() {
|
||||
// dynamic load tinymce from cdn
|
||||
load(tinymceCDN, (err) => {
|
||||
if (err) {
|
||||
this.$message.error(err.message)
|
||||
return
|
||||
}
|
||||
this.initTinymce()
|
||||
})
|
||||
},
|
||||
initTinymce() {
|
||||
const _this = this
|
||||
window.tinymce.init({
|
||||
selector: `#${this.tinymceId}`,
|
||||
language: this.languageTypeList['zh'],
|
||||
height: this.height,
|
||||
body_class: 'panel-body ',
|
||||
object_resizing: false,
|
||||
toolbar: this.toolbar,
|
||||
menubar: false,
|
||||
plugins: this.plugins,
|
||||
end_container_on_empty_block: true,
|
||||
powerpaste_word_import: 'clean',
|
||||
code_dialog_height: 450,
|
||||
code_dialog_width: 1000,
|
||||
advlist_bullet_styles: 'square',
|
||||
advlist_number_styles: 'default',
|
||||
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
|
||||
default_link_target: '_blank',
|
||||
link_title: false,
|
||||
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
||||
init_instance_callback: editor => {
|
||||
if (_this.value) {
|
||||
editor.setContent(_this.value)
|
||||
}
|
||||
_this.hasInit = true
|
||||
editor.on('NodeChange Change KeyUp SetContent', () => {
|
||||
this.hasChange = true
|
||||
this.$emit('input', editor.getContent())
|
||||
})
|
||||
},
|
||||
setup(editor) {
|
||||
editor.on('FullscreenStateChanged', (e) => {
|
||||
_this.fullscreen = e.state
|
||||
})
|
||||
},
|
||||
// it will try to keep these URLs intact
|
||||
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
|
||||
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
|
||||
convert_urls: false
|
||||
// 整合七牛上传
|
||||
// images_dataimg_filter(img) {
|
||||
// setTimeout(() => {
|
||||
// const $image = $(img);
|
||||
// $image.removeAttr('width');
|
||||
// $image.removeAttr('height');
|
||||
// if ($image[0].height && $image[0].width) {
|
||||
// $image.attr('data-wscntype', 'image');
|
||||
// $image.attr('data-wscnh', $image[0].height);
|
||||
// $image.attr('data-wscnw', $image[0].width);
|
||||
// $image.addClass('wscnph');
|
||||
// }
|
||||
// }, 0);
|
||||
// return img
|
||||
// },
|
||||
// images_upload_handler(blobInfo, success, failure, progress) {
|
||||
// progress(0);
|
||||
// const token = _this.$store.getters.token;
|
||||
// getToken(token).then(response => {
|
||||
// const url = response.data.qiniu_url;
|
||||
// const formData = new FormData();
|
||||
// formData.append('token', response.data.qiniu_token);
|
||||
// formData.append('key', response.data.qiniu_key);
|
||||
// formData.append('file', blobInfo.blob(), url);
|
||||
// upload(formData).then(() => {
|
||||
// success(url);
|
||||
// progress(100);
|
||||
// })
|
||||
// }).catch(err => {
|
||||
// failure('err')
|
||||
// console.log(err);
|
||||
// });
|
||||
// },
|
||||
})
|
||||
},
|
||||
destroyTinymce() {
|
||||
const tinymce = window.tinymce.get(this.tinymceId)
|
||||
if (this.fullscreen) {
|
||||
tinymce.execCommand('mceFullScreen')
|
||||
}
|
||||
|
||||
if (tinymce) {
|
||||
tinymce.destroy()
|
||||
}
|
||||
},
|
||||
setContent(value) {
|
||||
window.tinymce.get(this.tinymceId).setContent(value)
|
||||
},
|
||||
getContent() {
|
||||
window.tinymce.get(this.tinymceId).getContent()
|
||||
},
|
||||
imageSuccessCBK(arr) {
|
||||
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tinymce-containerty {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.tinymce-containerty {
|
||||
::v-deep {
|
||||
.mce-fullscreen {
|
||||
z-index: 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tinymce-textarea {
|
||||
visibility: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.editor-custom-btn-container {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
/*z-index: 2005;*/
|
||||
}
|
||||
|
||||
.fullscreen .editor-custom-btn-container {
|
||||
z-index: 10000;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.editor-upload-btn {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="j-markdown-editor" :id="dynamicId"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import load from './load'
|
||||
import { md_js, md_zh_cn_js } from './Resource'
|
||||
import defaultOptions from '@/components/jeecg/JMarkdownEditor/default-options.js'
|
||||
|
||||
export default {
|
||||
name: 'JMdEditorDyn',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: false,
|
||||
default() {
|
||||
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default() {
|
||||
return defaultOptions
|
||||
}
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'markdown'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '300px'
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'zh-CN'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
dynamicId: this.id
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editorOptions() {
|
||||
const options = Object.assign({}, defaultOptions, this.options)
|
||||
options.initialEditType = this.mode
|
||||
options.height = this.height
|
||||
options.language = this.language
|
||||
return options
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newValue, preValue) {
|
||||
if (newValue !== preValue && newValue !== this.editor.getMarkdown()) {
|
||||
this.editor.setMarkdown(newValue)
|
||||
}
|
||||
},
|
||||
language(val) {
|
||||
this.destroyEditor()
|
||||
this.initEditor()
|
||||
},
|
||||
height(newValue) {
|
||||
this.editor.height(newValue)
|
||||
},
|
||||
mode(newValue) {
|
||||
this.editor.changeMode(newValue)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyEditor()
|
||||
},
|
||||
methods: {
|
||||
init(){
|
||||
|
||||
this.initEditor()
|
||||
/* load(md_js,'',()=>{
|
||||
load(md_zh_cn_js,'',()=>{
|
||||
|
||||
})
|
||||
})*/
|
||||
},
|
||||
initEditor() {
|
||||
const Editor = toastui.Editor
|
||||
this.editor = new Editor({
|
||||
el: document.getElementById(this.dynamicId),
|
||||
...this.editorOptions
|
||||
})
|
||||
if (this.value) {
|
||||
this.editor.setMarkdown(this.value)
|
||||
}
|
||||
this.editor.on('change', () => {
|
||||
this.$emit('change', this.editor.getMarkdown())
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
if (!this.editor) return
|
||||
this.editor.off('change')
|
||||
this.editor.remove()
|
||||
},
|
||||
setMarkdown(value) {
|
||||
this.editor.setMarkdown(value)
|
||||
},
|
||||
getMarkdown() {
|
||||
return this.editor.getMarkdown()
|
||||
},
|
||||
setHtml(value) {
|
||||
this.editor.setHtml(value)
|
||||
},
|
||||
getHtml() {
|
||||
return this.editor.getHtml()
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
|
||||
.j-markdown-editor {
|
||||
/deep/ .tui-editor-defaultUI {
|
||||
.te-mode-switch,
|
||||
.tui-scrollsync
|
||||
{
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="jeecg-editor-ty" :class="fullCoder?'jeecg-editor-max':'jeecg-editor-min'">
|
||||
<a-icon v-if="fullScreen" class="full-screen-icon" :type="iconType" @click="()=>fullCoder=!fullCoder"/>
|
||||
<textarea :id="dynamicId" />
|
||||
<span @click="nullTipClick" class="null-tip" :class="{'null-tip-hidden': hasCode}" :style="nullTipStyle">{{ placeholderShow }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import load from './load'
|
||||
import '@/assets/less/codemirror_idea.css'
|
||||
import './cm_sql_hint.js'
|
||||
import { sql_keyword } from './Resource'
|
||||
|
||||
|
||||
export default {
|
||||
name: 'JSqlCodeEditorDyn',
|
||||
props:{
|
||||
id: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return 'vue-editor-' + new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 显示行号
|
||||
lineNumbers: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
zIndex: {
|
||||
type: [Number, String],
|
||||
default: 999
|
||||
},
|
||||
autoHeight: {
|
||||
type: [String, Boolean],
|
||||
default: true
|
||||
},
|
||||
// 不自适应高度的情况下生效的固定高度
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: '240px'
|
||||
},
|
||||
autoHeight: {
|
||||
type: [String, Boolean],
|
||||
default: true
|
||||
},
|
||||
// 是否显示全屏按钮
|
||||
fullScreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
autoHint:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
dynamicId: this.id,
|
||||
coder: '',
|
||||
hasCode: false,
|
||||
code: '',
|
||||
// code 编辑器 是否全屏
|
||||
fullCoder: false,
|
||||
iconType: 'fullscreen',
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
placeholderShow() {
|
||||
if (this.placeholder == null) {
|
||||
return `请在此输入javascript代码`
|
||||
} else {
|
||||
return this.placeholder
|
||||
}
|
||||
},
|
||||
nullTipStyle(){
|
||||
if (this.lineNumbers) {
|
||||
return { left: '36px' }
|
||||
} else {
|
||||
return { left: '12px' }
|
||||
}
|
||||
},
|
||||
isAutoHeight() {
|
||||
let {autoHeight} = this
|
||||
if (typeof autoHeight === 'string' && autoHeight.toLowerCase().trim() === '!ie') {
|
||||
autoHeight = !(isIE() || isIE11())
|
||||
} else {
|
||||
autoHeight = true
|
||||
}
|
||||
return autoHeight
|
||||
},
|
||||
fullScreenParentProps() {
|
||||
let props = {
|
||||
class: {
|
||||
'full-screen-parent': true,
|
||||
'full-screen': this.fullCoder,
|
||||
'auto-height': this.isAutoHeight
|
||||
},
|
||||
style: {}
|
||||
}
|
||||
if (this.fullCoder) {
|
||||
props.style['z-index'] = this.zIndex
|
||||
}
|
||||
if (!this.isAutoHeight) {
|
||||
props.style['height'] = (typeof this.height === 'number' ? this.height + 'px' : this.height)
|
||||
}
|
||||
return props
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
fullCoder:{
|
||||
handler(value) {
|
||||
if(value){
|
||||
this.iconType="fullscreen-exit"
|
||||
}else{
|
||||
this.iconType="fullscreen"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods:{
|
||||
init(){
|
||||
this.main();
|
||||
},
|
||||
main(){
|
||||
let obj = document.getElementById(this.dynamicId);
|
||||
const that = this;
|
||||
let editor = CodeMirror.fromTextArea(obj,{
|
||||
theme:'idea',
|
||||
lineNumbers: this.lineNumbers,
|
||||
lineWrapping: true,
|
||||
mode: "sql",
|
||||
indentUnit: 1,
|
||||
indentWithTabs: true,
|
||||
styleActiveLine: true,
|
||||
/* styleSelectedText: false, */
|
||||
extraKeys: {
|
||||
"F11": function(cm) {
|
||||
that.fullCoder = !that.fullCoder
|
||||
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
|
||||
},
|
||||
"Esc": function(cm) {
|
||||
that.fullCoder = false
|
||||
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
|
||||
},
|
||||
"Alt-/": function(cm) {
|
||||
cm.showHint();
|
||||
},
|
||||
"Tab": (cm) => {
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection('add');
|
||||
} else {
|
||||
//cm.indentLine(cm.getCursor().line, "add");
|
||||
//走两格 第三格输入
|
||||
cm.replaceSelection(Array(3).join(" "), "end", "+input");
|
||||
}
|
||||
},
|
||||
"Shift-Tab": (cm) => {
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection('subtract');
|
||||
} else {
|
||||
// cm.indentLine(cm.getCursor().line, "subtract");
|
||||
const cursor = cm.getCursor();
|
||||
// 光标回退 indexUnit 字符
|
||||
cm.setCursor({line: cursor.line, ch: cursor.ch - 4});
|
||||
}
|
||||
return ;
|
||||
}
|
||||
}
|
||||
})
|
||||
this.coder = editor
|
||||
this.addEvent();
|
||||
this.setCoderValue();
|
||||
this.addSystemHint();
|
||||
},
|
||||
setCoderValue(){
|
||||
if(this.value||this.code){
|
||||
this.hasCode=true
|
||||
this.setCodeContent(this.value || this.code)
|
||||
}else{
|
||||
this.coder.setValue('')
|
||||
this.hasCode=false
|
||||
}
|
||||
},
|
||||
getCodeContent(){
|
||||
return this.code
|
||||
},
|
||||
setCodeContent(val){
|
||||
setTimeout(()=>{
|
||||
if(!val){
|
||||
this.coder.setValue('')
|
||||
}else{
|
||||
this.coder.setValue(val)
|
||||
}
|
||||
},300)
|
||||
},
|
||||
addSystemHint(){
|
||||
this.coder.setOption('hintOptions', {
|
||||
completeSingle: false,
|
||||
tables: sql_keyword
|
||||
});
|
||||
},
|
||||
addEvent(){
|
||||
if(this.autoHint){
|
||||
this.coder.on('cursorActivity', ()=>{
|
||||
this.coder.showHint();
|
||||
});
|
||||
}
|
||||
this.coder.on('change', (coder) => {
|
||||
this.code = coder.getValue()
|
||||
if(this.code){
|
||||
this.hasCode=true
|
||||
}else{
|
||||
this.hasCode=false
|
||||
}
|
||||
if (this.$emit) {
|
||||
this.$emit('input', this.code)
|
||||
}
|
||||
});
|
||||
this.coder.on('focus', () => {
|
||||
this.hasCode=true
|
||||
});
|
||||
this.coder.on('blur', () => {
|
||||
if(this.code){
|
||||
this.hasCode=true
|
||||
}else{
|
||||
this.hasCode=false
|
||||
}
|
||||
});
|
||||
},
|
||||
loadResource(src,type){
|
||||
return new Promise((resolve,reject)=>{
|
||||
load(src,type,(msg)=>{
|
||||
if(!msg){
|
||||
resolve();
|
||||
}else{
|
||||
reject(msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
nullTipClick(){
|
||||
this.coder.focus()
|
||||
},
|
||||
fullToggle(){
|
||||
this.fullCoder = !this.fullCoder
|
||||
this.coder.setOption("fullScreen", this.fullCoder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="less" >
|
||||
.jeecg-editor-ty{
|
||||
position: relative;
|
||||
|
||||
.full-screen-icon {
|
||||
opacity: 0;
|
||||
color: black;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 24px;
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 2px;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
&:hover {
|
||||
.full-screen-icon {
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.88);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.null-tip{
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 36px;
|
||||
z-index: 10;
|
||||
font-size:16px;
|
||||
color: #acaaaac9;
|
||||
line-height: initial;
|
||||
}
|
||||
.null-tip-hidden{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.jeecg-editor-max{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
|
||||
.CodeMirror{
|
||||
position: inherit !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.full-screen-icon{
|
||||
z-index:9999;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<div class="jeecg-editor-ty" :class="fullCoder?'jeecg-editor-max':'jeecg-editor-min'">
|
||||
<a-icon v-if="fullScreen" class="full-screen-icon" :type="iconType" @click="()=>fullCoder=!fullCoder"/>
|
||||
<textarea :id="dynamicId" />
|
||||
<span @click="nullTipClick" class="null-tip" :class="{'null-tip-hidden': hasCode}" :style="nullTipStyle">{{ placeholderShow }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import '@/assets/less/codemirror_idea.css'
|
||||
import './cm_hint.js'
|
||||
|
||||
export default {
|
||||
name: 'JsCodeEditorDyn',
|
||||
props:{
|
||||
id: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return 'vue-editor-' + new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 显示行号
|
||||
lineNumbers: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
zIndex: {
|
||||
type: [Number, String],
|
||||
default: 999
|
||||
},
|
||||
autoHeight: {
|
||||
type: [String, Boolean],
|
||||
default: true
|
||||
},
|
||||
// 不自适应高度的情况下生效的固定高度
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: '240px'
|
||||
},
|
||||
autoHeight: {
|
||||
type: [String, Boolean],
|
||||
default: true
|
||||
},
|
||||
// 是否显示全屏按钮
|
||||
fullScreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
dynamicId: this.id,
|
||||
coder: '',
|
||||
hasCode: false,
|
||||
code: '',
|
||||
// code 编辑器 是否全屏
|
||||
fullCoder: false,
|
||||
iconType: 'fullscreen',
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
placeholderShow() {
|
||||
if (this.placeholder == null) {
|
||||
return `请在此输入javascript代码`
|
||||
} else {
|
||||
return this.placeholder
|
||||
}
|
||||
},
|
||||
nullTipStyle(){
|
||||
if (this.lineNumbers) {
|
||||
return { left: '36px' }
|
||||
} else {
|
||||
return { left: '12px' }
|
||||
}
|
||||
},
|
||||
isAutoHeight() {
|
||||
let {autoHeight} = this
|
||||
if (typeof autoHeight === 'string' && autoHeight.toLowerCase().trim() === '!ie') {
|
||||
autoHeight = !(isIE() || isIE11())
|
||||
} else {
|
||||
autoHeight = true
|
||||
}
|
||||
return autoHeight
|
||||
},
|
||||
fullScreenParentProps() {
|
||||
let props = {
|
||||
class: {
|
||||
'full-screen-parent': true,
|
||||
'full-screen': this.fullCoder,
|
||||
'auto-height': this.isAutoHeight
|
||||
},
|
||||
style: {}
|
||||
}
|
||||
if (this.fullCoder) {
|
||||
props.style['z-index'] = this.zIndex
|
||||
}
|
||||
if (!this.isAutoHeight) {
|
||||
props.style['height'] = (typeof this.height === 'number' ? this.height + 'px' : this.height)
|
||||
}
|
||||
return props
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
fullCoder:{
|
||||
handler(value) {
|
||||
if(value){
|
||||
this.iconType="fullscreen-exit"
|
||||
}else{
|
||||
this.iconType="fullscreen"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods:{
|
||||
init(){
|
||||
this.main();
|
||||
},
|
||||
main(){
|
||||
let obj = document.getElementById(this.dynamicId);
|
||||
const that = this;
|
||||
let editor = CodeMirror.fromTextArea(obj,{
|
||||
theme:'idea',
|
||||
lineNumbers: this.lineNumbers,
|
||||
lineWrapping: true,
|
||||
mode: "javascript",
|
||||
indentUnit: 1,
|
||||
indentWithTabs: true,
|
||||
styleActiveLine: true,
|
||||
/* styleSelectedText: false, */
|
||||
extraKeys: {
|
||||
"F11": function(cm) {
|
||||
that.fullCoder = !that.fullCoder
|
||||
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
|
||||
},
|
||||
"Esc": function(cm) {
|
||||
that.fullCoder = false
|
||||
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
|
||||
},
|
||||
"Alt-/": function(cm) {
|
||||
let a = cm.getValue()+""
|
||||
console.log('a',a)
|
||||
cm.showHint();
|
||||
},
|
||||
"Tab": (cm) => {
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection('add');
|
||||
} else {
|
||||
//cm.indentLine(cm.getCursor().line, "add");
|
||||
//走两格 第三格输入
|
||||
cm.replaceSelection(Array(3).join(" "), "end", "+input");
|
||||
}
|
||||
},
|
||||
"Shift-Tab": (cm) => {
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection('subtract');
|
||||
} else {
|
||||
// cm.indentLine(cm.getCursor().line, "subtract");
|
||||
const cursor = cm.getCursor();
|
||||
// 光标回退 indexUnit 字符
|
||||
cm.setCursor({line: cursor.line, ch: cursor.ch - 4});
|
||||
}
|
||||
return ;
|
||||
}
|
||||
}
|
||||
})
|
||||
this.coder = editor
|
||||
this.addEvent();
|
||||
this.setCoderValue();
|
||||
},
|
||||
setCoderValue(){
|
||||
if(this.value||this.code){
|
||||
this.hasCode=true
|
||||
this.setCodeContent(this.value || this.code)
|
||||
}else{
|
||||
this.coder.setValue('')
|
||||
this.hasCode=false
|
||||
}
|
||||
},
|
||||
getCodeContent(){
|
||||
return this.code
|
||||
},
|
||||
setCodeContent(val){
|
||||
setTimeout(()=>{
|
||||
if(!val){
|
||||
this.coder.setValue('')
|
||||
}else{
|
||||
this.coder.setValue(val)
|
||||
}
|
||||
},300)
|
||||
},
|
||||
addEvent(){
|
||||
const that = this;
|
||||
this.coder.on('cursorActivity',function(wl) {
|
||||
let arr = wl.state.activeLines
|
||||
if(arr && arr.length>0){
|
||||
let text = arr[0].text
|
||||
if(text.lastIndexOf('that.')>=0){
|
||||
that.coder.showHint();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.coder.on('change', (coder) => {
|
||||
this.code = coder.getValue()
|
||||
if(this.code){
|
||||
this.hasCode=true
|
||||
}else{
|
||||
this.hasCode=false
|
||||
}
|
||||
if (this.$emit) {
|
||||
this.$emit('input', this.code)
|
||||
}
|
||||
});
|
||||
this.coder.on('focus', () => {
|
||||
this.hasCode=true
|
||||
});
|
||||
this.coder.on('blur', () => {
|
||||
if(this.code){
|
||||
this.hasCode=true
|
||||
}else{
|
||||
this.hasCode=false
|
||||
}
|
||||
});
|
||||
},
|
||||
loadResource(src,type){
|
||||
return new Promise((resolve,reject)=>{
|
||||
load(src,type,(msg)=>{
|
||||
if(!msg){
|
||||
resolve();
|
||||
}else{
|
||||
reject(msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
nullTipClick(){
|
||||
this.coder.focus()
|
||||
},
|
||||
fullToggle(){
|
||||
this.fullCoder = !this.fullCoder
|
||||
this.coder.setOption("fullScreen", this.fullCoder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="less" >
|
||||
.jeecg-editor-ty{
|
||||
position: relative;
|
||||
|
||||
.full-screen-icon {
|
||||
opacity: 0;
|
||||
color: black;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 24px;
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 2px;
|
||||
z-index: 9;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
&:hover {
|
||||
.full-screen-icon {
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.88);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.null-tip{
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 36px;
|
||||
z-index: 10;
|
||||
font-size:16px;
|
||||
color: #acaaaac9;
|
||||
line-height: initial;
|
||||
}
|
||||
.null-tip-hidden{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.jeecg-editor-max{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
|
||||
.CodeMirror{
|
||||
position: inherit !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.full-screen-icon{
|
||||
z-index:9999;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,24 @@
|
||||
|
||||
/**js编辑器关键词用于提示*/
|
||||
const js_keyword = [
|
||||
'that',
|
||||
'getAction','postAction','deleteAction',
|
||||
'beforeAdd','beforeEdit','beforeDelete','mounted','created','show'
|
||||
]
|
||||
|
||||
/**js编辑器 方法名用于提示*/
|
||||
const js_method = [
|
||||
'.getSelectOptions','.changeOptions','.triggleChangeValues','.immediateEnhance ','.simpleDateFormat','.lodash'
|
||||
]
|
||||
|
||||
/**sql编辑器 表名字段名用于提示*/
|
||||
const sql_keyword = {
|
||||
sys_user: ['USERNAME', 'REALNAME', 'ID','BIRTHDAY','AGE'],
|
||||
demo: ['name', 'age', 'id', 'sex']
|
||||
}
|
||||
|
||||
export {
|
||||
js_keyword,
|
||||
js_method,
|
||||
sql_keyword
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
import { js_keyword, js_method } from './Resource'
|
||||
(function(mod) {
|
||||
mod(CodeMirror);
|
||||
/*if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env*/
|
||||
|
||||
})(function(CodeMirror) {
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
function forEach(arr, f) {
|
||||
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
|
||||
}
|
||||
|
||||
function arrayContains(arr, item) {
|
||||
if (!Array.prototype.indexOf) {
|
||||
var i = arr.length;
|
||||
while (i--) {
|
||||
if (arr[i] === item) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return arr.indexOf(item) != -1;
|
||||
}
|
||||
|
||||
function scriptHint(editor, keywords, getToken, options) {
|
||||
// Find the token at the cursor
|
||||
var cur = editor.getCursor(), token = getToken(editor, cur);
|
||||
if (/\b(?:string|comment)\b/.test(token.type)) return;
|
||||
var innerMode = CodeMirror.innerMode(editor.getMode(), token.state);
|
||||
if (innerMode.mode.helperType === "json") return;
|
||||
token.state = innerMode.state;
|
||||
if('.' === token.string){
|
||||
let arr = []
|
||||
for(let k of js_method){
|
||||
arr.push(k)
|
||||
}
|
||||
return {
|
||||
list: arr,
|
||||
from: Pos(cur.line, token.start),
|
||||
to: Pos(cur.line, token.end)
|
||||
};
|
||||
}
|
||||
// If it's not a 'word-style' token, ignore the token.
|
||||
if (!/^[\w$_]*$/.test(token.string)) {
|
||||
token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
|
||||
type: token.string == "." ? "property" : null};
|
||||
} else if (token.end > cur.ch) {
|
||||
token.end = cur.ch;
|
||||
token.string = token.string.slice(0, cur.ch - token.start);
|
||||
}
|
||||
|
||||
var tprop = token;
|
||||
// If it is a property, find out what it is a property of.
|
||||
while (tprop.type == "property") {
|
||||
tprop = getToken(editor, Pos(cur.line, tprop.start));
|
||||
if (tprop.string != ".") return;
|
||||
tprop = getToken(editor, Pos(cur.line, tprop.start));
|
||||
if (!context) var context = [];
|
||||
context.push(tprop);
|
||||
}
|
||||
return {list: getCompletions(token, context, keywords, options),
|
||||
from: Pos(cur.line, token.start),
|
||||
to: Pos(cur.line, token.end)};
|
||||
}
|
||||
|
||||
function javascriptHint(editor, options) {
|
||||
return scriptHint(editor, javascriptKeywords,
|
||||
function (e, cur) {return e.getTokenAt(cur);},
|
||||
options);
|
||||
};
|
||||
CodeMirror.registerHelper("hint", "javascript", javascriptHint);
|
||||
|
||||
function getCoffeeScriptToken(editor, cur) {
|
||||
// This getToken, it is for coffeescript, imitates the behavior of
|
||||
// getTokenAt method in javascript.js, that is, returning "property"
|
||||
// type and treat "." as indepenent token.
|
||||
var token = editor.getTokenAt(cur);
|
||||
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
|
||||
token.end = token.start;
|
||||
token.string = '.';
|
||||
token.type = "property";
|
||||
}
|
||||
else if (/^\.[\w$_]*$/.test(token.string)) {
|
||||
token.type = "property";
|
||||
token.start++;
|
||||
token.string = token.string.replace(/\./, '');
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
function coffeescriptHint(editor, options) {
|
||||
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
|
||||
}
|
||||
CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
|
||||
|
||||
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
|
||||
"toUpperCase toLowerCase split concat match replace search").split(" ");
|
||||
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
|
||||
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
|
||||
var funcProps = "prototype apply call bind".split(" ");
|
||||
|
||||
var javascriptKeywords = ("break case catch class const continue debugger default delete do else export extends false finally for function " +
|
||||
"if in import instanceof new null return super switch this throw true try typeof var void while with yield that").split(" ");
|
||||
for(let jk of js_keyword){
|
||||
javascriptKeywords.push(jk)
|
||||
}
|
||||
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
|
||||
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
|
||||
|
||||
function forAllProps(obj, callback) {
|
||||
if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
|
||||
for (var name in obj) callback(name)
|
||||
} else {
|
||||
for (var o = obj; o; o = Object.getPrototypeOf(o))
|
||||
Object.getOwnPropertyNames(o).forEach(callback)
|
||||
}
|
||||
}
|
||||
|
||||
function getCompletions(token, context, keywords, options) {
|
||||
var found = [], start = token.string, global = options && options.globalScope || window;
|
||||
function maybeAdd(str) {
|
||||
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
|
||||
}
|
||||
function gatherCompletions(obj) {
|
||||
if (typeof obj == "string") forEach(stringProps, maybeAdd);
|
||||
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
|
||||
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
|
||||
forAllProps(obj, maybeAdd)
|
||||
}
|
||||
|
||||
if (context && context.length) {
|
||||
// If this is a property, see if it belongs to some object we can
|
||||
// find in the current environment.
|
||||
var obj = context.pop(), base;
|
||||
if (obj.type && obj.type.indexOf("variable") === 0) {
|
||||
if (options && options.additionalContext)
|
||||
base = options.additionalContext[obj.string];
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
base = base || global[obj.string];
|
||||
} else if (obj.type == "string") {
|
||||
base = "";
|
||||
} else if (obj.type == "atom") {
|
||||
base = 1;
|
||||
} else if (obj.type == "function") {
|
||||
if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
|
||||
(typeof global.jQuery == 'function'))
|
||||
base = global.jQuery();
|
||||
else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
|
||||
base = global._();
|
||||
}
|
||||
while (base != null && context.length)
|
||||
base = base[context.pop().string];
|
||||
if (base != null) gatherCompletions(base);
|
||||
} else {
|
||||
// If not, just look in the global object, any local scope, and optional additional-context
|
||||
// (reading into JS mode internals to get at the local and global variables)
|
||||
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
|
||||
for (var c = token.state.context; c; c = c.prev)
|
||||
for (var v = c.vars; v; v = v.next) maybeAdd(v.name)
|
||||
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
|
||||
if (options && options.additionalContext != null)
|
||||
for (var key in options.additionalContext)
|
||||
maybeAdd(key);
|
||||
if (!options || options.useGlobalScope !== false)
|
||||
gatherCompletions(global);
|
||||
forEach(keywords, maybeAdd);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
});
|
@ -0,0 +1,305 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
/*if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
|
||||
else */
|
||||
// Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var tables;
|
||||
var defaultTable;
|
||||
var keywords;
|
||||
var identifierQuote;
|
||||
var CONS = {
|
||||
QUERY_DIV: ";",
|
||||
ALIAS_KEYWORD: "AS"
|
||||
};
|
||||
var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
|
||||
|
||||
function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
|
||||
|
||||
function getKeywords(editor) {
|
||||
var mode = editor.doc.modeOption;
|
||||
if (mode === "sql") mode = "text/x-sql";
|
||||
return CodeMirror.resolveMode(mode).keywords;
|
||||
}
|
||||
|
||||
function getIdentifierQuote(editor) {
|
||||
var mode = editor.doc.modeOption;
|
||||
if (mode === "sql") mode = "text/x-sql";
|
||||
return CodeMirror.resolveMode(mode).identifierQuote || "`";
|
||||
}
|
||||
|
||||
function getText(item) {
|
||||
return typeof item == "string" ? item : item.text;
|
||||
}
|
||||
|
||||
function wrapTable(name, value) {
|
||||
if (isArray(value)) value = {columns: value}
|
||||
if (!value.text) value.text = name
|
||||
return value
|
||||
}
|
||||
|
||||
function parseTables(input) {
|
||||
var result = {}
|
||||
if (isArray(input)) {
|
||||
for (var i = input.length - 1; i >= 0; i--) {
|
||||
var item = input[i]
|
||||
result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
|
||||
}
|
||||
} else if (input) {
|
||||
for (var name in input)
|
||||
result[name.toUpperCase()] = wrapTable(name, input[name])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function getTable(name) {
|
||||
return tables[name.toUpperCase()]
|
||||
}
|
||||
|
||||
function shallowClone(object) {
|
||||
var result = {};
|
||||
for (var key in object) if (object.hasOwnProperty(key))
|
||||
result[key] = object[key];
|
||||
return result;
|
||||
}
|
||||
|
||||
function match(string, word) {
|
||||
var len = string.length;
|
||||
var sub = getText(word).substr(0, len);
|
||||
return string.toUpperCase() === sub.toUpperCase();
|
||||
}
|
||||
|
||||
function addMatches(result, search, wordlist, formatter) {
|
||||
if (isArray(wordlist)) {
|
||||
for (var i = 0; i < wordlist.length; i++)
|
||||
if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
|
||||
} else {
|
||||
for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
|
||||
var val = wordlist[word]
|
||||
if (!val || val === true)
|
||||
val = word
|
||||
else
|
||||
val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
|
||||
if (match(search, val)) result.push(formatter(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanName(name) {
|
||||
// Get rid name from identifierQuote and preceding dot(.)
|
||||
if (name.charAt(0) == ".") {
|
||||
name = name.substr(1);
|
||||
}
|
||||
// replace doublicated identifierQuotes with single identifierQuotes
|
||||
// and remove single identifierQuotes
|
||||
var nameParts = name.split(identifierQuote+identifierQuote);
|
||||
for (var i = 0; i < nameParts.length; i++)
|
||||
nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
|
||||
return nameParts.join(identifierQuote);
|
||||
}
|
||||
|
||||
function insertIdentifierQuotes(name) {
|
||||
var nameParts = getText(name).split(".");
|
||||
for (var i = 0; i < nameParts.length; i++)
|
||||
nameParts[i] = identifierQuote +
|
||||
// doublicate identifierQuotes
|
||||
nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
|
||||
identifierQuote;
|
||||
var escaped = nameParts.join(".");
|
||||
if (typeof name == "string") return escaped;
|
||||
name = shallowClone(name);
|
||||
name.text = escaped;
|
||||
return name;
|
||||
}
|
||||
|
||||
function nameCompletion(cur, token, result, editor) {
|
||||
// Try to complete table, column names and return start position of completion
|
||||
var useIdentifierQuotes = false;
|
||||
var nameParts = [];
|
||||
var start = token.start;
|
||||
var cont = true;
|
||||
while (cont) {
|
||||
cont = (token.string.charAt(0) == ".");
|
||||
useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
|
||||
|
||||
start = token.start;
|
||||
nameParts.unshift(cleanName(token.string));
|
||||
|
||||
token = editor.getTokenAt(Pos(cur.line, token.start));
|
||||
if (token.string == ".") {
|
||||
cont = true;
|
||||
token = editor.getTokenAt(Pos(cur.line, token.start));
|
||||
}
|
||||
}
|
||||
|
||||
// Try to complete table names
|
||||
var string = nameParts.join(".");
|
||||
addMatches(result, string, tables, function(w) {
|
||||
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
|
||||
});
|
||||
|
||||
// Try to complete columns from defaultTable
|
||||
addMatches(result, string, defaultTable, function(w) {
|
||||
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
|
||||
});
|
||||
|
||||
// Try to complete columns
|
||||
string = nameParts.pop();
|
||||
var table = nameParts.join(".");
|
||||
|
||||
var alias = false;
|
||||
var aliasTable = table;
|
||||
// Check if table is available. If not, find table by Alias
|
||||
if (!getTable(table)) {
|
||||
var oldTable = table;
|
||||
table = findTableByAlias(table, editor);
|
||||
if (table !== oldTable) alias = true;
|
||||
}
|
||||
|
||||
var columns = getTable(table);
|
||||
if (columns && columns.columns)
|
||||
columns = columns.columns;
|
||||
|
||||
if (columns) {
|
||||
addMatches(result, string, columns, function(w) {
|
||||
var tableInsert = table;
|
||||
if (alias == true) tableInsert = aliasTable;
|
||||
if (typeof w == "string") {
|
||||
w = tableInsert + "." + w;
|
||||
} else {
|
||||
w = shallowClone(w);
|
||||
w.text = tableInsert + "." + w.text;
|
||||
}
|
||||
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
|
||||
});
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
function eachWord(lineText, f) {
|
||||
var words = lineText.split(/\s+/)
|
||||
for (var i = 0; i < words.length; i++)
|
||||
if (words[i]) f(words[i].replace(/[,;]/g, ''))
|
||||
}
|
||||
|
||||
function findTableByAlias(alias, editor) {
|
||||
var doc = editor.doc;
|
||||
var fullQuery = doc.getValue();
|
||||
var aliasUpperCase = alias.toUpperCase();
|
||||
var previousWord = "";
|
||||
var table = "";
|
||||
var separator = [];
|
||||
var validRange = {
|
||||
start: Pos(0, 0),
|
||||
end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
|
||||
};
|
||||
|
||||
//add separator
|
||||
var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
|
||||
while(indexOfSeparator != -1) {
|
||||
separator.push(doc.posFromIndex(indexOfSeparator));
|
||||
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
|
||||
}
|
||||
separator.unshift(Pos(0, 0));
|
||||
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
|
||||
|
||||
//find valid range
|
||||
var prevItem = null;
|
||||
var current = editor.getCursor()
|
||||
for (var i = 0; i < separator.length; i++) {
|
||||
if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
|
||||
validRange = {start: prevItem, end: separator[i]};
|
||||
break;
|
||||
}
|
||||
prevItem = separator[i];
|
||||
}
|
||||
|
||||
if (validRange.start) {
|
||||
var query = doc.getRange(validRange.start, validRange.end, false);
|
||||
|
||||
for (var i = 0; i < query.length; i++) {
|
||||
var lineText = query[i];
|
||||
eachWord(lineText, function(word) {
|
||||
var wordUpperCase = word.toUpperCase();
|
||||
if (wordUpperCase === aliasUpperCase && getTable(previousWord))
|
||||
table = previousWord;
|
||||
if (wordUpperCase !== CONS.ALIAS_KEYWORD)
|
||||
previousWord = word;
|
||||
});
|
||||
if (table) break;
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
|
||||
tables = parseTables(options && options.tables)
|
||||
var defaultTableName = options && options.defaultTable;
|
||||
var disableKeywords = options && options.disableKeywords;
|
||||
defaultTable = defaultTableName && getTable(defaultTableName);
|
||||
keywords = getKeywords(editor);
|
||||
identifierQuote = getIdentifierQuote(editor);
|
||||
|
||||
if (defaultTableName && !defaultTable)
|
||||
defaultTable = findTableByAlias(defaultTableName, editor);
|
||||
|
||||
defaultTable = defaultTable || [];
|
||||
|
||||
if (defaultTable.columns)
|
||||
defaultTable = defaultTable.columns;
|
||||
|
||||
var cur = editor.getCursor();
|
||||
var result = [];
|
||||
var token = editor.getTokenAt(cur), start, end, search;
|
||||
if (token.end > cur.ch) {
|
||||
token.end = cur.ch;
|
||||
token.string = token.string.slice(0, cur.ch - token.start);
|
||||
}
|
||||
|
||||
if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
|
||||
search = token.string;
|
||||
start = token.start;
|
||||
end = token.end;
|
||||
} else {
|
||||
start = end = cur.ch;
|
||||
search = "";
|
||||
}
|
||||
if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
|
||||
start = nameCompletion(cur, token, result, editor);
|
||||
} else {
|
||||
var objectOrClass = function(w, className) {
|
||||
if (typeof w === "object") {
|
||||
w.className = className;
|
||||
} else {
|
||||
w = { text: w, className: className };
|
||||
}
|
||||
return w;
|
||||
};
|
||||
addMatches(result, search, defaultTable, function(w) {
|
||||
return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");
|
||||
});
|
||||
addMatches(
|
||||
result,
|
||||
search,
|
||||
tables, function(w) {
|
||||
return objectOrClass(w, "CodeMirror-hint-table");
|
||||
}
|
||||
);
|
||||
if (!disableKeywords)
|
||||
addMatches(result, search, keywords, function(w) {
|
||||
return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");
|
||||
});
|
||||
}
|
||||
|
||||
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
|
||||
});
|
||||
});
|
@ -0,0 +1,48 @@
|
||||
export default {
|
||||
name: 'JSelectBizQueryItem',
|
||||
props: {
|
||||
queryParam: Object,
|
||||
queryConfig: Array,
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
renderQueryItem() {
|
||||
return this.queryConfig.map(queryItem => {
|
||||
const {key, label, placeholder, dictCode, props, customRender} = queryItem
|
||||
const options = {
|
||||
props: {},
|
||||
on: {
|
||||
pressEnter: () => this.$emit('pressEnter'),
|
||||
}
|
||||
}
|
||||
if (props != null) {
|
||||
Object.assign(options.props, props)
|
||||
}
|
||||
if (placeholder === undefined) {
|
||||
if (dictCode) {
|
||||
options.props['placeholder'] = `请选择${label}`
|
||||
} else {
|
||||
options.props['placeholder'] = `请输入${label}`
|
||||
}
|
||||
} else {
|
||||
options.props['placeholder'] = placeholder
|
||||
}
|
||||
|
||||
let input
|
||||
if (typeof customRender === 'function') {
|
||||
input = customRender.call(this, {key, options, queryParam: this.queryParam})
|
||||
} else if (dictCode) {
|
||||
input = <j-dict-select-tag {...options} vModel={this.queryParam[key]} dictCode={dictCode} style="width:180px;"/>
|
||||
} else {
|
||||
input = <a-input {...options} vModel={this.queryParam[key]}/>
|
||||
}
|
||||
return <a-form-item key={key} label={label}>{input}</a-form-item>
|
||||
})
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return <span>{this.renderQueryItem()}</span>
|
||||
},
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
// base library
|
||||
import {
|
||||
ConfigProvider,
|
||||
Layout,
|
||||
Input,
|
||||
InputNumber,
|
||||
Button,
|
||||
Switch,
|
||||
Radio,
|
||||
Checkbox,
|
||||
Select,
|
||||
Card,
|
||||
Form,
|
||||
Row,
|
||||
Col,
|
||||
Modal,
|
||||
Table,
|
||||
Tabs,
|
||||
Icon,
|
||||
Badge,
|
||||
Popover,
|
||||
Dropdown,
|
||||
List,
|
||||
Avatar,
|
||||
Breadcrumb,
|
||||
Steps,
|
||||
Spin,
|
||||
Menu,
|
||||
Drawer,
|
||||
Tooltip,
|
||||
Alert,
|
||||
Tag,
|
||||
Divider,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Upload,
|
||||
Progress,
|
||||
Skeleton,
|
||||
Popconfirm,
|
||||
PageHeader,
|
||||
Result,
|
||||
Statistic,
|
||||
Descriptions,
|
||||
message,
|
||||
notification,
|
||||
Empty,
|
||||
Tree,
|
||||
TreeSelect,
|
||||
Carousel,
|
||||
Pagination,
|
||||
} from 'ant-design-vue'
|
||||
import Viser from 'viser-vue'
|
||||
|
||||
Vue.use(ConfigProvider)
|
||||
Vue.use(Layout)
|
||||
Vue.use(Input)
|
||||
Vue.use(InputNumber)
|
||||
Vue.use(Button)
|
||||
Vue.use(Switch)
|
||||
Vue.use(Radio)
|
||||
Vue.use(Checkbox)
|
||||
Vue.use(Select)
|
||||
Vue.use(Card)
|
||||
Vue.use(Form)
|
||||
Vue.use(Row)
|
||||
Vue.use(Col)
|
||||
Vue.use(Modal)
|
||||
Vue.use(Table)
|
||||
Vue.use(Tabs)
|
||||
Vue.use(Icon)
|
||||
Vue.use(Badge)
|
||||
Vue.use(Popover)
|
||||
Vue.use(Dropdown)
|
||||
Vue.use(List)
|
||||
Vue.use(Avatar)
|
||||
Vue.use(Breadcrumb)
|
||||
Vue.use(Steps)
|
||||
Vue.use(Spin)
|
||||
Vue.use(Menu)
|
||||
Vue.use(Drawer)
|
||||
Vue.use(Tooltip)
|
||||
Vue.use(Alert)
|
||||
Vue.use(Tag)
|
||||
Vue.use(Divider)
|
||||
Vue.use(DatePicker)
|
||||
Vue.use(TimePicker)
|
||||
Vue.use(Upload)
|
||||
Vue.use(Progress)
|
||||
Vue.use(Skeleton)
|
||||
Vue.use(Popconfirm)
|
||||
Vue.use(PageHeader)
|
||||
Vue.use(Result)
|
||||
Vue.use(Statistic)
|
||||
Vue.use(Descriptions)
|
||||
Vue.use(Empty)
|
||||
Vue.use(Tree)
|
||||
Vue.use(TreeSelect)
|
||||
Vue.use(Carousel)
|
||||
Vue.use(Pagination)
|
||||
|
||||
Vue.prototype.$confirm = Modal.confirm
|
||||
Vue.prototype.$message = message
|
||||
Vue.prototype.$notification = notification
|
||||
Vue.prototype.$info = Modal.info
|
||||
Vue.prototype.$success = Modal.success
|
||||
Vue.prototype.$error = Modal.error
|
||||
Vue.prototype.$warning = Modal.warning
|
||||
|
||||
process.env.NODE_ENV !== 'production' && console.warn('[jeecg-boot-vue] NOTICE: Antd use lazy-load.')
|
@ -0,0 +1,15 @@
|
||||
// src/icons.js
|
||||
|
||||
// export what you need
|
||||
export {
|
||||
default as SmileOutline
|
||||
} from '@ant-design/icons/lib/outline/SmileOutline';
|
||||
export {
|
||||
default as MehOutline
|
||||
} from '@ant-design/icons/lib/outline/MehOutline';
|
||||
|
||||
// export what antd other components need
|
||||
export {
|
||||
default as CloseOutline
|
||||
} from '@ant-design/icons/lib/outline/CloseOutline';
|
||||
// and other icons...
|
@ -0,0 +1,25 @@
|
||||
import Vue from 'vue'
|
||||
import { ONL_AUTH_FIELDS } from "@/store/mutation-types"
|
||||
import { getAction } from '@/api/manage'
|
||||
|
||||
|
||||
const online = {
|
||||
state: {
|
||||
//存储对象属性 value,text
|
||||
authFields: [],
|
||||
},
|
||||
mutations: {
|
||||
SET_AUTHFIELDS: (state, fields) => {
|
||||
console.log('fields',fields)
|
||||
Vue.set(state, 'authFields', fields)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// TODO 如果没找到可以尝试请求一下
|
||||
xxxxxx({ commit }, userInfo) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default online
|
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 功能模块
|
||||
* @type {{LEAVE_EARLY: {text: string, value: string}, LATE: {text: string, value: string}, ABSENT: {text: string, value: string}, NO_SIGN: {text: string, value: string}, NORMAL: {text: string, value: string}}}
|
||||
*/
|
||||
export const FunctionEnum = {
|
||||
EoaCmsBanner: { path: 'modules/eoa/cmsoa/modules/EoaCmsBanner', formData: 'carouselImg' },
|
||||
EoaCmsNewsInfo: { path: 'modules/eoa/cmsoa/modules/EoaCmsNewsInfo', formData: 'newsInfo' },
|
||||
EoaCmsRuleInfo: { path: 'modules/eoa/cmsoa/modules/EoaCmsRuleInfo', formData: 'ruleDownInfo' },
|
||||
EoaCmsSignNews: { path: 'modules/eoa/cmsoa/modules/EoaCmsSignNews', formData: 'signNews' },
|
||||
EoaCmsUserNotice: { path: 'modules/eoa/cmsoa/modules/EoaCmsUserNotice', formData: 'userNotice' },
|
||||
EoaCmsPlan: { path: 'modules/eoa/cmsoa/modules/EoaCmsPlan', formData: '' },
|
||||
EoaCmsLink: { path: 'modules/eoa/cmsoa/modules/EoaCmsLink', formData: '' },
|
||||
EoaCmsCommUse:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsCommUse', formData: '' },
|
||||
EoaCmsMyProcess:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsMyProcess', formData: '' },
|
||||
EoaCmsApplyProcess:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsApplyProcess', formData: '' },
|
||||
EoaCmsProcessNotice:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsProcessNotice', formData: '' },
|
||||
EoaCmsProcessChatData:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsProcessChatData', formData: '' },
|
||||
EoaCmsProcessTypeChat:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsProcessTypeChat', formData: '' },
|
||||
EoaCmsEmail:{ path: 'modules/eoa/cmsbpm/modules/EoaCmsEmail', formData: '' },
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
|
||||
<a-tabs>
|
||||
<a-tab-pane tab="基础示例" key="1" forceRender>
|
||||
<j-vxe-demo1/>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane tab="高级示例" key="2" forceRender>
|
||||
<j-vxe-demo2/>
|
||||
</a-tab-pane>
|
||||
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import JVxeDemo1 from '@views/jeecg/JVxeDemo/JVxeDemo1'
|
||||
import JVxeDemo2 from '@views/jeecg/JVxeDemo/JVxeDemo2'
|
||||
|
||||
export default {
|
||||
name: 'JVXETableDemo',
|
||||
components: {JVxeDemo2, JVxeDemo1},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<a-tabs>
|
||||
<a-tab-pane tab="ERP布局模板" key="erp">
|
||||
<erp-template/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="布局模板1" key="1">
|
||||
<template1/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="布局模板2" key="2">
|
||||
<template2/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="布局模板3" key="3">
|
||||
<template3/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="布局模板4" key="4">
|
||||
<template4/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="布局模板5" key="5">
|
||||
<template5/>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Template1 from './Template1'
|
||||
import Template2 from './Template2'
|
||||
import Template3 from './Template3'
|
||||
import Template4 from './Template4'
|
||||
import Template5 from './Template5'
|
||||
import ErpTemplate from './ErpTemplate'
|
||||
|
||||
export default {
|
||||
name: 'LayoutDemo',
|
||||
components: {Template5, Template4, Template3, Template2, Template1, ErpTemplate}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue