parent
f131de1dc4
commit
5e7590b474
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 286 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1,212 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-checkbox">
|
||||||
|
<template v-if="valueIsObject">
|
||||||
|
<el-select
|
||||||
|
v-if="showType === 'default'"
|
||||||
|
v-model="dataValue.select"
|
||||||
|
:disabled="disabled"
|
||||||
|
:clearable="clearable"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
style="width: 100%;"
|
||||||
|
multiple
|
||||||
|
@change="valueChange">
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in options"
|
||||||
|
:key="index"
|
||||||
|
:label="!isEmptyValue(item.value) ? item.label || item.name : item "
|
||||||
|
:value="getValue(item)"/>
|
||||||
|
</el-select>
|
||||||
|
<el-checkbox-group
|
||||||
|
v-else-if="showType === 'tiled'"
|
||||||
|
v-model="dataValue.select"
|
||||||
|
:disabled="disabled"
|
||||||
|
@change="valueChange">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="(item, index) in options"
|
||||||
|
:key="index"
|
||||||
|
:label="getValue(item)">
|
||||||
|
{{ !isEmptyValue(item.value) ? item.label || item.name : item }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
<el-input
|
||||||
|
v-if="dataValue.select.includes('其他')"
|
||||||
|
v-model="dataValue.otherValue"
|
||||||
|
:disabled="disabled"
|
||||||
|
:maxlength="100"
|
||||||
|
placeholder="其他选项需填写,否则为无效选项"
|
||||||
|
@blur="inputBlur"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { isObject, isEmpty } from '@/utils/types'
|
||||||
|
import { valueEquals } from 'element-ui/lib/utils/util'
|
||||||
|
import Emitter from 'element-ui/lib/mixins/emitter'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 自定义字段库 多选
|
||||||
|
name: 'WkCheckbox',
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
|
value: {},
|
||||||
|
// 选择其他展示input输入框
|
||||||
|
otherShowInput: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
disabled: Boolean,
|
||||||
|
clearable: Boolean,
|
||||||
|
placeholder: String,
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showType: {
|
||||||
|
type: String,
|
||||||
|
default: 'default' // 下拉 default 平铺 tiled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataValue: {
|
||||||
|
select: [],
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
valueIsObject() {
|
||||||
|
return isObject(this.dataValue)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(newVal, oldVal) {
|
||||||
|
this.validValue()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 验证值
|
||||||
|
*/
|
||||||
|
validValue() {
|
||||||
|
if (isEmpty(this.value)) {
|
||||||
|
this.dataValue = {
|
||||||
|
select: [],
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.otherShowInput) {
|
||||||
|
const otherItem = this.value.filter((name) => !this.options.includes(name))
|
||||||
|
if (otherItem.length > 0) {
|
||||||
|
const newValue = this.value.filter((name) => !otherItem.includes(name))
|
||||||
|
newValue.push('其他')
|
||||||
|
this.dataValue = {
|
||||||
|
select: newValue,
|
||||||
|
otherValue: otherItem[otherItem.length - 1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!valueEquals(this.value, this.dataValue.select)) {
|
||||||
|
this.dataValue = {
|
||||||
|
select: this.value,
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.dataValue = {
|
||||||
|
select: this.value,
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选项值
|
||||||
|
*/
|
||||||
|
getValue(item) {
|
||||||
|
return !this.isEmptyValue(item.value) ? item.value : item
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是空值
|
||||||
|
*/
|
||||||
|
isEmptyValue(value) {
|
||||||
|
return value === null || value == undefined
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值更新
|
||||||
|
*/
|
||||||
|
valueChange() {
|
||||||
|
if (this.dataValue.select.includes('其他')) {
|
||||||
|
const newValue = this.dataValue.select.filter(item => item !== '其他')
|
||||||
|
newValue.push(this.dataValue.otherValue.trim())
|
||||||
|
this.$emit('input', newValue)
|
||||||
|
this.$emit('change', newValue)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', newValue)
|
||||||
|
} else {
|
||||||
|
this.dataValue.otherValue = ''
|
||||||
|
this.$emit('input', this.dataValue.select)
|
||||||
|
this.$emit('change', this.dataValue.select)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', this.dataValue.select)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失去焦点
|
||||||
|
*/
|
||||||
|
inputBlur() {
|
||||||
|
this.valueChange()
|
||||||
|
// const value = this.dataValue.otherValue
|
||||||
|
// const eIsObject = this.options.length > 0 && !this.isEmptyValue(this.options[0].value)
|
||||||
|
// const has = this.options.find(item => {
|
||||||
|
// if (eIsObject) {
|
||||||
|
// return item.value === value.trim()
|
||||||
|
// } else {
|
||||||
|
// return item === value.trim()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// if (has) {
|
||||||
|
// this.dataValue.otherValue = ''
|
||||||
|
// }
|
||||||
|
// this.$emit('change', this.dataValue.select)
|
||||||
|
// this.$emit('input', this.dataValue.select)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-checkbox {
|
||||||
|
.el-input {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-checkbox-group {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-desc-text">
|
||||||
|
<tinymce
|
||||||
|
v-bind="$attrs"
|
||||||
|
:disabled="true" :toolbar="[]" :init="{
|
||||||
|
statusbar: false,
|
||||||
|
placeholder: '描述文字内容',
|
||||||
|
content_style: ' * {color: #262626; margin: 0;} body { font-size: 14px; }',
|
||||||
|
quickbars_selection_toolbar: false,
|
||||||
|
contextmenu: '',
|
||||||
|
plugins: 'autoresize',
|
||||||
|
autoresize_bottom_margin: 0
|
||||||
|
}" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Tinymce from '@/components/Tinymce'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 描述文字
|
||||||
|
name: 'WkDescText',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Tinymce
|
||||||
|
},
|
||||||
|
|
||||||
|
inheritAttrs: false,
|
||||||
|
|
||||||
|
props: {},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wk-desc-text {
|
||||||
|
.tox-tinymce {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox .tox-edit-area__iframe {
|
||||||
|
background-color: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,160 @@
|
|||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:data="fieldFrom"
|
||||||
|
:row-key="Date.now().toString()"
|
||||||
|
class="wk-table-items"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column
|
||||||
|
label="序号"
|
||||||
|
width="50">
|
||||||
|
<template slot-scope="{ row, column, $index }">
|
||||||
|
{{ $index + 1 }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(item, index) in fieldList"
|
||||||
|
v-if="getShowValue(item)"
|
||||||
|
:key="index"
|
||||||
|
:prop="item.field"
|
||||||
|
:min-width="getMinWidth(item.formType)">
|
||||||
|
<template
|
||||||
|
slot="header"
|
||||||
|
slot-scope="scope">
|
||||||
|
<span v-if="item.isNull == 1" class="red">*</span>{{ item.name }}
|
||||||
|
</template>
|
||||||
|
<template slot-scope="{ row, column, $index }">
|
||||||
|
<wk-form-item
|
||||||
|
:prop-prefix="`${propPrefix || ''}[${$index}].`"
|
||||||
|
:item="fieldList[index]"
|
||||||
|
:index="$index"
|
||||||
|
:field-from="fieldFrom[$index]"
|
||||||
|
:disabled="disabled"
|
||||||
|
@change="fieldChange"
|
||||||
|
>
|
||||||
|
<template slot-scope="{ data, index }">
|
||||||
|
<slot :data="data" :index="$index" />
|
||||||
|
</template>
|
||||||
|
</wk-form-item>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:resizable="false"
|
||||||
|
fixed="right"
|
||||||
|
label="操作"
|
||||||
|
width="60">
|
||||||
|
<template slot-scope="{ row, column, $index }">
|
||||||
|
<el-button
|
||||||
|
icon="wk wk-icon-bin" type="text" @click="deleteClick($index)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// table 风格展示事项
|
||||||
|
name: 'WkTableItems',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkFormItem: () => import('../WkForm/WkFormItem')
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
// 表单验证前缀
|
||||||
|
propPrefix: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
fieldFrom: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fieldList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
deleteClick(index) {
|
||||||
|
this.$emit('delete', index)
|
||||||
|
},
|
||||||
|
|
||||||
|
getMinWidth(formType) {
|
||||||
|
if (formType === 'date_interval' ||
|
||||||
|
formType === 'dateRange' ||
|
||||||
|
formType === 'file' ||
|
||||||
|
formType === 'location' ||
|
||||||
|
formType === 'position') {
|
||||||
|
return 250
|
||||||
|
}
|
||||||
|
return 150
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断展示
|
||||||
|
*/
|
||||||
|
getShowValue(item) {
|
||||||
|
if (item.hasOwnProperty('show')) {
|
||||||
|
return item.show
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段change
|
||||||
|
*/
|
||||||
|
fieldChange(item, index, value, valueList) {
|
||||||
|
this.$emit('change', item, index, value, valueList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wk-table-items {
|
||||||
|
th {
|
||||||
|
line-height: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-form-item {
|
||||||
|
padding: 8px 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
.el-form-item__label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.red {
|
||||||
|
color: #F56C6C;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-distpicker">
|
||||||
|
<el-cascader
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-model="dataValue"
|
||||||
|
:options="options"
|
||||||
|
:props="config"
|
||||||
|
@change="handleChange"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DISTRICTS from '../../VDistpicker/districts'
|
||||||
|
import { valueEquals } from 'element-ui/lib/utils/util'
|
||||||
|
import { isObject } from '@/utils/types'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// WkDistpicker
|
||||||
|
name: 'WkDistpicker',
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
inheritAttrs: false,
|
||||||
|
|
||||||
|
props: {
|
||||||
|
hideArea: { type: Boolean, default: false },
|
||||||
|
onlyProvince: { type: Boolean, default: false },
|
||||||
|
value: Array,
|
||||||
|
props: Object
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataValue: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
options() {
|
||||||
|
return this.getOptions()
|
||||||
|
},
|
||||||
|
|
||||||
|
config() {
|
||||||
|
const props = this.props || {}
|
||||||
|
return {
|
||||||
|
label: 'name',
|
||||||
|
value: 'code',
|
||||||
|
...props
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler() {
|
||||||
|
this.validateValue()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getOptions() {
|
||||||
|
const list = DISTRICTS
|
||||||
|
if (!this.onlyProvince && !this.hideArea) {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
const newList = []
|
||||||
|
list.forEach(provinceItem => {
|
||||||
|
const province = {
|
||||||
|
code: provinceItem.code,
|
||||||
|
name: provinceItem.name
|
||||||
|
}
|
||||||
|
if (!this.onlyProvince) {
|
||||||
|
province.children = []
|
||||||
|
provinceItem.children.forEach(cityItem => {
|
||||||
|
const city = {
|
||||||
|
code: cityItem.code,
|
||||||
|
name: cityItem.name
|
||||||
|
}
|
||||||
|
province.children.push(city)
|
||||||
|
if (!this.hideArea) {
|
||||||
|
city.children = cityItem.children
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
newList.push(province)
|
||||||
|
})
|
||||||
|
|
||||||
|
return newList
|
||||||
|
},
|
||||||
|
|
||||||
|
validateValue() {
|
||||||
|
if (this.value && this.value.length) {
|
||||||
|
let dataValue = this.value
|
||||||
|
if (isObject(this.value[0])) {
|
||||||
|
dataValue = this.value.map(item => item[this.config.value])
|
||||||
|
}
|
||||||
|
if (!valueEquals(dataValue, this.dataValue)) {
|
||||||
|
this.dataValue = dataValue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.dataValue = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange() {
|
||||||
|
const objValue = this.getCascaderValArr(this.dataValue, this.options)
|
||||||
|
this.$emit('input', objValue)
|
||||||
|
this.$emit('change', objValue)
|
||||||
|
},
|
||||||
|
|
||||||
|
getCascaderValArr(value, data) {
|
||||||
|
const res = []
|
||||||
|
if (value.length === 0) return res
|
||||||
|
let index = 0
|
||||||
|
do {
|
||||||
|
const findRes = data.find(o => o.code === value[index])
|
||||||
|
if (findRes) {
|
||||||
|
data = findRes.children || []
|
||||||
|
res.push({
|
||||||
|
code: findRes.code,
|
||||||
|
name: findRes.name,
|
||||||
|
id: index + 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
} while (index <= value.length)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-cascader {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,322 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="ignoreFields.includes(item.field)">
|
||||||
|
<slot :data="item" :index="index" />
|
||||||
|
</div>
|
||||||
|
<el-input
|
||||||
|
v-else-if="item.form_type == 'text'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:maxlength="100"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:type="item.form_type"
|
||||||
|
@input="commonChange(item, index, $event)"/>
|
||||||
|
<el-input
|
||||||
|
v-else-if="isTrimInput(item.form_type)"
|
||||||
|
v-model.trim="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:prefix-icon="getInputIcon(item.form_type)"
|
||||||
|
:maxlength="getInputMaxlength(item.form_type)"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
type="text"
|
||||||
|
@input="commonChange(item, index, $event)"/>
|
||||||
|
<el-input-number
|
||||||
|
v-else-if="item.form_type == 'number'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:controls="false"
|
||||||
|
@change="commonChange(item, index, $event)" />
|
||||||
|
<el-input-number
|
||||||
|
v-else-if="item.form_type == 'floatnumber'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:controls="false"
|
||||||
|
@change="commonChange(item, index, $event)" />
|
||||||
|
<wk-percent-input
|
||||||
|
v-else-if="item.form_type == 'percent'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:controls="false"
|
||||||
|
@change="commonChange(item, index, $event)" />
|
||||||
|
<el-input
|
||||||
|
v-else-if="item.form_type == 'textarea'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:rows="3"
|
||||||
|
:autosize="{ minRows: 3}"
|
||||||
|
:maxlength="item.maxlength || 800"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:type="item.form_type"
|
||||||
|
resize="none"
|
||||||
|
@input="commonChange(item, index, $event)" />
|
||||||
|
<wk-select
|
||||||
|
v-else-if="['select'].includes(item.form_type)"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:clearable="item.clearable"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:options="item.setting"
|
||||||
|
:show-type="item.precisions === 1 ? 'tiled' : 'default'"
|
||||||
|
:other-show-input="item.hasOwnProperty('optionsData')"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<wk-checkbox
|
||||||
|
v-else-if="['checkbox'].includes(item.form_type)"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:clearable="item.clearable"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:options="item.setting"
|
||||||
|
:show-type="item.precisions === 1 ? 'tiled' : 'default'"
|
||||||
|
:other-show-input="item.hasOwnProperty('optionsData')"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<!-- <el-select
|
||||||
|
v-else-if="['checkbox', 'select'].includes(item.form_type)"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:clearable="item.clearable"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
:multiple="item.form_type === 'checkbox'"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="commonChange(item, index, $event)">
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in item.setting"
|
||||||
|
:key="index"
|
||||||
|
:label="!isEmptyValue(item.value) ? item.label || item.name : item "
|
||||||
|
:value="!isEmptyValue(item.value) ? item.value : item"/>
|
||||||
|
</el-select> -->
|
||||||
|
<!-- <el-select
|
||||||
|
v-else-if="item.form_type == 'checkbox'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:clearable="item.clearable"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
multiple
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="commonChange(item, index, $event)">
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in item.setting"
|
||||||
|
:key="index"
|
||||||
|
:label="!isEmptyValue(item.value) ? item.label || item.name : item "
|
||||||
|
:value="!isEmptyValue(item.value) ? item.value : item"/>
|
||||||
|
</el-select> -->
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="item.form_type == 'date'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
clearable
|
||||||
|
style="width: 100%;"
|
||||||
|
type="date"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
placeholder="选择日期"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="item.form_type == 'dateRange'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:type="item.dateType || 'daterange'"
|
||||||
|
:value-format="item.dateValueFormat || 'yyyy-MM-dd'"
|
||||||
|
clearable
|
||||||
|
style="width: 100%;vertical-align: middle;"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="item.form_type == 'datetime'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
clearable
|
||||||
|
style="width: 100%;"
|
||||||
|
type="datetime"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
placeholder="选择日期"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<wk-dep-select
|
||||||
|
v-else-if="item.form_type == 'structure'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:request="item.request"
|
||||||
|
:props="item.props"
|
||||||
|
:params="item.params"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:radio="!isEmptyValue(item.radio) ? item.radio : true"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="depOrUserChange(item, index, arguments[0], arguments[1])"
|
||||||
|
/>
|
||||||
|
<wk-user-select
|
||||||
|
v-else-if="['single_user', 'user'].includes(item.form_type)"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:request="item.request"
|
||||||
|
:props="item.props"
|
||||||
|
:params="item.params"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:radio="!isEmptyValue(item.radio) ? item.radio : true"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="depOrUserChange(item, index, arguments[0], arguments[1])"
|
||||||
|
/>
|
||||||
|
<el-radio-group
|
||||||
|
v-else-if="item.form_type == 'radio'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
@change="commonChange(item, index, $event)">
|
||||||
|
<el-radio
|
||||||
|
v-for="(item, index) in item.setting"
|
||||||
|
:key="index"
|
||||||
|
:label="!isEmptyValue(item.value) ? item.value : item">
|
||||||
|
{{ !isEmptyValue(item.value) ? item.label || item.name : item }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<el-switch
|
||||||
|
v-else-if="item.form_type == 'boolean_value'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<wk-position
|
||||||
|
v-else-if="item.form_type == 'position'"
|
||||||
|
:hide-area="item.hideArea"
|
||||||
|
:only-province="item.onlyProvince"
|
||||||
|
:show-detail="item.showDetail"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<wk-location
|
||||||
|
v-else-if="item.form_type == 'location'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<wk-signature-pad
|
||||||
|
v-else-if="item.form_type == 'handwriting_sign'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"/>
|
||||||
|
<wk-desc-text
|
||||||
|
v-else-if="item.form_type == 'desc_text'"
|
||||||
|
:value="fieldFrom[item.field]"/>
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="item.form_type === 'date_interval'"
|
||||||
|
v-model="fieldFrom[item.field]"
|
||||||
|
:type="item.dateType || 'daterange'"
|
||||||
|
:value-format="item.dateValueFormat || 'yyyy-MM-dd'"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
style="width: 100%;vertical-align: middle;"
|
||||||
|
clearable
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
@change="commonChange(item, index, $event)"/>
|
||||||
|
<v-distpicker
|
||||||
|
v-else-if="item.form_type == 'address'"
|
||||||
|
:province="fieldFrom[item.field].province"
|
||||||
|
:city="fieldFrom[item.field].city"
|
||||||
|
:area="fieldFrom[item.field].area"
|
||||||
|
@province="selectProvince($event, item, index)"
|
||||||
|
@city="selectCity($event, item, index)"
|
||||||
|
@area="selectArea($event, item, index)"/>
|
||||||
|
<xh-files
|
||||||
|
v-else-if="item.form_type == 'file'"
|
||||||
|
:value="fieldFrom[item.field]"
|
||||||
|
:disabled="item.disabled || disabled"
|
||||||
|
@value-change="oldChange($event, item, index)"
|
||||||
|
/>
|
||||||
|
<wk-detail-table
|
||||||
|
v-else-if="item.form_type == 'detail_table'"
|
||||||
|
:show-type="item.precisions === 2 ? 'table' : 'default'"
|
||||||
|
:title="item.name"
|
||||||
|
:prop-prefix="item.field"
|
||||||
|
:btn-name="item.remark"
|
||||||
|
:add-field-list="item.fieldExtendList"
|
||||||
|
:add-field-form="item.fieldForm"
|
||||||
|
:field-form="fieldFrom[item.field]"
|
||||||
|
:field-list="item.fieldList"
|
||||||
|
:disabled="item.disabled || disabled"/>
|
||||||
|
<div v-else>
|
||||||
|
<slot :data="item" :index="index" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkUserSelect from '@/components/NewCom/WkUserSelect'
|
||||||
|
import WkDepSelect from '@/components/NewCom/WkDepSelect'
|
||||||
|
import WkPosition from '@/components/NewCom/WkPosition'
|
||||||
|
import WkLocation from '@/components/NewCom/WkLocation'
|
||||||
|
import WkSignaturePad from '@/components/NewCom/WkSignaturePad'
|
||||||
|
import WkDescText from '@/components/NewCom/WkDescText'
|
||||||
|
import WkPercentInput from '@/components/NewCom/WkPercentInput'
|
||||||
|
import WkSelect from '@/components/NewCom/WkSelect'
|
||||||
|
import WkCheckbox from '@/components/NewCom/WkCheckbox'
|
||||||
|
import WkDetailTable from '@/components/NewCom/WkDetailTable'
|
||||||
|
import VDistpicker from '@/components/VDistpicker'
|
||||||
|
import { XhFiles } from '@/components/CreateCom'
|
||||||
|
|
||||||
|
import Mixin from './Mixin'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 字段
|
||||||
|
name: 'WkField',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkUserSelect,
|
||||||
|
WkDepSelect,
|
||||||
|
WkPosition,
|
||||||
|
WkLocation,
|
||||||
|
WkSignaturePad,
|
||||||
|
WkDescText,
|
||||||
|
WkPercentInput,
|
||||||
|
WkSelect,
|
||||||
|
WkCheckbox,
|
||||||
|
WkDetailTable,
|
||||||
|
VDistpicker,
|
||||||
|
XhFiles
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [Mixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
item: Object,
|
||||||
|
index: Number,
|
||||||
|
fieldFrom: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 忽略的字段直接输出
|
||||||
|
ignoreFields: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number {
|
||||||
|
width: 100%;
|
||||||
|
/deep/ .el-input__inner {
|
||||||
|
text-align: left;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,192 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="`is-${form_type}`"
|
||||||
|
class="wk-field-view"
|
||||||
|
>
|
||||||
|
<template v-if="ignoreFields.includes(props.field)">
|
||||||
|
<slot :data="$props" />
|
||||||
|
</template>
|
||||||
|
<span v-else-if="isCommonType">{{ getCommonShowValue() }}</span>
|
||||||
|
<el-switch
|
||||||
|
v-else-if="form_type == 'boolean_value'"
|
||||||
|
:value="value"
|
||||||
|
disabled
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0"
|
||||||
|
/>
|
||||||
|
<wk-signature-image
|
||||||
|
v-else-if="form_type == 'handwriting_sign'"
|
||||||
|
:src=" !!value ? value.url:''"
|
||||||
|
:height="config.signatureHeight"
|
||||||
|
/>
|
||||||
|
<wk-desc-text
|
||||||
|
v-else-if="form_type == 'desc_text'"
|
||||||
|
:key="Date.now().toString()"
|
||||||
|
:value="value"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else-if="form_type == 'location'"
|
||||||
|
:class="{'can-check':objectHasValue(value, 'address')}"
|
||||||
|
@click.stop="mapViewShow=true"
|
||||||
|
>{{ objectHasValue(value, 'address') ? value.address : '--' }}</span>
|
||||||
|
<span
|
||||||
|
v-else-if="form_type == 'website'"
|
||||||
|
:class="{'can-check': !isEmpty}"
|
||||||
|
@click.stop="openUrl(value)"
|
||||||
|
>{{ value }}</span>
|
||||||
|
<file-list-view
|
||||||
|
v-else-if="form_type == 'file'"
|
||||||
|
:list="value || []"
|
||||||
|
/>
|
||||||
|
<wk-detail-table-view
|
||||||
|
v-else-if="form_type == 'detail_table'"
|
||||||
|
:show-type="props.precisions === 2 ? 'table' : 'default'"
|
||||||
|
:title="props.name"
|
||||||
|
:add-field-list="props.fieldExtendList"
|
||||||
|
:field-form="value"
|
||||||
|
:field-list="props.fieldList"
|
||||||
|
>
|
||||||
|
<template slot-scope="{ data }">
|
||||||
|
<slot :data="data" />
|
||||||
|
</template>
|
||||||
|
</wk-detail-table-view>
|
||||||
|
<template v-else>
|
||||||
|
<slot :data="$props" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<map-view
|
||||||
|
v-if="mapViewShow"
|
||||||
|
:title="value.address"
|
||||||
|
:lat="value.lat"
|
||||||
|
:lng="value.lng"
|
||||||
|
@hidden="mapViewShow=false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkSignatureImage from '@/components/NewCom/WkSignaturePad/Image'
|
||||||
|
import WkDescText from '@/components/NewCom/WkDescText'
|
||||||
|
import MapView from '@/components/MapView' // 地图详情
|
||||||
|
import FileListView from '@/components/FileListView' // 附件
|
||||||
|
import WkDetailTableView from '@/components/NewCom/WkDetailTable/View'
|
||||||
|
|
||||||
|
import merge from '@/utils/merge'
|
||||||
|
import { isObject, isEmpty } from '@/utils/types'
|
||||||
|
import { getFormFieldShowName } from './utils'
|
||||||
|
|
||||||
|
const DefaultWkFieldView = {
|
||||||
|
signatureHeight: '26px'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 特殊字段展示
|
||||||
|
name: 'WkFieldView',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkSignatureImage,
|
||||||
|
WkDescText,
|
||||||
|
MapView,
|
||||||
|
FileListView,
|
||||||
|
WkDetailTableView
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
props: Object, // 自定义字段参数信息
|
||||||
|
form_type: String,
|
||||||
|
value: [String, Object, Array, Number],
|
||||||
|
// 忽略的字段直接输出
|
||||||
|
ignoreFields: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 控制展示地图详情
|
||||||
|
mapViewShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
return merge({ ...DefaultWkFieldView }, this.props || {})
|
||||||
|
},
|
||||||
|
isEmpty() {
|
||||||
|
return isEmpty(this.value)
|
||||||
|
},
|
||||||
|
isCommonType() {
|
||||||
|
return [
|
||||||
|
'text',
|
||||||
|
'textarea',
|
||||||
|
'website',
|
||||||
|
'select',
|
||||||
|
'checkbox',
|
||||||
|
'number',
|
||||||
|
'floatnumber',
|
||||||
|
'percent',
|
||||||
|
'mobile',
|
||||||
|
'email',
|
||||||
|
'date',
|
||||||
|
'datetime',
|
||||||
|
'date_interval',
|
||||||
|
'user',
|
||||||
|
'structure',
|
||||||
|
'position'
|
||||||
|
].includes(this.form_type)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 判断对象是否值
|
||||||
|
*/
|
||||||
|
objectHasValue(obj, key) {
|
||||||
|
if (isObject(obj)) {
|
||||||
|
return !isEmpty(obj[key])
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
openUrl(url) {
|
||||||
|
if (!url.match(/^https?:\/\//i)) {
|
||||||
|
url = 'http://' + url
|
||||||
|
}
|
||||||
|
window.open(url)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类型的展示值
|
||||||
|
*/
|
||||||
|
getCommonShowValue() {
|
||||||
|
return getFormFieldShowName(this.form_type, this.value, '', this.props)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-field-view {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
.can-check {
|
||||||
|
color: $xr-color-primary;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-website {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,130 @@
|
|||||||
|
<template>
|
||||||
|
<el-form-item
|
||||||
|
v-if="getShowValue(item)"
|
||||||
|
:key="index"
|
||||||
|
:prop="`${propPrefix || ''}${item.field}`"
|
||||||
|
:rules="item.rules"
|
||||||
|
:class="[item.className || '', `is-${item.form_type}`]"
|
||||||
|
:style="{width: item.style_percent ? `${item.style_percent}%` : 'auto'}"
|
||||||
|
class="wk-form-item">
|
||||||
|
<template slot="label">
|
||||||
|
{{ item.name }}
|
||||||
|
<el-tooltip
|
||||||
|
v-if="item.tipType == 'tooltip'"
|
||||||
|
effect="dark"
|
||||||
|
placement="top">
|
||||||
|
<div slot="content" v-html="getTips(item)"/>
|
||||||
|
<i class="wk wk-help wk-help-tips"/>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else style="color:#999;">
|
||||||
|
{{ getTips(item) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<wk-field
|
||||||
|
:item="item"
|
||||||
|
:index="index"
|
||||||
|
:field-from="fieldFrom"
|
||||||
|
:ignore-fields="ignoreFields"
|
||||||
|
:disabled="disabled"
|
||||||
|
@change="fieldChange"
|
||||||
|
>
|
||||||
|
<template slot-scope="{ data, index }">
|
||||||
|
<slot :data="data" :index="index" />
|
||||||
|
</template>
|
||||||
|
</wk-field>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkField from './WkField'
|
||||||
|
|
||||||
|
import Mixin from './Mixin'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// item
|
||||||
|
name: 'WkFormItem',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkField
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [Mixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
// 表单验证前缀
|
||||||
|
propPrefix: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
item: Object,
|
||||||
|
index: Number,
|
||||||
|
fieldFrom: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 忽略的字段直接输出
|
||||||
|
ignoreFields: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fieldChange(item, index, value, valueList) {
|
||||||
|
this.$emit('change', item, index, value, valueList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wk-form-item {
|
||||||
|
.el-form-item__label {
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
word-break: break-all;
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item__error {
|
||||||
|
position: relative;
|
||||||
|
top: auto;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item.is-desc_text {
|
||||||
|
.el-form-item__label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-form-item {
|
||||||
|
padding: 12px 12px 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,62 @@
|
|||||||
|
import { isArray, isObject, isEmpty } from '@/utils/types'
|
||||||
|
import CheckStatusMixin from '@/mixins/CheckStatusMixin'
|
||||||
|
import CustomFieldsMixin from '@/mixins/CustomFields'
|
||||||
|
import { separator } from '@/filters/vueNumeralFilter/filters'
|
||||||
|
import { getWkDateTime } from '@/utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自定义字段展示值
|
||||||
|
* @param {*} form_type
|
||||||
|
* @param {*} value
|
||||||
|
* @param {*} placeholder
|
||||||
|
* @param {*} item 自定义字段模型
|
||||||
|
* @returns 字符串
|
||||||
|
*/
|
||||||
|
export function getFormFieldShowName(form_type, value, placeholder = '--', item) {
|
||||||
|
if (form_type === 'position') {
|
||||||
|
return isArray(value) ? value.map(item => item.name).join() : placeholder
|
||||||
|
} else if (form_type === 'floatnumber') {
|
||||||
|
return isEmpty(value) ? '' : separator(value)
|
||||||
|
} else if (form_type === 'date') {
|
||||||
|
return getWkDateTime(value)
|
||||||
|
} else if (form_type === 'location') {
|
||||||
|
return isObject(value) ? value.address : placeholder
|
||||||
|
} else if (form_type === 'date_interval') {
|
||||||
|
return isArray(value) ? value.join('-') : placeholder
|
||||||
|
} else if (form_type === 'percent') {
|
||||||
|
return isEmpty(value) ? placeholder : `${value}%`
|
||||||
|
} else if (form_type === 'single_user') {
|
||||||
|
if (isObject(value)) {
|
||||||
|
return value.realname || placeholder
|
||||||
|
}
|
||||||
|
return value || placeholder
|
||||||
|
} else if (form_type === 'select') {
|
||||||
|
const newValue = CustomFieldsMixin.methods.getRealParams({ form_type }, value)
|
||||||
|
if (isEmpty(newValue)) {
|
||||||
|
return placeholder
|
||||||
|
} else {
|
||||||
|
return newValue
|
||||||
|
}
|
||||||
|
} else if (form_type === 'checkbox') {
|
||||||
|
const newValue = CustomFieldsMixin.methods.getRealParams({ form_type }, value)
|
||||||
|
if (isEmpty(newValue)) {
|
||||||
|
return placeholder
|
||||||
|
} else {
|
||||||
|
return newValue
|
||||||
|
}
|
||||||
|
} else if (form_type === 'structure') {
|
||||||
|
if (isArray(value)) {
|
||||||
|
return value.map(item => item.name).join() || placeholder
|
||||||
|
}
|
||||||
|
return value || placeholder
|
||||||
|
} else if (form_type === 'user') {
|
||||||
|
if (isArray(value)) {
|
||||||
|
return value.map(item => item.realname).join() || placeholder
|
||||||
|
}
|
||||||
|
return value || placeholder
|
||||||
|
} else if (form_type === 'check_status') {
|
||||||
|
return CheckStatusMixin.methods.getStatusName(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isEmpty(value) ? placeholder : value
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="wk-location"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false">
|
||||||
|
<el-input
|
||||||
|
v-model="dataValue.address"
|
||||||
|
:disabled="disabled"
|
||||||
|
readonly
|
||||||
|
clearable
|
||||||
|
placeholder="点击定位"
|
||||||
|
@click.native="inputClick"
|
||||||
|
@clear="inputClear">
|
||||||
|
<template slot="suffix">
|
||||||
|
<i
|
||||||
|
v-if="dataValue.address && hovering"
|
||||||
|
class="el-icon-circle-close"
|
||||||
|
style="cursor: pointer;"
|
||||||
|
@click.stop="inputClear" />
|
||||||
|
<i v-else class="wk wk-icon-location" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<wk-location-point-dialog
|
||||||
|
:value="dataValue"
|
||||||
|
:visible.sync="pointDialogVisible"
|
||||||
|
@select="pointSelect"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkLocationPointDialog from '../WkLocationPointDialog'
|
||||||
|
|
||||||
|
import { isObject } from '@/utils/types'
|
||||||
|
import { valueEquals } from 'element-ui/lib/utils/util'
|
||||||
|
import Emitter from 'element-ui/lib/mixins/emitter'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 定位
|
||||||
|
name: 'WkLocation',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkLocationPointDialog
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
|
value: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hovering: false,
|
||||||
|
dataValue: this.getDefaultValue(),
|
||||||
|
pointDialogVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(val) {
|
||||||
|
if (!valueEquals(val, this.dataValue)) {
|
||||||
|
if (isObject(this.value)) {
|
||||||
|
this.dataValue = val
|
||||||
|
} else {
|
||||||
|
this.dataValue = this.getDefaultValue()
|
||||||
|
this.$emit('input', this.dataValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getDefaultValue() {
|
||||||
|
return {
|
||||||
|
lat: '',
|
||||||
|
lng: '',
|
||||||
|
address: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
inputClick() {
|
||||||
|
if (!this.disabled) {
|
||||||
|
this.pointDialogVisible = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
inputClear() {
|
||||||
|
this.dataValue = this.getDefaultValue()
|
||||||
|
this.valueChange()
|
||||||
|
},
|
||||||
|
|
||||||
|
pointSelect(data) {
|
||||||
|
if (data) {
|
||||||
|
this.dataValue = {
|
||||||
|
lat: data.point.lat,
|
||||||
|
lng: data.point.lng,
|
||||||
|
address: data.address + data.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.valueChange()
|
||||||
|
},
|
||||||
|
|
||||||
|
valueChange() {
|
||||||
|
this.$emit('input', this.dataValue)
|
||||||
|
this.$emit('change', this.dataValue)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', this.dataValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,210 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:visible="visible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
append-to-body
|
||||||
|
title="选择位置"
|
||||||
|
width="500px"
|
||||||
|
@close="close">
|
||||||
|
<flexbox align="stretch">
|
||||||
|
<flexbox-item>
|
||||||
|
<div class="area-title">定位</div>
|
||||||
|
<el-autocomplete
|
||||||
|
v-model="searchInput"
|
||||||
|
:fetch-suggestions="querySearchAsync"
|
||||||
|
style="width: 100%;"
|
||||||
|
placeholder="请输入详细位置名称"
|
||||||
|
@blur="inputBlur"
|
||||||
|
@focus="inputFocus"
|
||||||
|
@select="handleSelect">
|
||||||
|
<template slot-scope="{ item }">
|
||||||
|
<div class="name">{{ item.address + item.title }}</div>
|
||||||
|
</template>
|
||||||
|
</el-autocomplete>
|
||||||
|
<div
|
||||||
|
ref="myMap"
|
||||||
|
class="map"/>
|
||||||
|
</flexbox-item>
|
||||||
|
</flexbox>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="close">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="selectSure">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script type="text/javascript">
|
||||||
|
import VDistpicker from '@/components/VDistpicker'
|
||||||
|
import { getBaiduMap } from '@/utils'
|
||||||
|
import { isEmpty } from '@/utils/types'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WkLocationPointDialog',
|
||||||
|
components: {
|
||||||
|
VDistpicker
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
map: null,
|
||||||
|
searchInput: '', // 搜索
|
||||||
|
searchCopyInput: '', // 避免修改
|
||||||
|
pointAddress: null // 经纬度点
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {
|
||||||
|
visible(val) {
|
||||||
|
if (val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
getBaiduMap()
|
||||||
|
.then(() => {
|
||||||
|
const map = new BMap.Map(this.$refs.myMap, { enableMapClick: true })
|
||||||
|
let point = new BMap.Point(116.404, 39.915)
|
||||||
|
if (this.value) {
|
||||||
|
if (!isEmpty(this.value.lat) && !isEmpty(this.value.lng)) {
|
||||||
|
point = new BMap.Point(this.value.lng, this.value.lat)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEmpty(this.value.address)) {
|
||||||
|
this.searchInput = this.value.address
|
||||||
|
this.searchCopyInput = this.searchInput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.value || (
|
||||||
|
this.value && isEmpty(this.value.lat) && isEmpty(this.value.lng) &&
|
||||||
|
isEmpty(this.value.address)
|
||||||
|
)) {
|
||||||
|
const self = this
|
||||||
|
// 定位逻辑
|
||||||
|
var geolocation = new BMap.Geolocation()
|
||||||
|
geolocation.getCurrentPosition(function(r) {
|
||||||
|
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
|
||||||
|
var myGeo = new BMap.Geocoder({ extensions_town: true })
|
||||||
|
// 根据坐标得到地址描述
|
||||||
|
myGeo.getLocation(r.point, function(result) {
|
||||||
|
if (result) {
|
||||||
|
self.searchInput = result.address
|
||||||
|
self.searchCopyInput = result.address
|
||||||
|
self.addMarkerLabel(result.point)
|
||||||
|
result.title = ''
|
||||||
|
self.pointAddress = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
map.centerAndZoom(point, 14)
|
||||||
|
map.enableScrollWheelZoom()
|
||||||
|
this.map = map
|
||||||
|
this.addMarkerLabel(point)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
querySearchAsync(queryString, cb) {
|
||||||
|
if (queryString) {
|
||||||
|
var options = {
|
||||||
|
onSearchComplete: function(results) {
|
||||||
|
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
|
||||||
|
var address = []
|
||||||
|
for (var i = 0; i < results.getCurrentNumPois(); i++) {
|
||||||
|
address.push(results.getPoi(i))
|
||||||
|
}
|
||||||
|
cb(address)
|
||||||
|
} else {
|
||||||
|
cb([])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pageCapacity: 20
|
||||||
|
}
|
||||||
|
var local = new BMap.LocalSearch(this.map, options)
|
||||||
|
local.search(queryString)
|
||||||
|
} else {
|
||||||
|
cb([])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 搜索结果选择
|
||||||
|
**/
|
||||||
|
handleSelect(item) {
|
||||||
|
this.searchInput = item.address + item.title
|
||||||
|
this.searchCopyInput = this.searchInput // 只能通过这种方式修改
|
||||||
|
|
||||||
|
this.addMarkerLabel(item.point)
|
||||||
|
this.pointAddress = item
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Input 失去焦点 searchInput 只能通过选择更改
|
||||||
|
**/
|
||||||
|
inputBlur() {
|
||||||
|
if (this.searchCopyInput !== this.searchInput) {
|
||||||
|
this.searchInput = this.searchCopyInput
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputFocus() {
|
||||||
|
this.searchCopyInput = this.searchInput
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 创建标注
|
||||||
|
*/
|
||||||
|
addMarkerLabel(point) {
|
||||||
|
this.map.clearOverlays()
|
||||||
|
this.map.centerAndZoom(point, 14)
|
||||||
|
this.map.addOverlay(new BMap.Marker(point))
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 确定选择
|
||||||
|
*/
|
||||||
|
selectSure() {
|
||||||
|
this.$emit('select', this.pointAddress)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
|
.map {
|
||||||
|
height: 150px;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-title {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.distpicker-address-wrapper /deep/ select {
|
||||||
|
height: 34px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 0.1rem;
|
||||||
|
}
|
||||||
|
/deep/ .el-dialog__body {
|
||||||
|
padding: 10px 20px 20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,281 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="[
|
||||||
|
'el-input-number',
|
||||||
|
inputNumberSize ? 'el-input-number--' + inputNumberSize : '',
|
||||||
|
{ 'is-disabled': inputNumberDisabled },
|
||||||
|
{ 'is-without-controls': !controls },
|
||||||
|
{ 'is-controls-right': controlsAtRight }
|
||||||
|
]"
|
||||||
|
@dragstart.prevent>
|
||||||
|
<span
|
||||||
|
v-repeat-click="decrease"
|
||||||
|
v-if="controls"
|
||||||
|
:class="{'is-disabled': minDisabled}"
|
||||||
|
class="el-input-number__decrease"
|
||||||
|
role="button"
|
||||||
|
@keydown.enter="decrease">
|
||||||
|
<i :class="`el-icon-${controlsAtRight ? 'arrow-down' : 'minus'}`"/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-repeat-click="increase"
|
||||||
|
v-if="controls"
|
||||||
|
:class="{'is-disabled': maxDisabled}"
|
||||||
|
class="el-input-number__increase"
|
||||||
|
role="button"
|
||||||
|
@keydown.enter="increase">
|
||||||
|
<i :class="`el-icon-${controlsAtRight ? 'arrow-up' : 'plus'}`"/>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
ref="input"
|
||||||
|
:value="displayValue"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:disabled="inputNumberDisabled"
|
||||||
|
:size="inputNumberSize"
|
||||||
|
:max="max"
|
||||||
|
:min="min"
|
||||||
|
:name="name"
|
||||||
|
:label="label"
|
||||||
|
@keydown.up.native.prevent="increase"
|
||||||
|
@keydown.down.native.prevent="decrease"
|
||||||
|
@blur="handleBlur"
|
||||||
|
@focus="handleFocus"
|
||||||
|
@input="handleInput"
|
||||||
|
@change="handleInputChange">
|
||||||
|
<template slot="suffix">%</template>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Focus from 'element-ui/src/mixins/focus'
|
||||||
|
import RepeatClick from 'element-ui/src/directives/repeat-click'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'WkPercentInput',
|
||||||
|
directives: {
|
||||||
|
RepeatClick
|
||||||
|
},
|
||||||
|
mixins: [Focus('input')],
|
||||||
|
inject: {
|
||||||
|
elForm: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
elFormItem: {
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
step: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
stepStrictly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
default: Infinity
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
default: -Infinity
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
|
value: {},
|
||||||
|
disabled: Boolean,
|
||||||
|
size: String,
|
||||||
|
controls: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
controlsPosition: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
name: String,
|
||||||
|
label: String,
|
||||||
|
placeholder: String,
|
||||||
|
precision: {
|
||||||
|
type: Number,
|
||||||
|
validator(val) {
|
||||||
|
return val >= 0 && val === parseInt(val, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentValue: 0,
|
||||||
|
userInput: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
minDisabled() {
|
||||||
|
return this._decrease(this.value, this.step) < this.min
|
||||||
|
},
|
||||||
|
maxDisabled() {
|
||||||
|
return this._increase(this.value, this.step) > this.max
|
||||||
|
},
|
||||||
|
numPrecision() {
|
||||||
|
const { value, step, getPrecision, precision } = this
|
||||||
|
const stepPrecision = getPrecision(step)
|
||||||
|
if (precision !== undefined) {
|
||||||
|
if (stepPrecision > precision) {
|
||||||
|
console.warn('[Element Warn][InputNumber]precision should not be less than the decimal places of step')
|
||||||
|
}
|
||||||
|
return precision
|
||||||
|
} else {
|
||||||
|
return Math.max(getPrecision(value), stepPrecision)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controlsAtRight() {
|
||||||
|
return this.controls && this.controlsPosition === 'right'
|
||||||
|
},
|
||||||
|
_elFormItemSize() {
|
||||||
|
return (this.elFormItem || {}).elFormItemSize
|
||||||
|
},
|
||||||
|
inputNumberSize() {
|
||||||
|
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size
|
||||||
|
},
|
||||||
|
inputNumberDisabled() {
|
||||||
|
return this.disabled || !!(this.elForm || {}).disabled
|
||||||
|
},
|
||||||
|
displayValue() {
|
||||||
|
if (this.userInput !== null) {
|
||||||
|
return this.userInput
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentValue = this.currentValue
|
||||||
|
|
||||||
|
if (typeof currentValue === 'number') {
|
||||||
|
if (this.stepStrictly) {
|
||||||
|
const stepPrecision = this.getPrecision(this.step)
|
||||||
|
const precisionFactor = Math.pow(10, stepPrecision)
|
||||||
|
currentValue = Math.round(currentValue / this.step) * precisionFactor * this.step / precisionFactor
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.precision !== undefined) {
|
||||||
|
currentValue = currentValue.toFixed(this.precision)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentValue
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
immediate: true,
|
||||||
|
handler(value) {
|
||||||
|
let newVal = value === undefined ? value : Number(value)
|
||||||
|
if (newVal !== undefined) {
|
||||||
|
if (isNaN(newVal)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.stepStrictly) {
|
||||||
|
const stepPrecision = this.getPrecision(this.step)
|
||||||
|
const precisionFactor = Math.pow(10, stepPrecision)
|
||||||
|
newVal = Math.round(newVal / this.step) * precisionFactor * this.step / precisionFactor
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.precision !== undefined) {
|
||||||
|
newVal = this.toPrecision(newVal, this.precision)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newVal >= this.max) newVal = this.max
|
||||||
|
if (newVal <= this.min) newVal = this.min
|
||||||
|
this.currentValue = newVal
|
||||||
|
this.userInput = null
|
||||||
|
this.$emit('input', newVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const innerInput = this.$refs.input.$refs.input
|
||||||
|
innerInput.setAttribute('role', 'spinbutton')
|
||||||
|
innerInput.setAttribute('aria-valuemax', this.max)
|
||||||
|
innerInput.setAttribute('aria-valuemin', this.min)
|
||||||
|
innerInput.setAttribute('aria-valuenow', this.currentValue)
|
||||||
|
innerInput.setAttribute('aria-disabled', this.inputNumberDisabled)
|
||||||
|
},
|
||||||
|
updated() {
|
||||||
|
if (!this.$refs || !this.$refs.input) return
|
||||||
|
const innerInput = this.$refs.input.$refs.input
|
||||||
|
innerInput.setAttribute('aria-valuenow', this.currentValue)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toPrecision(num, precision) {
|
||||||
|
if (precision === undefined) precision = this.numPrecision
|
||||||
|
return parseFloat(Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision))
|
||||||
|
},
|
||||||
|
getPrecision(value) {
|
||||||
|
if (value === undefined) return 0
|
||||||
|
const valueString = value.toString()
|
||||||
|
const dotPosition = valueString.indexOf('.')
|
||||||
|
let precision = 0
|
||||||
|
if (dotPosition !== -1) {
|
||||||
|
precision = valueString.length - dotPosition - 1
|
||||||
|
}
|
||||||
|
return precision
|
||||||
|
},
|
||||||
|
_increase(val, step) {
|
||||||
|
if (typeof val !== 'number' && val !== undefined) return this.currentValue
|
||||||
|
|
||||||
|
const precisionFactor = Math.pow(10, this.numPrecision)
|
||||||
|
// Solve the accuracy problem of JS decimal calculation by converting the value to integer.
|
||||||
|
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor)
|
||||||
|
},
|
||||||
|
_decrease(val, step) {
|
||||||
|
if (typeof val !== 'number' && val !== undefined) return this.currentValue
|
||||||
|
|
||||||
|
const precisionFactor = Math.pow(10, this.numPrecision)
|
||||||
|
|
||||||
|
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor)
|
||||||
|
},
|
||||||
|
increase() {
|
||||||
|
if (this.inputNumberDisabled || this.maxDisabled) return
|
||||||
|
const value = this.value || 0
|
||||||
|
const newVal = this._increase(value, this.step)
|
||||||
|
this.setCurrentValue(newVal)
|
||||||
|
},
|
||||||
|
decrease() {
|
||||||
|
if (this.inputNumberDisabled || this.minDisabled) return
|
||||||
|
const value = this.value || 0
|
||||||
|
const newVal = this._decrease(value, this.step)
|
||||||
|
this.setCurrentValue(newVal)
|
||||||
|
},
|
||||||
|
handleBlur(event) {
|
||||||
|
this.$emit('blur', event)
|
||||||
|
},
|
||||||
|
handleFocus(event) {
|
||||||
|
this.$emit('focus', event)
|
||||||
|
},
|
||||||
|
setCurrentValue(newVal) {
|
||||||
|
const oldVal = this.currentValue
|
||||||
|
if (typeof newVal === 'number' && this.precision !== undefined) {
|
||||||
|
newVal = this.toPrecision(newVal, this.precision)
|
||||||
|
}
|
||||||
|
if (newVal >= this.max) newVal = this.max
|
||||||
|
if (newVal <= this.min) newVal = this.min
|
||||||
|
if (oldVal === newVal) return
|
||||||
|
this.userInput = null
|
||||||
|
this.$emit('input', newVal)
|
||||||
|
this.$emit('change', newVal, oldVal)
|
||||||
|
this.currentValue = newVal
|
||||||
|
},
|
||||||
|
handleInput(value) {
|
||||||
|
this.userInput = value
|
||||||
|
},
|
||||||
|
handleInputChange(value) {
|
||||||
|
const newVal = value === '' ? undefined : Number(value)
|
||||||
|
if (!isNaN(newVal) || value === '') {
|
||||||
|
this.setCurrentValue(newVal)
|
||||||
|
}
|
||||||
|
this.userInput = null
|
||||||
|
},
|
||||||
|
select() {
|
||||||
|
this.$refs.input.select()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-position">
|
||||||
|
<wk-distpicker
|
||||||
|
:hide-area="hideArea"
|
||||||
|
:only-province="onlyProvince"
|
||||||
|
:disabled="disabled"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-model="distpickerValue"
|
||||||
|
clearable
|
||||||
|
@change="valueChange"/>
|
||||||
|
<el-input
|
||||||
|
v-if="showDetail"
|
||||||
|
:rows="2"
|
||||||
|
:disabled="disabled"
|
||||||
|
v-model="detailAddress"
|
||||||
|
:maxlength="100"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="详细地址"
|
||||||
|
@change="valueChange"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkDistpicker from '../WkDistpicker'
|
||||||
|
|
||||||
|
import { isArray, isEmpty } from '@/utils/types'
|
||||||
|
import Emitter from 'element-ui/lib/mixins/emitter'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 地址
|
||||||
|
name: 'WkPosition',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
WkDistpicker
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
|
inheritAttrs: false,
|
||||||
|
|
||||||
|
props: {
|
||||||
|
hideArea: { type: Boolean, default: false },
|
||||||
|
onlyProvince: { type: Boolean, default: false },
|
||||||
|
showDetail: { type: Boolean, default: true },
|
||||||
|
// eslint-disable-next-line vue/require-prop-types
|
||||||
|
value: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
distpickerValue: [],
|
||||||
|
detailAddress: '',
|
||||||
|
dataValue: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(val) {
|
||||||
|
if (!this.valueEquals(val, this.dataValue)) {
|
||||||
|
this.getDefaultValue()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getDefaultValue() {
|
||||||
|
const value = isArray(this.value) ? this.value : []
|
||||||
|
|
||||||
|
const distpickerValue = []
|
||||||
|
let hasAddress = false
|
||||||
|
value.forEach(item => {
|
||||||
|
if (item.id === 4) {
|
||||||
|
hasAddress = true
|
||||||
|
this.detailAddress = item.name
|
||||||
|
} else {
|
||||||
|
distpickerValue.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!hasAddress) {
|
||||||
|
this.detailAddress = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this.distpickerValue = distpickerValue
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值更新
|
||||||
|
*/
|
||||||
|
valueChange() {
|
||||||
|
const dataValue = this.showDetail && isEmpty(this.detailAddress) ? this.distpickerValue : this.distpickerValue.concat([{
|
||||||
|
code: '',
|
||||||
|
name: this.detailAddress,
|
||||||
|
id: 4
|
||||||
|
}])
|
||||||
|
this.dataValue = dataValue
|
||||||
|
|
||||||
|
this.$emit('input', this.dataValue)
|
||||||
|
this.$emit('change', this.dataValue)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', this.dataValue)
|
||||||
|
},
|
||||||
|
|
||||||
|
valueEquals(a, b) {
|
||||||
|
if (a === b) return true
|
||||||
|
if (!(a instanceof Array)) return false
|
||||||
|
if (!(b instanceof Array)) return false
|
||||||
|
if (a.length !== b.length) return false
|
||||||
|
for (let i = 0; i !== a.length; ++i) {
|
||||||
|
const aValue = a[i]
|
||||||
|
const bValue = b[i]
|
||||||
|
if (aValue.id !== bValue.id || aValue.name !== bValue.name) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-position {
|
||||||
|
.el-textarea {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,205 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-select">
|
||||||
|
<template v-if="valueIsObject">
|
||||||
|
<el-select
|
||||||
|
v-if="showType === 'default'"
|
||||||
|
v-model="dataValue.select"
|
||||||
|
:disabled="disabled"
|
||||||
|
:clearable="clearable"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="valueChange">
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in options"
|
||||||
|
:key="index"
|
||||||
|
:label="!isEmptyValue(item.value) ? item.label || item.name : item "
|
||||||
|
:value="getValue(item)"/>
|
||||||
|
</el-select>
|
||||||
|
<el-radio-group
|
||||||
|
v-else-if="showType === 'tiled'"
|
||||||
|
v-model="dataValue.select"
|
||||||
|
@change="valueChange">
|
||||||
|
<el-radio
|
||||||
|
v-for="(item, index) in options"
|
||||||
|
:key="index"
|
||||||
|
:label="getValue(item)">
|
||||||
|
{{ !isEmptyValue(item.value) ? item.label || item.name : item }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<el-input
|
||||||
|
v-if="dataValue.select === '其他' && otherShowInput"
|
||||||
|
v-model="dataValue.otherValue"
|
||||||
|
:disabled="disabled"
|
||||||
|
:maxlength="100"
|
||||||
|
placeholder="其他选项需填写,否则为无效选项"
|
||||||
|
@blur="inputBlur"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { isObject, isEmpty } from '@/utils/types'
|
||||||
|
import Emitter from 'element-ui/lib/mixins/emitter'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 自定义字段库 单选
|
||||||
|
name: 'WkSelect',
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: [String, Number],
|
||||||
|
// 选择其他展示input输入框
|
||||||
|
otherShowInput: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
disabled: Boolean,
|
||||||
|
clearable: Boolean,
|
||||||
|
placeholder: String,
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showType: {
|
||||||
|
type: String,
|
||||||
|
default: 'default' // 下拉 default 平铺 tiled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataValue: {
|
||||||
|
select: '',
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
valueIsObject() {
|
||||||
|
return isObject(this.dataValue)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(newVal, oldVal) {
|
||||||
|
this.validValue()
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// this.validValue()
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 验证值
|
||||||
|
*/
|
||||||
|
validValue() {
|
||||||
|
if (this.value !== this.dataValue.select && this.value !== this.dataValue.otherValue) {
|
||||||
|
if (isEmpty(this.value)) {
|
||||||
|
this.dataValue = {
|
||||||
|
select: '',
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.otherShowInput) {
|
||||||
|
const valueObj = this.options.find(item => this.getValue(item) === this.value)
|
||||||
|
if (valueObj) {
|
||||||
|
if (this.dataValue.select !== this.value) {
|
||||||
|
this.dataValue = {
|
||||||
|
select: this.value,
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.dataValue.otherValue !== this.value) {
|
||||||
|
this.dataValue = {
|
||||||
|
select: '其他',
|
||||||
|
otherValue: this.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.dataValue = {
|
||||||
|
select: this.value,
|
||||||
|
otherValue: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选项值
|
||||||
|
*/
|
||||||
|
getValue(item) {
|
||||||
|
return !this.isEmptyValue(item.value) ? item.value : item
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是空值
|
||||||
|
*/
|
||||||
|
isEmptyValue(value) {
|
||||||
|
return value === null || value == undefined
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值更新
|
||||||
|
*/
|
||||||
|
valueChange() {
|
||||||
|
const value = this.dataValue.select === '其他' ? this.dataValue.otherValue.trim() : this.dataValue.select
|
||||||
|
this.$emit('input', value)
|
||||||
|
this.$emit('change', value)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', value)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失去焦点
|
||||||
|
*/
|
||||||
|
inputBlur() {
|
||||||
|
// 暂未加input触发change逻辑
|
||||||
|
const value = this.dataValue.otherValue
|
||||||
|
const eIsObject = this.options.length > 0 && !this.isEmptyValue(this.options[0].value)
|
||||||
|
const has = this.options.find(item => {
|
||||||
|
if (eIsObject) {
|
||||||
|
return item.value === value.trim()
|
||||||
|
} else {
|
||||||
|
return item === value.trim()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (has) {
|
||||||
|
this.dataValue.otherValue = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('input', this.dataValue.otherValue)
|
||||||
|
this.$emit('change', this.dataValue.otherValue)
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', this.dataValue.otherValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-select {
|
||||||
|
.el-input {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-radio {
|
||||||
|
margin: 5px 30px 5px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<el-popover
|
||||||
|
:disabled="!hasContent"
|
||||||
|
placement="bottom"
|
||||||
|
width="200"
|
||||||
|
trigger="hover">
|
||||||
|
<el-image
|
||||||
|
:src="url"
|
||||||
|
:style="styleObj"
|
||||||
|
style="width: 100%; height: 100%"
|
||||||
|
fit="contain"/>
|
||||||
|
<div slot="reference">
|
||||||
|
<el-image
|
||||||
|
v-if="hasContent"
|
||||||
|
:src="url"
|
||||||
|
:style="{height: height, ...styleObj}"
|
||||||
|
style="width: 100%;"
|
||||||
|
fit="contain"/>
|
||||||
|
<template v-else>--</template>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import { adminFileQueryOneByBatchIdAPI } from '@/api/admin/file'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// WkSignatureImage
|
||||||
|
name: 'WkSignatureImage',
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
src: String // batchId 交互
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
url: '',
|
||||||
|
styleObj: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasContent() {
|
||||||
|
return !!this.url
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
src(newVal, oldVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.getData()
|
||||||
|
} else {
|
||||||
|
this.url = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (this.src) {
|
||||||
|
this.getData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getData() {
|
||||||
|
// adminFileQueryOneByBatchIdAPI(this.src).then(res => {
|
||||||
|
// const resData = res.data
|
||||||
|
// if (resData) {
|
||||||
|
// const url = process.env.BASE_API + resData.url
|
||||||
|
// if (this.url !== url) {
|
||||||
|
// this.url = url
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// this.url = ''
|
||||||
|
// }
|
||||||
|
// }).catch(() => {
|
||||||
|
|
||||||
|
// })
|
||||||
|
this.url = this.src
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,196 @@
|
|||||||
|
<script>
|
||||||
|
import SignaturePad from 'signature_pad'
|
||||||
|
// import mergeImages from 'merge-images'
|
||||||
|
import {
|
||||||
|
DEFAULT_OPTIONS,
|
||||||
|
TRANSPARENT_PNG,
|
||||||
|
IMAGE_TYPES,
|
||||||
|
checkSaveType,
|
||||||
|
convert2NonReactive
|
||||||
|
} from '../utils/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VueSignaturePad',
|
||||||
|
props: {
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
signaturePad: {},
|
||||||
|
cacheImages: [],
|
||||||
|
signatureData: TRANSPARENT_PNG,
|
||||||
|
onResizeHandler: null
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
propsImagesAndCustomImages() {
|
||||||
|
const nonReactiveProrpImages = convert2NonReactive(this.images)
|
||||||
|
const nonReactiveCachImages = convert2NonReactive(this.cacheImages)
|
||||||
|
return [...nonReactiveProrpImages, ...nonReactiveCachImages]
|
||||||
|
},
|
||||||
|
canvas() {
|
||||||
|
return this.$refs.signaturePadCanvas
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
options: function(nextOptions) {
|
||||||
|
Object.keys(nextOptions).forEach(option => {
|
||||||
|
if (this.signaturePad[option]) {
|
||||||
|
this.signaturePad[option] = nextOptions[option]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
height() {
|
||||||
|
this.resizeCanvas()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const { options } = this
|
||||||
|
const canvas = this.$refs.signaturePadCanvas
|
||||||
|
const signaturePad = new SignaturePad(canvas, {
|
||||||
|
...DEFAULT_OPTIONS,
|
||||||
|
...options
|
||||||
|
})
|
||||||
|
this.signaturePad = signaturePad
|
||||||
|
this.onResizeHandler = this.resizeCanvas.bind(this)
|
||||||
|
window.addEventListener('resize', this.onResizeHandler, false)
|
||||||
|
this.resizeCanvas()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.onResizeHandler) {
|
||||||
|
window.removeEventListener('resize', this.onResizeHandler, false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resizeCanvas() {
|
||||||
|
const canvas = this.$refs.signaturePadCanvas
|
||||||
|
const data = this.signaturePad.toData()
|
||||||
|
const ratio = Math.max(window.devicePixelRatio || 1, 1)
|
||||||
|
canvas.width = canvas.offsetWidth * ratio
|
||||||
|
canvas.height = canvas.offsetHeight * ratio
|
||||||
|
canvas.getContext('2d').scale(ratio, ratio)
|
||||||
|
this.signaturePad.clear()
|
||||||
|
this.signatureData = TRANSPARENT_PNG
|
||||||
|
this.signaturePad.fromData(data)
|
||||||
|
},
|
||||||
|
saveSignature(type = IMAGE_TYPES[0], encoderOptions) {
|
||||||
|
const { signaturePad } = this
|
||||||
|
const status = { isEmpty: false, data: undefined }
|
||||||
|
if (!checkSaveType(type)) {
|
||||||
|
const imageTypesString = IMAGE_TYPES.join(', ')
|
||||||
|
throw new Error(
|
||||||
|
`The Image type is incorrect! We are support ${imageTypesString} types.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (signaturePad.isEmpty()) {
|
||||||
|
return {
|
||||||
|
...status,
|
||||||
|
isEmpty: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.signatureData = signaturePad.toDataURL(type, encoderOptions)
|
||||||
|
return {
|
||||||
|
...status,
|
||||||
|
data: this.signatureData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
undoSignature() {
|
||||||
|
const { signaturePad } = this
|
||||||
|
const record = signaturePad.toData()
|
||||||
|
if (record) {
|
||||||
|
return signaturePad.fromData(record.slice(0, -1))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// mergeImageAndSignature(customSignature) {
|
||||||
|
// this.signatureData = customSignature
|
||||||
|
// return mergeImages([
|
||||||
|
// ...this.images,
|
||||||
|
// ...this.cacheImages,
|
||||||
|
// this.signatureData
|
||||||
|
// ])
|
||||||
|
// },
|
||||||
|
// addImages(images = []) {
|
||||||
|
// this.cacheImages = [...this.cacheImages, ...images]
|
||||||
|
// return mergeImages([
|
||||||
|
// ...this.images,
|
||||||
|
// ...this.cacheImages,
|
||||||
|
// this.signatureData
|
||||||
|
// ])
|
||||||
|
// },
|
||||||
|
fromDataURL(data, options = {}, callback) {
|
||||||
|
return this.signaturePad.fromDataURL(data, options, callback)
|
||||||
|
},
|
||||||
|
fromData(data) {
|
||||||
|
return this.signaturePad.fromData(data)
|
||||||
|
},
|
||||||
|
toData() {
|
||||||
|
return this.signaturePad.toData()
|
||||||
|
},
|
||||||
|
lockSignaturePad() {
|
||||||
|
return this.signaturePad.off()
|
||||||
|
},
|
||||||
|
openSignaturePad() {
|
||||||
|
return this.signaturePad.on()
|
||||||
|
},
|
||||||
|
isEmpty() {
|
||||||
|
return this.signaturePad.isEmpty()
|
||||||
|
},
|
||||||
|
getPropImagesAndCacheImages() {
|
||||||
|
return this.propsImagesAndCustomImages
|
||||||
|
},
|
||||||
|
clearCacheImages() {
|
||||||
|
this.cacheImages = []
|
||||||
|
return this.cacheImages
|
||||||
|
},
|
||||||
|
clearSignature() {
|
||||||
|
return this.signaturePad.clear()
|
||||||
|
},
|
||||||
|
toBlob(callback, type, encoderOptions) {
|
||||||
|
this.$refs.signaturePadCanvas.toBlob(callback, type, encoderOptions)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render(createElement) {
|
||||||
|
const { width, height, customStyle } = this
|
||||||
|
const urlObj = require('./signature.png')
|
||||||
|
return createElement(
|
||||||
|
'div',
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
...customStyle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
createElement('canvas', {
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
cursor: `url(${urlObj}),default`
|
||||||
|
},
|
||||||
|
ref: 'signaturePadCanvas'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
After Width: | Height: | Size: 394 B |
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="wkSignaturePad" class="wk-signature-pad">
|
||||||
|
<wk-signature-image
|
||||||
|
v-if="disabled"
|
||||||
|
:src="value.url"
|
||||||
|
:height="height"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<vue-signature-pad
|
||||||
|
ref="signaturePad"
|
||||||
|
:key="height"
|
||||||
|
:options="options"
|
||||||
|
:height="height"
|
||||||
|
width="100%"
|
||||||
|
/>
|
||||||
|
<div class="wk-signature-pad__handle">
|
||||||
|
<el-button type="text" icon="wk wk-icon-reply" @click="handleClick('undo')">撤回</el-button>
|
||||||
|
<el-button type="text" icon="wk wk-icon-bin" @click="handleClick('clear')">清空</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { crmFileSingleSaveAPI } from '@/api/common'
|
||||||
|
|
||||||
|
import VueSignaturePad from './VueSignaturePad'
|
||||||
|
import WkSignatureImage from './Image'
|
||||||
|
|
||||||
|
import { valueEquals } from 'element-ui/lib/utils/util'
|
||||||
|
import { getImageData } from '@/utils'
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 签名
|
||||||
|
name: 'WkSignaturePad',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
VueSignaturePad,
|
||||||
|
WkSignatureImage
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: [Object, String], // batchId 交互
|
||||||
|
data: String, // 同步数据源
|
||||||
|
disabled: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
onEnd: this.onEnd,
|
||||||
|
minWidth: 1,
|
||||||
|
maxWidth: 3
|
||||||
|
},
|
||||||
|
height: '150px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
data(newVal, oldVal) {
|
||||||
|
if (!valueEquals(newVal, oldVal)) {
|
||||||
|
this.$refs.signaturePad.fromDataURL(newVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.value) {
|
||||||
|
this.getData()
|
||||||
|
} else {
|
||||||
|
this.$emit('input', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.height = `${parseInt(this.$refs.wkSignaturePad.clientWidth / 2.6)}px`
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getData() {
|
||||||
|
getImageData(this.value.url)
|
||||||
|
.then(data => {
|
||||||
|
var img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
const canvasWidth = this.$refs.signaturePad.canvas.width
|
||||||
|
const width = img.width
|
||||||
|
const ratio = canvasWidth / width
|
||||||
|
console.log(width, canvasWidth, ratio)
|
||||||
|
this.options.minWidth = this.options.minWidth * ratio
|
||||||
|
this.options.maxWidth = this.options.maxWidth * ratio
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.signaturePad.fromDataURL(data.src)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
img.src = data.src
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onEnd() {
|
||||||
|
const { isEmpty, data } = this.$refs.signaturePad.saveSignature()
|
||||||
|
this.$emit('update:data', data)
|
||||||
|
if (!isEmpty) {
|
||||||
|
this.$refs.signaturePad.toBlob((blob) => {
|
||||||
|
this.uploadFile(blob)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uploadFile(blob) {
|
||||||
|
crmFileSingleSaveAPI({
|
||||||
|
file: blob,
|
||||||
|
batchId: this.value
|
||||||
|
}).then((res) => {
|
||||||
|
this.$emit('input', res.data)
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick(type) {
|
||||||
|
if (type === 'clear') {
|
||||||
|
this.$refs.signaturePad.clearSignature()
|
||||||
|
} else if (type === 'undo') {
|
||||||
|
this.$refs.signaturePad.undoSignature()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.el-form-item.is-error {
|
||||||
|
.wk-signature-pad {
|
||||||
|
border-color: #f56c6c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wk-signature-pad {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__handle {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 0;
|
||||||
|
.el-button--text {
|
||||||
|
color: #999;
|
||||||
|
&:hover {
|
||||||
|
color: $xr-color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
export const IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/svg+xml']
|
||||||
|
|
||||||
|
export const checkSaveType = type => IMAGE_TYPES.includes(type)
|
||||||
|
|
||||||
|
export const DEFAULT_OPTIONS = {
|
||||||
|
dotSize: (0.5 + 2.5) / 2,
|
||||||
|
minWidth: 0.5,
|
||||||
|
maxWidth: 2.5,
|
||||||
|
throttle: 16,
|
||||||
|
minDistance: 5,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0)',
|
||||||
|
penColor: 'black',
|
||||||
|
velocityFilterWeight: 0.7,
|
||||||
|
onBegin: () => {},
|
||||||
|
onEnd: () => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const convert2NonReactive = observerValue =>
|
||||||
|
JSON.parse(JSON.stringify(observerValue))
|
||||||
|
|
||||||
|
export const TRANSPARENT_PNG = {
|
||||||
|
src:
|
||||||
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wk-empty">
|
||||||
|
<div class="wk-empty__title">{{ config.emptyText || '暂无数据' }}</div>
|
||||||
|
<el-button
|
||||||
|
v-if="config.showButton"
|
||||||
|
:icon="config.buttonIcon"
|
||||||
|
class="wk-empty__button xr-btn--orange"
|
||||||
|
type="primary"
|
||||||
|
@click="btnClick">{{ config.buttonTitle || '新建' }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import merge from '@/utils/merge'
|
||||||
|
|
||||||
|
const DefaultEmptyProps = {
|
||||||
|
emptyText: '', // 是否搜索
|
||||||
|
showButton: false,
|
||||||
|
buttonIcon: 'el-icon-plus', // 员工列表请求
|
||||||
|
buttonTitle: '' // 空参数
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 空数据
|
||||||
|
name: 'WkEmpty',
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
props: Object
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
return merge({ ...DefaultEmptyProps }, this.props || {})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
created() {},
|
||||||
|
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
btnClick() {
|
||||||
|
this.$emit('click')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wk-empty {
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<div class="import-history">
|
||||||
|
<div class="import-history__hd">
|
||||||
|
<span class="import-history__title">查看历史导入记录</span>
|
||||||
|
<span class="import-history__des">(错误数据只保存七天,七天后将自动失效)</span>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
class="xr-icon-close-btn"
|
||||||
|
icon="el-icon-close"
|
||||||
|
@click="closeClick" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
:data="tableList"
|
||||||
|
class="import-history__bd"
|
||||||
|
height="250"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column
|
||||||
|
prop="createTime"
|
||||||
|
label="导入时间"
|
||||||
|
width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.createTime | createTime }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="realname"
|
||||||
|
label="操作人"
|
||||||
|
width="80"/>
|
||||||
|
<el-table-column
|
||||||
|
prop="address"
|
||||||
|
label="导入结果">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ `导入总数据${scope.row.title}条,${getImportContent(scope.row.title, scope.row.content)}` }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="option"
|
||||||
|
width="150"
|
||||||
|
label="操作">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<template v-if="getErrorNum(scope.row.content) > 0">
|
||||||
|
<el-button
|
||||||
|
v-if="scope.row.valid == 1"
|
||||||
|
type="text"
|
||||||
|
@click="downloadError(scope.row.messageId)">下载错误数据</el-button>
|
||||||
|
<span v-else-if="scope.row.valid == 0" class="invalid-tips">已失效</span>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="import-history__ft">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="closeClick">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { systemMessageListAPI } from '@/api/common'
|
||||||
|
import {
|
||||||
|
crmDownImportErrorAPI
|
||||||
|
} from '@/api/crm/common'
|
||||||
|
|
||||||
|
import { downloadExcelWithResData } from '@/utils/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// 导入历史
|
||||||
|
name: 'CRMImportHistory',
|
||||||
|
components: {},
|
||||||
|
filters: {
|
||||||
|
createTime(time) {
|
||||||
|
const times = time.split(' ')
|
||||||
|
return times.length > 0 ? times[0] : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// CRM类型
|
||||||
|
crmType: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// moduleType
|
||||||
|
props: Object
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
tableList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {
|
||||||
|
show(value) {
|
||||||
|
if (value) {
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
systemMessageListAPI({
|
||||||
|
page: 1,
|
||||||
|
limit: 9999,
|
||||||
|
type: {
|
||||||
|
customer: 14,
|
||||||
|
contacts: 16,
|
||||||
|
leads: 18,
|
||||||
|
product: 20,
|
||||||
|
hrm: 50
|
||||||
|
}[this.crmType] || this.props.moduleType
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
this.loading = false
|
||||||
|
this.tableList = res.data.list
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载错误数据
|
||||||
|
*/
|
||||||
|
downloadError(messageId) {
|
||||||
|
crmDownImportErrorAPI({ messageId })
|
||||||
|
.then(res => {
|
||||||
|
downloadExcelWithResData(res)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
getImportContent(totalSize, content) {
|
||||||
|
const list = content.split(',') || []
|
||||||
|
const updateSize = Number(list[1] || '0')
|
||||||
|
const errSize = Number(list[0] || '0')
|
||||||
|
return `覆盖${updateSize}条,导入成功${totalSize - errSize}条,导入失败${errSize}条。`
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取错误数据数
|
||||||
|
*/
|
||||||
|
getErrorNum(content) {
|
||||||
|
const list = content.split(',') || []
|
||||||
|
const errSize = Number(list[0] || '0')
|
||||||
|
return parseInt(errSize)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭
|
||||||
|
*/
|
||||||
|
closeClick() {
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.import-history {
|
||||||
|
&__hd {
|
||||||
|
padding: 20px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__des {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__bd {
|
||||||
|
border-top: 1px solid #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__ft {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #F7F8FA;
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xr-icon-close-btn {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid-tips {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,77 @@
|
|||||||
|
import { crmQueryImportNumAPI } from '@/api/crm/common'
|
||||||
|
|
||||||
|
import Lockr from 'lockr'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showCRMImport: false,
|
||||||
|
crmType: '',
|
||||||
|
crmProps: null,
|
||||||
|
crmImportStatus: '',
|
||||||
|
cacheShow: false, // 缓存展示
|
||||||
|
cacheDone: false, // 缓存导入是否完成
|
||||||
|
|
||||||
|
userInfo: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// 处理上次缓存
|
||||||
|
const beforeImportInfo = Lockr.get('crmImportInfo')
|
||||||
|
if (beforeImportInfo && beforeImportInfo.messageId) {
|
||||||
|
this.crmType = beforeImportInfo.crmType
|
||||||
|
this.crmProps = beforeImportInfo.crmProps
|
||||||
|
this.lockrSecondQueryNum(beforeImportInfo.messageId)
|
||||||
|
this.cacheShow = true
|
||||||
|
} else {
|
||||||
|
this.cacheShow = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
// 1.导入框展示 2.导入状态状态为空或者是等待状态 缩小框不展示
|
||||||
|
showFixImport() {
|
||||||
|
return !this.showCRMImport && this.crmImportStatus && this.crmImportStatus != 'wait'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
crmImportChange(status) {
|
||||||
|
this.crmImportStatus = this.showCRMImport && status == 'finish' ? '' : status
|
||||||
|
},
|
||||||
|
|
||||||
|
fixImportClick() {
|
||||||
|
this.showCRMImport = true
|
||||||
|
},
|
||||||
|
|
||||||
|
crmImportClose(status) {
|
||||||
|
if (status == 'finish') {
|
||||||
|
this.crmImportStatus = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第二步查询数量
|
||||||
|
*/
|
||||||
|
lockrSecondQueryNum(messageId) {
|
||||||
|
crmQueryImportNumAPI({ messageId: messageId })
|
||||||
|
.then(res => {
|
||||||
|
if (res.data === null) { // 结束 否则 进行中
|
||||||
|
this.crmImportStatus = 'finish'
|
||||||
|
this.cacheDone = true
|
||||||
|
} else {
|
||||||
|
this.cacheDone = false
|
||||||
|
this.crmImportStatus = 'process'
|
||||||
|
}
|
||||||
|
this.showCRMImport = false
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
Lockr.rm('crmImportInfo')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<flexbox class="xr-import">
|
||||||
|
<div
|
||||||
|
v-loading="loading"
|
||||||
|
v-if="loading"
|
||||||
|
class="xr-import__icon" />
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="wk wk-success xr-import__icon" />
|
||||||
|
<p
|
||||||
|
:class="{ 'is-loading': loading }"
|
||||||
|
class="xr-import__label">{{ processLabel }}</p>
|
||||||
|
</flexbox>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// 导入缩小框子
|
||||||
|
name: 'XrImport',
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
// wait / process / finish / error / success
|
||||||
|
processStatus: {
|
||||||
|
type: String,
|
||||||
|
default: 'wait'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
loading() {
|
||||||
|
return this.processStatus == 'process'
|
||||||
|
},
|
||||||
|
|
||||||
|
processLabel() {
|
||||||
|
return this.loading ? '导入中' : '导入完成'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {},
|
||||||
|
mounted() {},
|
||||||
|
|
||||||
|
beforeDestroy() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xr-import {
|
||||||
|
position: fixed;
|
||||||
|
right: 50px;
|
||||||
|
bottom: 150px;
|
||||||
|
z-index: 999999;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
width: 130px;
|
||||||
|
height: 50px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 25px;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 30px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label.is-loading {
|
||||||
|
margin-left: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-loading-spinner .circular {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-loading-spinner {
|
||||||
|
margin-top: -15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wk-success {
|
||||||
|
color: $xr-color-primary;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,15 @@
|
|||||||
|
import WkImportVue from './index.vue'
|
||||||
|
|
||||||
|
const WkImport = {}
|
||||||
|
|
||||||
|
WkImport.install = (Vue) => {
|
||||||
|
const WkCRMImportConstructor = Vue.extend(WkImportVue)
|
||||||
|
const instance = new WkCRMImportConstructor({
|
||||||
|
el: document.createElement('div')
|
||||||
|
})
|
||||||
|
document.body.appendChild(instance.$el)
|
||||||
|
|
||||||
|
Vue.prototype.$wkImport = instance
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WkImport
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 351 KiB After Width: | Height: | Size: 427 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,30 @@
|
|||||||
|
.org-tree-company {
|
||||||
|
color: #42526E;
|
||||||
|
background-color: #ECEEF2;
|
||||||
|
box-shadow: none !important;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-tree-department {
|
||||||
|
color: #42526E;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: none !important;
|
||||||
|
font-size: 12px;
|
||||||
|
border: 2px solid #42526E;
|
||||||
|
padding: 8px 15px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-tree-node-label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-tree-node:not(:last-child):after,
|
||||||
|
.org-tree-node:not(:first-child):before {
|
||||||
|
border-top: 2px solid #42526E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-tree-node:after,
|
||||||
|
.org-tree-node-children:before {
|
||||||
|
border-left: 2px solid #42526E;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-boolean"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
<el-switch
|
||||||
|
v-model="field.default_value"
|
||||||
|
active-value="1"
|
||||||
|
inactive-value="0" />
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldBoolean',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 0;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-date-interval"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<flexbox class="range-box">
|
||||||
|
<i class="el-icon-date icon" />
|
||||||
|
<flexbox-item :class="{ placeholder: !Boolean(field.default_value) }">
|
||||||
|
{{ field.default_value[0] || '开始时间' }}
|
||||||
|
</flexbox-item>
|
||||||
|
<span>至</span>
|
||||||
|
<flexbox-item :class="{ placeholder: !Boolean(field.default_value) }">
|
||||||
|
{{ field.default_value[1] || '结束时间' }}
|
||||||
|
</flexbox-item>
|
||||||
|
</flexbox>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldDateInterval',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.range-box {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: white;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.placeholder {
|
||||||
|
flex: 1;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
hidden-title
|
||||||
|
class="field-desc-text"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<tinymce
|
||||||
|
:value="field.default_value"
|
||||||
|
:disabled="true"
|
||||||
|
:toolbar="[]"
|
||||||
|
:init="{
|
||||||
|
menubar: false,
|
||||||
|
toolbar_sticky: true,
|
||||||
|
statusbar: false,
|
||||||
|
placeholder: '描述文字内容',
|
||||||
|
quickbars_selection_toolbar: false,
|
||||||
|
contextmenu: '',
|
||||||
|
content_style: ' * {color: #262626; margin: 0;} body { font-size: 14px; }',
|
||||||
|
plugins: 'autoresize',
|
||||||
|
autoresize_bottom_margin: 0
|
||||||
|
}"
|
||||||
|
class="rich-txt" />
|
||||||
|
<div class="field-desc-text-cover"/>
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import Tinymce from '@/components/Tinymce'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldDescText',
|
||||||
|
components: {
|
||||||
|
FieldWrapper,
|
||||||
|
Tinymce
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.field-desc-text {
|
||||||
|
.tox-tinymce {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox .tox-edit-area__iframe {
|
||||||
|
background-color: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.field-desc-text {
|
||||||
|
padding: 15px 10px;
|
||||||
|
|
||||||
|
&-cover {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.rich-txt {
|
||||||
|
width: 100%;
|
||||||
|
background-color: white;
|
||||||
|
border: 0 none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-file"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
请选择文件
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldFile',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
width: 100px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: white;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-input"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<flexbox align="center" class="box">
|
||||||
|
<span class="default-val">
|
||||||
|
{{ typeof field.default_value == 'string' ? field.default_value : '' }}
|
||||||
|
</span>
|
||||||
|
</flexbox>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldInput',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
background: white;
|
||||||
|
padding: 0 10px;
|
||||||
|
|
||||||
|
.default-val {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-current-position"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<flexbox align="center" class="box">
|
||||||
|
<flexbox-item class="default-val" />
|
||||||
|
<span class="wk wk-icon-location" />
|
||||||
|
</flexbox>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldCurrentPosition',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
background: white;
|
||||||
|
padding: 0 10px;
|
||||||
|
.wk-icon-location {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-percent"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<span class="default-val">{{ field.default_value || '' }}</span>
|
||||||
|
<span class="rate">%</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldPercent',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
background: white;
|
||||||
|
padding: 0 30px 0 10px;
|
||||||
|
|
||||||
|
.rate {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 10px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-map-position"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<flexbox class="box-select">
|
||||||
|
<div :class="{placeholder: !Boolean(areaText)}">
|
||||||
|
{{ areaText || '请选择' }}
|
||||||
|
</div>
|
||||||
|
<i class="el-icon-arrow-down el-icon--right"/>
|
||||||
|
</flexbox>
|
||||||
|
<div
|
||||||
|
v-if="field.precisions === 1"
|
||||||
|
class="box-textarea">
|
||||||
|
<div :class="{placeholder: !Boolean(detailAddress)}">
|
||||||
|
{{ detailAddress || '详细地址' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
import { isEmpty } from '@/utils/types'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldPosition',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
computed: {
|
||||||
|
areaText() {
|
||||||
|
if (isEmpty(this.field.default_value)) return ''
|
||||||
|
return this.field.default_value
|
||||||
|
.filter(o => o.id !== 4)
|
||||||
|
.map(o => o.name)
|
||||||
|
.join('/')
|
||||||
|
},
|
||||||
|
detailAddress() {
|
||||||
|
if (isEmpty(this.field.default_value)) return ''
|
||||||
|
const findRes = this.field.default_value.find(o => o.id === 4)
|
||||||
|
if (!findRes) return ''
|
||||||
|
return findRes.name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.placeholder {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.box-select {
|
||||||
|
width: 100%;
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
padding: 10px;
|
||||||
|
div {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.box-textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-textarea"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="default-val">
|
||||||
|
{{ typeof field.default_value == 'string' ? field.default_value : '' }}
|
||||||
|
</div>
|
||||||
|
<div class="max-tips">
|
||||||
|
{{ field.default_value.length+'/'+(field.max_length || 800) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldTextarea',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 80px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: $xr-border-radius-base;
|
||||||
|
padding: 10px 10px 15px 10px;
|
||||||
|
|
||||||
|
.default-val {
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
word-break: break-all;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.max-tips {
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
word-break: break-all;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<field-wrapper
|
||||||
|
:activate="activate"
|
||||||
|
:field="field"
|
||||||
|
:control-flag="controlFlag"
|
||||||
|
class="field-writing-sign"
|
||||||
|
@click="emitClick"
|
||||||
|
@action="handleAction">
|
||||||
|
|
||||||
|
<div class="box" />
|
||||||
|
|
||||||
|
</field-wrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FieldWrapper from './FieldWrapper'
|
||||||
|
import mixins from './mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldWritingSign',
|
||||||
|
components: {
|
||||||
|
FieldWrapper
|
||||||
|
},
|
||||||
|
mixins: [mixins],
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
border: 1px solid #e1e1e1;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: white;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,13 @@
|
|||||||
|
export { default as FieldInput } from './FieldInput'
|
||||||
|
export { default as FieldTextarea } from './FieldTextarea'
|
||||||
|
export { default as FieldSelect } from './FieldSelect'
|
||||||
|
export { default as FieldCheckbox } from './FieldCheckbox'
|
||||||
|
export { default as FieldFile } from './FieldFile'
|
||||||
|
export { default as FieldBoolean } from './FieldBoolean'
|
||||||
|
export { default as FieldPercent } from './FieldPercent'
|
||||||
|
export { default as FieldPosition } from './FieldPosition'
|
||||||
|
export { default as FieldLocation } from './FieldLocation'
|
||||||
|
export { default as FieldDetailTable } from './FieldDetailTable'
|
||||||
|
export { default as FieldWritingSign } from './FieldWritingSign'
|
||||||
|
export { default as FieldDateInterval } from './FieldDateInterval'
|
||||||
|
export { default as FieldDescText } from './FieldDescText'
|
@ -0,0 +1,132 @@
|
|||||||
|
import { getFieldAuth } from '../../utils'
|
||||||
|
import { isEmpty } from '@/utils/types'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
field: { // 当前字段信息
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
fieldArr: { // 全部字段数组,为空时则禁止点击改变位置
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
point: { // 当前字段坐标
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
activePoint: { // 选中的字段坐标
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
specialFormType: [
|
||||||
|
// 'detail_table' // 明细表格
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 当前字段是否激活
|
||||||
|
activate() {
|
||||||
|
return this.point[0] === this.activePoint[0] &&
|
||||||
|
this.point[1] === this.activePoint[1]
|
||||||
|
},
|
||||||
|
/** 只读 */
|
||||||
|
disabled() {
|
||||||
|
return !this.fieldAuth.defaultEdit
|
||||||
|
},
|
||||||
|
|
||||||
|
fieldAuth() {
|
||||||
|
return getFieldAuth(this.field.operating)
|
||||||
|
},
|
||||||
|
// 向上操作按钮
|
||||||
|
topFlag() {
|
||||||
|
if (isEmpty(this.fieldArr)) return false
|
||||||
|
// 第一行、上一行有4个、上一行为特殊字段类型不显示
|
||||||
|
const row = this.point[0]
|
||||||
|
if (row === 0) return false
|
||||||
|
const prevRow = this.fieldArr[row - 1]
|
||||||
|
if (prevRow.length === 4) return false
|
||||||
|
if (this.specialFormType.includes(prevRow[0].form_type)) return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 向下操作按钮
|
||||||
|
bottomFlag() {
|
||||||
|
if (isEmpty(this.fieldArr)) return false
|
||||||
|
// 最后一行、当前行只有一个不显示
|
||||||
|
const row = this.point[0]
|
||||||
|
if (row === this.fieldArr.length - 1) return false
|
||||||
|
// if (this.fieldArr[row].length <= 1) return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 左侧操作按钮
|
||||||
|
leftFlag() {
|
||||||
|
if (isEmpty(this.fieldArr)) return false
|
||||||
|
// 第一列不显示
|
||||||
|
const column = this.point[1]
|
||||||
|
if (column === 0) return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 右侧操作按钮
|
||||||
|
rightFlag() {
|
||||||
|
if (isEmpty(this.fieldArr)) return false
|
||||||
|
// 最后一列不显示
|
||||||
|
const column = this.point[1]
|
||||||
|
const row = this.point[0]
|
||||||
|
if (column === this.fieldArr[row].length - 1) return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 复制按钮
|
||||||
|
copyFlag() {
|
||||||
|
if (isEmpty(this.fieldArr)) return false
|
||||||
|
return ![
|
||||||
|
'customer',
|
||||||
|
'business',
|
||||||
|
'contacts',
|
||||||
|
'contract',
|
||||||
|
'receivables_plan',
|
||||||
|
'single_user'
|
||||||
|
].includes(this.field.form_type)
|
||||||
|
},
|
||||||
|
controlFlag() {
|
||||||
|
return {
|
||||||
|
top: this.topFlag,
|
||||||
|
bottom: this.bottomFlag,
|
||||||
|
left: this.leftFlag,
|
||||||
|
right: this.rightFlag,
|
||||||
|
delete: this.fieldAuth.deleteEdit,
|
||||||
|
copy: this.copyFlag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// watch: {
|
||||||
|
// field: {
|
||||||
|
// handler() {
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.$forceUpdate()
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// deep: true,
|
||||||
|
// immediate: true
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* click
|
||||||
|
* @param evt
|
||||||
|
*/
|
||||||
|
emitClick(evt) {
|
||||||
|
this.$emit('click', evt)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击删除
|
||||||
|
* @param action
|
||||||
|
* @param evt
|
||||||
|
*/
|
||||||
|
handleAction(action, evt) {
|
||||||
|
this.$emit('action', action, this.point, evt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,372 @@
|
|||||||
|
<template>
|
||||||
|
<div class="setting-default">
|
||||||
|
<el-input
|
||||||
|
v-if="type === 'text'"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:maxlength="field.max_length || 100"
|
||||||
|
:disabled="disabled"
|
||||||
|
@blur="inputBlur" />
|
||||||
|
|
||||||
|
<el-input
|
||||||
|
v-else-if="type === 'textarea'"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:maxlength="field.max_length || 800"
|
||||||
|
:disabled="disabled"
|
||||||
|
@blur="inputBlur" />
|
||||||
|
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="type === 'datePicker'"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:disabled="disabled"
|
||||||
|
:type="field.form_type === 'date' ? 'date' : 'datetime'"
|
||||||
|
:value-format="field.form_type === 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
|
||||||
|
placeholder="请选择" />
|
||||||
|
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="type === 'date_interval'"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:type="field.precisions === 1 ? 'daterange' : 'datetimerange'"
|
||||||
|
:value-format="field.precisions === 1 ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
|
||||||
|
:disabled="disabled"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期" />
|
||||||
|
|
||||||
|
<el-select
|
||||||
|
v-else-if="type === 'select'"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:clearable="canClearable"
|
||||||
|
:multiple="field.form_type === 'checkbox'"
|
||||||
|
:disabled="disabled"
|
||||||
|
placeholder="请选择">
|
||||||
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<template v-else-if="type === 'number'">
|
||||||
|
<el-input
|
||||||
|
v-model="field.default_value"
|
||||||
|
:disabled="disabled"
|
||||||
|
@blur="inputBlur">
|
||||||
|
<div
|
||||||
|
v-if="field.form_type === 'percent'"
|
||||||
|
slot="suffix"
|
||||||
|
class="el-input__icon">%</div>
|
||||||
|
</el-input>
|
||||||
|
<div class="input-tips">
|
||||||
|
<span>*</span>
|
||||||
|
数字的位数必须少于{{ field.form_type === 'percent' ? 10 : 15 }}位
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="type === 'position'">
|
||||||
|
<wk-distpicker
|
||||||
|
v-model="selectedMapValue"
|
||||||
|
:hide-area="field.precisions >= 3"
|
||||||
|
:only-province="field.precisions === 4"
|
||||||
|
:disabled="disabled"
|
||||||
|
clearable
|
||||||
|
@change="handleCascaderChange" />
|
||||||
|
<el-input
|
||||||
|
v-if="field.precisions === 1"
|
||||||
|
v-model="detailAddress"
|
||||||
|
:rows="3"
|
||||||
|
:maxlength="100"
|
||||||
|
:disabled="disabled"
|
||||||
|
type="textarea"
|
||||||
|
style="margin-top: 5px"
|
||||||
|
@change="inputPositionChange" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WkDistpicker from '@/components/NewCom/WkDistpicker'
|
||||||
|
|
||||||
|
import { isEmpty, isArray } from '@/utils/types'
|
||||||
|
import { regexIsCRMMobile, regexIsCRMEmail, objDeepCopy } from '@/utils'
|
||||||
|
import { getFieldAuth } from '../../utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingDefault',
|
||||||
|
components: {
|
||||||
|
WkDistpicker
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedMapValue: [],
|
||||||
|
detailAddress: '',
|
||||||
|
oldPrecisions: null,
|
||||||
|
|
||||||
|
areaData: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 只读
|
||||||
|
disabled() {
|
||||||
|
return !getFieldAuth(this.field.operating).defaultEdit
|
||||||
|
},
|
||||||
|
// 是否允许清除默认选项
|
||||||
|
canClearable() {
|
||||||
|
const form_type = this.field.form_type
|
||||||
|
if ([
|
||||||
|
'boolean_value'
|
||||||
|
].includes(form_type)) return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 类型
|
||||||
|
type() {
|
||||||
|
const form_type = this.field.form_type
|
||||||
|
if ([
|
||||||
|
'date',
|
||||||
|
'datetime'
|
||||||
|
].includes(form_type)) return 'datePicker'
|
||||||
|
if ([
|
||||||
|
'number',
|
||||||
|
'floatnumber',
|
||||||
|
'percent'
|
||||||
|
].includes(form_type)) return 'number'
|
||||||
|
if ([
|
||||||
|
'select',
|
||||||
|
'checkbox',
|
||||||
|
'boolean_value'
|
||||||
|
].includes(form_type)) return 'select'
|
||||||
|
switch (this.field.form_type) {
|
||||||
|
case 'date_interval':
|
||||||
|
return 'date_interval'
|
||||||
|
case 'position':
|
||||||
|
return 'position'
|
||||||
|
case 'textarea':
|
||||||
|
return 'textarea'
|
||||||
|
default:
|
||||||
|
return 'text'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 选项
|
||||||
|
options() {
|
||||||
|
if (this.type !== 'select') return []
|
||||||
|
const form_type = this.field.form_type
|
||||||
|
if ([
|
||||||
|
'select',
|
||||||
|
'checkbox'
|
||||||
|
].includes(form_type)) {
|
||||||
|
return this.field.setting.map(o => {
|
||||||
|
return { label: o, value: o }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
switch (form_type) {
|
||||||
|
case 'boolean_value':
|
||||||
|
return [
|
||||||
|
{ label: '选中', value: '1' },
|
||||||
|
{ label: '不选中', value: '0' }
|
||||||
|
]
|
||||||
|
default:
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
field: {
|
||||||
|
handler() {
|
||||||
|
if (this.field.form_type === 'boolean_value') {
|
||||||
|
// 布尔值
|
||||||
|
this.field.default_value = isEmpty(this.field.default_value) ? '0' : this.field.default_value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.type === 'select' &&
|
||||||
|
isEmpty(this.field.setting) &&
|
||||||
|
!isEmpty(this.field.options)
|
||||||
|
) {
|
||||||
|
this.$set(this.field, 'setting', this.field.options.split(','))
|
||||||
|
}
|
||||||
|
if (this.type === 'position') {
|
||||||
|
this.resetDefaultValue()
|
||||||
|
// 地址默认值
|
||||||
|
if (isEmpty(this.field.default_value)) {
|
||||||
|
this.selectedMapValue = []
|
||||||
|
if (!isArray(this.field.default_value)) {
|
||||||
|
this.field.default_value = []
|
||||||
|
}
|
||||||
|
this.detailAddress = ''
|
||||||
|
} else {
|
||||||
|
this.selectedMapValue = this.field.default_value.filter(o => o.id !== 4)
|
||||||
|
if (this.field.precisions === 1) {
|
||||||
|
const findRes = this.field.default_value.find(o => o.id === 4)
|
||||||
|
if (findRes) {
|
||||||
|
this.detailAddress = findRes.name
|
||||||
|
} else {
|
||||||
|
this.detailAddress = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
inputBlur() {
|
||||||
|
// this.$emit('input', this.value)
|
||||||
|
if (!this.field.default_value) return
|
||||||
|
if (this.field.form_type === 'mobile') {
|
||||||
|
// 校验手机号
|
||||||
|
if (!regexIsCRMMobile(this.field.default_value)) {
|
||||||
|
this.$message.error('输入的手机格式有误')
|
||||||
|
this.field.default_value = ''
|
||||||
|
}
|
||||||
|
} else if (this.field.form_type === 'email') {
|
||||||
|
// 校验邮箱
|
||||||
|
if (!regexIsCRMEmail(this.field.default_value)) {
|
||||||
|
this.$message.error('输入的邮箱格式有误')
|
||||||
|
this.field.default_value = ''
|
||||||
|
}
|
||||||
|
} else if (this.type === 'number') {
|
||||||
|
// 校验数字类型
|
||||||
|
const num = Number(this.field.default_value) // 去0
|
||||||
|
if (isNaN(num)) {
|
||||||
|
this.field.default_value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.field.default_value = String(num)
|
||||||
|
const arr = String(num).split('.')
|
||||||
|
|
||||||
|
const len = String(num)
|
||||||
|
.replace('.', '')
|
||||||
|
.replace('-', '')
|
||||||
|
.length
|
||||||
|
const maxlength = this.field.form_type === 'percent' ? 10 : 15
|
||||||
|
if (len > maxlength) {
|
||||||
|
this.$message.error(`最多支持${maxlength}位数字(包含小数位)`)
|
||||||
|
this.field.default_value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const min = isEmpty(this.field.minNumRestrict) ? -Infinity : Number(this.field.minNumRestrict || -Infinity)
|
||||||
|
const max = isEmpty(this.field.maxNumRestrict) ? Infinity : Number(this.field.maxNumRestrict || Infinity)
|
||||||
|
if (num < min) {
|
||||||
|
this.$message.error('默认值不能小于最小值')
|
||||||
|
this.field.default_value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (num > max) {
|
||||||
|
this.$message.error('默认值不能大于最大值')
|
||||||
|
this.field.default_value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// null 不支持小数 0 不限制小数位
|
||||||
|
if (isEmpty(this.field.precisions)) {
|
||||||
|
this.field.default_value = arr[0]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.field.precisions === 0) return
|
||||||
|
if (arr.length > 1 && arr[1].length > Number(this.field.precisions)) {
|
||||||
|
this.$message.error(`默认值的小数位不能大于${this.field.precisions}`)
|
||||||
|
this.field.default_value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改精度重置默认值
|
||||||
|
*/
|
||||||
|
resetDefaultValue() {
|
||||||
|
if (
|
||||||
|
!this.oldPrecisions ||
|
||||||
|
(this.oldPrecisions === this.field.precisions)
|
||||||
|
) {
|
||||||
|
this.oldPrecisions = this.field.precisions
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.oldPrecisions = this.field.precisions
|
||||||
|
this.selectedMapValue = []
|
||||||
|
if (!isEmpty(this.field.default_value)) {
|
||||||
|
this.field.default_value = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改详细地址
|
||||||
|
*/
|
||||||
|
inputPositionChange() {
|
||||||
|
if (this.field.precisions !== 1) {
|
||||||
|
const findIndex = this.field.default_value.findIndex(o => o.id === 4)
|
||||||
|
if (findIndex === -1) return
|
||||||
|
this.field.default_value.splice(findIndex, 1)
|
||||||
|
} else {
|
||||||
|
const findRes = this.field.default_value.find(o => o.id === 4)
|
||||||
|
if (findRes) {
|
||||||
|
findRes.name = this.detailAddress
|
||||||
|
} else {
|
||||||
|
this.field.default_value.push({
|
||||||
|
code: '',
|
||||||
|
name: this.detailAddress,
|
||||||
|
id: 4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择省市区
|
||||||
|
*/
|
||||||
|
handleCascaderChange() {
|
||||||
|
this.field.default_value = this.selectedMapValue
|
||||||
|
this.inputPositionChange()
|
||||||
|
},
|
||||||
|
|
||||||
|
getCascaderValArr(data, value) {
|
||||||
|
const res = []
|
||||||
|
if (value.length === 0) return res
|
||||||
|
let index = 0
|
||||||
|
let _data = objDeepCopy(data)
|
||||||
|
do {
|
||||||
|
const findRes = _data.find(o => o.code === value[index])
|
||||||
|
if (findRes) {
|
||||||
|
_data = findRes.children || []
|
||||||
|
res.push({
|
||||||
|
code: findRes.code,
|
||||||
|
name: findRes.name,
|
||||||
|
id: index + 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
} while (index <= value.length)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-date-editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-cascader {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-input__icon {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.input-tips {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #999;
|
||||||
|
span {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<div class="setting-rich-text">
|
||||||
|
<tinymce
|
||||||
|
ref="createTinymce"
|
||||||
|
v-model="field.default_value"
|
||||||
|
:init="getEditConfig()"
|
||||||
|
:height="200"
|
||||||
|
toolbar="bold italic underline strikethrough | fontselect | forecolor backcolor | fontsizeselect | numlist bullist | alignleft aligncenter alignright | image link | removeformat"
|
||||||
|
class="rich-txt"
|
||||||
|
@input="debouncedEditorInput" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Tinymce from '@/components/Tinymce'
|
||||||
|
import { debounce } from 'throttle-debounce'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingRichText',
|
||||||
|
components: {
|
||||||
|
Tinymce
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
debouncedEditorInput: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.debouncedEditorInput = debounce(300, this.editInputChange)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getEditConfig() {
|
||||||
|
return {
|
||||||
|
menubar: false,
|
||||||
|
statusbar: false,
|
||||||
|
paste_data_images: true, // 允许粘贴图片
|
||||||
|
paste_enable_default_filters: false,
|
||||||
|
placeholder: '描述文字内容',
|
||||||
|
content_style: ' * {color: #262626; margin: 0;} body { margin: 8px; font-size: 14px; }',
|
||||||
|
paste_retain_style_properties: 'border', // 粘贴内容时要保留的样式
|
||||||
|
toolbar_mode: 'scrolling',
|
||||||
|
paste_preprocess: function(plugin, args) {
|
||||||
|
// 删除部分标签
|
||||||
|
var delTag = ['b', 'strong', 'i', 'em']
|
||||||
|
delTag.forEach(tag => {
|
||||||
|
var reg = new RegExp(`(<${tag}>)|(</${tag}>)]`, 'g')
|
||||||
|
args.content = args.content.replace(reg, '')
|
||||||
|
})
|
||||||
|
// 替换部分标签
|
||||||
|
var replaceTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
|
||||||
|
replaceTag.forEach(tag => {
|
||||||
|
var reg1 = new RegExp(`<${tag}>`, 'g')
|
||||||
|
var reg2 = new RegExp(`</${tag}>`, 'g')
|
||||||
|
args.content = args.content.replace(reg1, '<p>')
|
||||||
|
args.content = args.content.replace(reg2, '</p>')
|
||||||
|
})
|
||||||
|
// 删除所有font标签
|
||||||
|
args.content = args.content.replace(/<\/font>/ig, '').replace(/<font[^>]+>/ig, '')
|
||||||
|
console.log(args.content)
|
||||||
|
},
|
||||||
|
paste_postprocess: function(plugin, args) {
|
||||||
|
var doms = Array.from(args.node.querySelectorAll('*'))
|
||||||
|
// 删除字体样式
|
||||||
|
doms.forEach(dom => {
|
||||||
|
dom.style.color = ''
|
||||||
|
dom.style.fontWeight = ''
|
||||||
|
dom.style.fontFamily = ''
|
||||||
|
dom.style.fontSize = ''
|
||||||
|
dom.style.background = ''
|
||||||
|
console.log(dom)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editInputChange() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,164 @@
|
|||||||
|
<template>
|
||||||
|
<div class="setting-detail-table">
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">表格字段</div>
|
||||||
|
<draggable
|
||||||
|
:list="field.fieldExtendList"
|
||||||
|
:options="dragConfig"
|
||||||
|
@sort="handleChange">
|
||||||
|
<flexbox
|
||||||
|
v-for="(item, index) in field.fieldExtendList"
|
||||||
|
:key="index"
|
||||||
|
align="center"
|
||||||
|
justify="flex-start"
|
||||||
|
class="option-item">
|
||||||
|
<i
|
||||||
|
:class="typeObj(item.form_type).icon"
|
||||||
|
class="type-icon" />
|
||||||
|
<div class="option-item__name">{{ item.name }}</div>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
class="option-item__icon wk wk-write"
|
||||||
|
@click="handleEdit(index)" />
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
class="option-item__icon wk wk-icon-bin"
|
||||||
|
@click="handleDelete(index)" />
|
||||||
|
<div class="option-item__icon drag-hook wk wk-grid" />
|
||||||
|
</flexbox>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">动作名</div>
|
||||||
|
<div>
|
||||||
|
<el-input v-model="field.remark" :maxlength="10" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">
|
||||||
|
填写方式
|
||||||
|
<el-tooltip
|
||||||
|
content="选择明细的填写方式"
|
||||||
|
effect="dark"
|
||||||
|
popper-class="setting-number-tooltip"
|
||||||
|
placement="top">
|
||||||
|
<i class="wk wk-help wk-help-tips" />
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<el-radio-group v-model="field.precisions">
|
||||||
|
<el-radio :label="1">列表</el-radio>
|
||||||
|
<el-radio :label="2">表格</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
import { guid } from '@/utils'
|
||||||
|
import FieldTypeLib from '../../fieldTypeLib'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingDetailTable',
|
||||||
|
components: {
|
||||||
|
draggable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dragConfig: {
|
||||||
|
group: guid(),
|
||||||
|
forceFallback: false,
|
||||||
|
fallbackClass: 'draggingStyle',
|
||||||
|
handle: '.drag-hook',
|
||||||
|
filter: '.el-input__inner',
|
||||||
|
preventOnFilter: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
field: {
|
||||||
|
handler() {
|
||||||
|
if (!this.field.precisions) {
|
||||||
|
this.$set(this.field, 'precisions', 1)
|
||||||
|
}
|
||||||
|
this.$set(this.field, 'precisions', this.field.precisions)
|
||||||
|
this.$set(this.field, 'remark', this.field.remark)
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
typeObj(form_type) {
|
||||||
|
return FieldTypeLib.find(o => o.form_type === form_type)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleChange() {
|
||||||
|
this.$set(this.field, 'fieldExtendList', this.field.fieldExtendList)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEdit(index) {
|
||||||
|
this.$emit('child-edit', this.field.fieldExtendList[index])
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDelete(index) {
|
||||||
|
this.field.fieldExtendList.splice(index, 1)
|
||||||
|
this.$set(this.field, 'fieldExtendList', this.field.fieldExtendList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.setting-detail-table {
|
||||||
|
.item-section {
|
||||||
|
padding: 10px 0;
|
||||||
|
border-bottom: 1px solid #e6e6e6;
|
||||||
|
.name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 34px;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 8px;
|
||||||
|
margin: 5px 0;
|
||||||
|
|
||||||
|
.drag-hook {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #777777;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-item__name {
|
||||||
|
width: 174px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.option-item__icon {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999999;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,211 @@
|
|||||||
|
<template>
|
||||||
|
<div class="setting-number">
|
||||||
|
<flexbox
|
||||||
|
align="center"
|
||||||
|
justify="flex-start"
|
||||||
|
class="setting-number-item">
|
||||||
|
<el-checkbox v-model="checked" @change="checkedChange" />
|
||||||
|
<span style="font-size: 13px;">支持小数</span>
|
||||||
|
<el-tooltip
|
||||||
|
content="不选择只能输入整数,勾选后可规定小数位数"
|
||||||
|
effect="dark"
|
||||||
|
popper-class="setting-number-tooltip"
|
||||||
|
placement="top">
|
||||||
|
<i class="wk wk-help wk-help-tips" />
|
||||||
|
</el-tooltip>
|
||||||
|
<template v-if="checked">
|
||||||
|
<span>限制 </span>
|
||||||
|
<el-select
|
||||||
|
v-model="field.precisions"
|
||||||
|
size="small"
|
||||||
|
placeholder=""
|
||||||
|
@change="handleSelectChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in precisionList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
<span> 位</span>
|
||||||
|
</template>
|
||||||
|
</flexbox>
|
||||||
|
<flexbox
|
||||||
|
align="flex-start"
|
||||||
|
justify="flex-start"
|
||||||
|
direction="column"
|
||||||
|
class="setting-number-item">
|
||||||
|
<el-checkbox v-model="limitChecked" @change="limitChange">
|
||||||
|
限制数值范围
|
||||||
|
</el-checkbox>
|
||||||
|
<flexbox
|
||||||
|
v-if="limitChecked"
|
||||||
|
align="center"
|
||||||
|
justify="flex-start"
|
||||||
|
class="number-range-body">
|
||||||
|
<flexbox-item>
|
||||||
|
<el-input-number
|
||||||
|
v-model="minNumRestrict"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最小值"
|
||||||
|
@change="handleChangeNumber('minNumRestrict')" />
|
||||||
|
</flexbox-item>
|
||||||
|
<div class="number-range-text">~</div>
|
||||||
|
<flexbox-item>
|
||||||
|
<el-input-number
|
||||||
|
v-model="maxNumRestrict"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最大值"
|
||||||
|
@change="handleChangeNumber('maxNumRestrict')" />
|
||||||
|
</flexbox-item>
|
||||||
|
</flexbox>
|
||||||
|
</flexbox>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { isEmpty } from '@/utils/types'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingNumber',
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
checked: false,
|
||||||
|
precisionList: [],
|
||||||
|
|
||||||
|
limitChecked: false,
|
||||||
|
minNumRestrict: undefined, // 定义为 undefined 防止input number自动填充0
|
||||||
|
maxNumRestrict: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
field: {
|
||||||
|
handler() {
|
||||||
|
if ([
|
||||||
|
'number',
|
||||||
|
'floatnumber',
|
||||||
|
'percent'
|
||||||
|
].includes(this.field.form_type)) {
|
||||||
|
if (!this.field.hasOwnProperty('minNumRestrict')) {
|
||||||
|
this.field.minNumRestrict = null
|
||||||
|
}
|
||||||
|
if (!this.field.hasOwnProperty('maxNumRestrict')) {
|
||||||
|
this.field.maxNumRestrict = null
|
||||||
|
}
|
||||||
|
this.minNumRestrict = isEmpty(this.field.minNumRestrict) ? undefined : Number(this.field.minNumRestrict)
|
||||||
|
this.maxNumRestrict = isEmpty(this.field.maxNumRestrict) ? undefined : Number(this.field.maxNumRestrict)
|
||||||
|
|
||||||
|
// 小数位
|
||||||
|
const max = this.field.form_type === 'percent' ? 5 : 14
|
||||||
|
this.precisionList = Array.from({ length: max })
|
||||||
|
.map((o, i) => {
|
||||||
|
return { label: i + 1, value: i + 1 }
|
||||||
|
})
|
||||||
|
// if (this.field.form_type !== 'percent') {
|
||||||
|
// this.precisionList.unshift({ label: '不限', value: 0 })
|
||||||
|
// }
|
||||||
|
if (!this.field.hasOwnProperty('precisions')) {
|
||||||
|
this.field.precisions = this.field.form_type === 'number' ? 4 : 2
|
||||||
|
}
|
||||||
|
if (this.field.precisions > max) {
|
||||||
|
// 不能大于最大值
|
||||||
|
this.field.precisions = max
|
||||||
|
}
|
||||||
|
this.checked = !isEmpty(this.field.precisions)
|
||||||
|
this.limitChecked = !isEmpty(this.minNumRestrict) || !isEmpty(this.maxNumRestrict)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkedChange() {
|
||||||
|
if (!this.checked) {
|
||||||
|
this.field.precisions = null
|
||||||
|
} else {
|
||||||
|
this.field.precisions = 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSelectChange() {
|
||||||
|
this.$set(this.field, 'precisions', this.field.precisions)
|
||||||
|
this.$forceUpdate()
|
||||||
|
},
|
||||||
|
limitChange() {
|
||||||
|
if (!this.limitChecked) {
|
||||||
|
this.minNumRestrict = undefined
|
||||||
|
this.maxNumRestrict = undefined
|
||||||
|
|
||||||
|
this.field.minNumRestrict = ''
|
||||||
|
this.field.maxNumRestrict = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleChangeNumber(type) {
|
||||||
|
const current = this[type]
|
||||||
|
const len = String(current || '')
|
||||||
|
.replace('.', '')
|
||||||
|
.replace('-', '')
|
||||||
|
.length
|
||||||
|
|
||||||
|
const maxlength = this.field.form_type === 'percent' ? 10 : 15
|
||||||
|
if (len > maxlength) {
|
||||||
|
this.$message.error(`最多支持${maxlength}位数字`)
|
||||||
|
this.field[type] = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const min = this.minNumRestrict
|
||||||
|
const max = this.maxNumRestrict
|
||||||
|
|
||||||
|
if (!isEmpty(min) && !isEmpty(max)) {
|
||||||
|
if (Number(min) > Number(max)) {
|
||||||
|
this.$message.error('请输入正确的数值范围')
|
||||||
|
this.field[type] = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const minNum = isEmpty(min) ? '' : min
|
||||||
|
const maxNum = isEmpty(max) ? '' : max
|
||||||
|
this.field.minNumRestrict = this.minNumRestrict !== null ? String(minNum) : null
|
||||||
|
this.field.maxNumRestrict = this.maxNumRestrict !== null ? String(maxNum) : null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.setting-number-tooltip {
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.setting-number-item {
|
||||||
|
height: 32px;
|
||||||
|
&:nth-child(2) {
|
||||||
|
height: auto;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.el-checkbox {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.el-tooltip {
|
||||||
|
margin: 0 10px 0 5px;
|
||||||
|
}
|
||||||
|
.el-select {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
.el-input-number {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.number-range-body {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.number-range-text {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<div class="setting-precisions">
|
||||||
|
<el-select
|
||||||
|
:disabled="!optionsEditAuth"
|
||||||
|
v-model="field.precisions"
|
||||||
|
placeholder="请选择">
|
||||||
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getFieldAuth } from '../../utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SettingPrecisions',
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 选项不能配置
|
||||||
|
optionsEditAuth() {
|
||||||
|
return getFieldAuth(this.field.operating).optionsEdit
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
field: {
|
||||||
|
handler() {
|
||||||
|
if (![
|
||||||
|
'date_interval',
|
||||||
|
'position',
|
||||||
|
'select',
|
||||||
|
'checkbox'
|
||||||
|
].includes(this.field.form_type)) return
|
||||||
|
if (this.field.form_type === 'date_interval') {
|
||||||
|
this.options = [
|
||||||
|
{ label: '日期', value: 1 },
|
||||||
|
{ label: '日期时间', value: 2 }
|
||||||
|
]
|
||||||
|
} else if (this.field.form_type === 'position') {
|
||||||
|
this.options = [
|
||||||
|
{ label: '省/地区、市、区/县、详细地址', value: 1 },
|
||||||
|
{ label: '省/地区、市、区/县', value: 2 },
|
||||||
|
{ label: '省/地区、市', value: 3 },
|
||||||
|
{ label: '省/地区', value: 4 }
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
this.options = [
|
||||||
|
{ label: '平铺', value: 1 },
|
||||||
|
{ label: '下拉', value: 2 }
|
||||||
|
]
|
||||||
|
if (!this.field.precisions) {
|
||||||
|
this.$set(this.field, 'precisions', this.field.form_type === 'checkbox' ? 1 : 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.field.precisions) {
|
||||||
|
this.$set(this.field, 'precisions', 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,325 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-clickoutside="clickOutSide"
|
||||||
|
v-if="typeObj"
|
||||||
|
class="field-setting">
|
||||||
|
<div class="setting-title">
|
||||||
|
{{ typeObj.name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-body">
|
||||||
|
<template v-if="!isDescText">
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">标识名</div>
|
||||||
|
<el-input
|
||||||
|
v-model="field.name"
|
||||||
|
:disabled="!fieldAuth.nameEdit"/>
|
||||||
|
<div class="input-tips"><span>*</span>标识名不能为空</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">提示文字</div>
|
||||||
|
<el-input
|
||||||
|
v-model="field.input_tips"
|
||||||
|
:rows="3"
|
||||||
|
type="textarea"
|
||||||
|
resize="none"/>
|
||||||
|
<div class="input-tips"><span>*</span>显示在标识名右侧的说明文字</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<setting-detail-table
|
||||||
|
v-if="field.form_type === 'detail_table'"
|
||||||
|
:field="field"
|
||||||
|
@child-edit="emitChildEdit" />
|
||||||
|
|
||||||
|
<template v-if="canOptions">
|
||||||
|
<div class="item-section">
|
||||||
|
<div class="name">选项内容</div>
|
||||||
|
<div class="input-tips"><span>*</span>修改选项后该项设置的逻辑表单会失效</div>
|
||||||
|
<setting-options
|
||||||
|
:field="field"
|
||||||
|
:is-table-child="isTableChild" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!isTableChild" class="item-section">
|
||||||
|
<div class="name">逻辑表单</div>
|
||||||
|
<setting-logic-form
|
||||||
|
:field="field"
|
||||||
|
:point="point"
|
||||||
|
:field-arr="fieldArr" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-if="canPrecisions" class="item-section">
|
||||||
|
<div class="name">
|
||||||
|
{{ precisionsTitle }}
|
||||||
|
</div>
|
||||||
|
<setting-precisions :field="field" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="canDefault" class="item-section">
|
||||||
|
<div class="name">默认值</div>
|
||||||
|
<setting-default :field="field" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="canNumber" class="item-section">
|
||||||
|
<setting-number :field="field" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-if="isDescText" class="item-section">
|
||||||
|
<div class="name">内容</div>
|
||||||
|
<setting-desc-text :field="field" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="fieldAuth.percentEdit" class="item-section">
|
||||||
|
<div class="name">
|
||||||
|
字段占比 %
|
||||||
|
<el-tooltip
|
||||||
|
content="配置表单布局,可以单行多字段排布"
|
||||||
|
effect="dark"
|
||||||
|
placement="top">
|
||||||
|
<i class="wk wk-help wk-help-tips" style="margin-left: 3px;"/>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<el-radio-group
|
||||||
|
v-model="field.style_percent"
|
||||||
|
size="medium"
|
||||||
|
@change="emitUpdateWidth">
|
||||||
|
<el-radio-button
|
||||||
|
v-for="item in widthOptions"
|
||||||
|
:label="item.value"
|
||||||
|
:key="item.value">{{ item.value }}</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="canTransform && transformData && transformData[field.form_type]" class="item-section">
|
||||||
|
<div class="name">转化客户字段</div>
|
||||||
|
<el-select
|
||||||
|
v-model="field.relevant"
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in transformData[field.form_type]"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="!isDescText">
|
||||||
|
<div
|
||||||
|
v-if="fieldAuth.nullEdit"
|
||||||
|
class="item-check-section">
|
||||||
|
<el-checkbox
|
||||||
|
v-model="field.is_null"
|
||||||
|
:true-label="1"
|
||||||
|
:false-label="0">设为必填</el-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="fieldAuth.uniqueEdit"
|
||||||
|
class="item-check-section">
|
||||||
|
<el-checkbox
|
||||||
|
v-model="field.is_unique"
|
||||||
|
:true-label="1"
|
||||||
|
:false-label="0">设为唯一</el-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="fieldAuth.hiddenEdit"
|
||||||
|
class="item-check-section">
|
||||||
|
<el-checkbox
|
||||||
|
v-model="field.is_hidden"
|
||||||
|
:true-label="1"
|
||||||
|
:false-label="0">隐藏字段</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SettingDefault from './SettingDefault'
|
||||||
|
import SettingOptions from './SettingOptions'
|
||||||
|
import SettingNumber from './SettingNumber'
|
||||||
|
import SettingPrecisions from './SettingPrecisions'
|
||||||
|
import SettingDescText from './SettingDescText'
|
||||||
|
import SettingDetailTable from './SettingDetailTable'
|
||||||
|
import SettingLogicForm from './SettingLogicForm'
|
||||||
|
|
||||||
|
import FieldTypeLib from '../../fieldTypeLib'
|
||||||
|
import { getFieldAuth } from '../../utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldSetting',
|
||||||
|
components: {
|
||||||
|
SettingDefault,
|
||||||
|
SettingOptions,
|
||||||
|
SettingNumber,
|
||||||
|
SettingPrecisions,
|
||||||
|
SettingDescText,
|
||||||
|
SettingDetailTable,
|
||||||
|
SettingLogicForm
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
// 是否开启转移 转移对应数据
|
||||||
|
canTransform: Boolean,
|
||||||
|
transformData: Object,
|
||||||
|
field: { // 要编辑的字段信息
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
fieldArr: { // 所有字段
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
point: { // 被选中的字段坐标
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
widthOptions: [
|
||||||
|
{ value: 25 },
|
||||||
|
{ value: 50 },
|
||||||
|
{ value: 75 },
|
||||||
|
{ value: 100 }
|
||||||
|
],
|
||||||
|
stylePercentValue: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
typeObj() {
|
||||||
|
const field = FieldTypeLib.find(o => o.form_type === this.field.form_type)
|
||||||
|
return field || this.field
|
||||||
|
},
|
||||||
|
fieldAuth() {
|
||||||
|
return getFieldAuth(this.field.operating)
|
||||||
|
},
|
||||||
|
// 是否允许设置字段默认值
|
||||||
|
canDefault() {
|
||||||
|
return ![
|
||||||
|
'user',
|
||||||
|
'structure',
|
||||||
|
'file',
|
||||||
|
'location',
|
||||||
|
'handwriting_sign',
|
||||||
|
'detail_table'
|
||||||
|
].includes(this.field.form_type)
|
||||||
|
},
|
||||||
|
// 是否允许设置选项内容
|
||||||
|
canOptions() {
|
||||||
|
return [
|
||||||
|
'select',
|
||||||
|
'checkbox'
|
||||||
|
].includes(this.field.form_type)
|
||||||
|
},
|
||||||
|
// 是否允许设置小数
|
||||||
|
canNumber() {
|
||||||
|
return [
|
||||||
|
'number',
|
||||||
|
'floatnumber',
|
||||||
|
'percent'
|
||||||
|
].includes(this.field.form_type)
|
||||||
|
},
|
||||||
|
// 精度
|
||||||
|
canPrecisions() {
|
||||||
|
return [
|
||||||
|
'date_interval',
|
||||||
|
'position',
|
||||||
|
'select',
|
||||||
|
'checkbox'
|
||||||
|
].includes(this.field.form_type)
|
||||||
|
},
|
||||||
|
// 精度标题
|
||||||
|
precisionsTitle() {
|
||||||
|
if (!this.canPrecisions) return ''
|
||||||
|
switch (this.field.form_type) {
|
||||||
|
case 'date_interval':
|
||||||
|
return '日期类型'
|
||||||
|
case 'position':
|
||||||
|
return '地址精度'
|
||||||
|
case 'select':
|
||||||
|
return '展示方式'
|
||||||
|
case 'checkbox':
|
||||||
|
return '展示方式'
|
||||||
|
default:
|
||||||
|
return '精度'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 是否为描述文字类型
|
||||||
|
isDescText() {
|
||||||
|
return this.field.form_type === 'desc_text'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 是否为明细表格内部字段
|
||||||
|
isTableChild() {
|
||||||
|
const fatherField = this.fieldArr[this.point[0]][this.point[1]]
|
||||||
|
return fatherField.form_type === 'detail_table'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
field: {
|
||||||
|
handler() {
|
||||||
|
this.stylePercentValue = [Number(this.field.style_percent) || 100]
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
emitUpdateWidth() {
|
||||||
|
this.$emit('update-width')
|
||||||
|
},
|
||||||
|
emitChildEdit(field = null) {
|
||||||
|
this.$emit('child-edit', field)
|
||||||
|
},
|
||||||
|
clickOutSide() {
|
||||||
|
this.emitChildEdit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-checkbox /deep/ .el-checkbox__label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-setting {
|
||||||
|
.setting-title {
|
||||||
|
padding: 20px 15px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-body {
|
||||||
|
padding: 0 15px 10px;
|
||||||
|
.input-tips {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #999;
|
||||||
|
span {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-section {
|
||||||
|
padding: 10px 0;
|
||||||
|
border-bottom: 1px solid #e6e6e6;
|
||||||
|
.name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-check-section {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,39 @@
|
|||||||
|
export default class Field {
|
||||||
|
constructor(obj) {
|
||||||
|
this.field_type = 0 // 新增字段默认加入0 1是系统字段 2 客户行业 级别 来源 等 3 特殊
|
||||||
|
this.field_id = obj.field_id || '' // 字段id 1
|
||||||
|
this.name = obj.name || '' // 标识名 1
|
||||||
|
this.form_type = obj.form_type || '' // 字段类型 1
|
||||||
|
this.is_unique = obj.is_unique || 0 // 是否唯一
|
||||||
|
this.is_null = obj.is_null || 0 // 是否必填
|
||||||
|
this.is_hidden = obj.is_hidden || 0 // 是否隐藏字段
|
||||||
|
this.input_tips = obj.input_tips || '' // 输入提示
|
||||||
|
if (this.form_type === 'textarea') {
|
||||||
|
this.max_length = obj.max_length || 800 // textarea 多行文本有最大数量
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.form_type === 'checkbox') {
|
||||||
|
this.default_value = obj.default_value || []
|
||||||
|
} else {
|
||||||
|
this.default_value = obj.default_value || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格的特殊处理
|
||||||
|
if (this.form_type === 'form') {
|
||||||
|
this.formValue = obj.formValue || [] // 内部布局
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setting = obj.setting || [] // 单选选项
|
||||||
|
// this.showSetting = obj.showSetting || [] // 单选选项
|
||||||
|
// this.componentName = '' // 组件名字
|
||||||
|
this.is_deleted = 0 // 是删除标示这个字段是无效的 1是无效的
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验数据
|
||||||
|
check() {
|
||||||
|
if (this.name === '') {
|
||||||
|
return '字段名称不能为空'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
export default [{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'text',
|
||||||
|
name: '单行文本',
|
||||||
|
type: 1,
|
||||||
|
icon: 'wk wk-icon-text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldTextarea',
|
||||||
|
form_type: 'textarea',
|
||||||
|
name: '多行文本',
|
||||||
|
type: 2,
|
||||||
|
icon: 'wk wk-icon-textarea'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'website',
|
||||||
|
name: '网址',
|
||||||
|
type: 25,
|
||||||
|
icon: 'wk wk-icon-website'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
componentName: 'FieldBoolean',
|
||||||
|
form_type: 'boolean_value',
|
||||||
|
name: '布尔值',
|
||||||
|
type: 41,
|
||||||
|
icon: 'wk wk-icon-bool'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldSelect',
|
||||||
|
form_type: 'select',
|
||||||
|
name: '单选',
|
||||||
|
type: 3,
|
||||||
|
icon: 'wk wk-icon-select'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldCheckbox',
|
||||||
|
form_type: 'checkbox',
|
||||||
|
name: '多选',
|
||||||
|
type: 9,
|
||||||
|
icon: 'wk wk-icon-checkbox'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'number',
|
||||||
|
name: '数字',
|
||||||
|
type: 5,
|
||||||
|
icon: 'wk wk-icon-int'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'floatnumber',
|
||||||
|
name: '货币',
|
||||||
|
type: 6,
|
||||||
|
icon: 'wk wk-icon-coin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldPercent',
|
||||||
|
form_type: 'percent',
|
||||||
|
name: '百分数',
|
||||||
|
type: 42,
|
||||||
|
icon: 'wk wk-icon-percent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'mobile',
|
||||||
|
name: '手机',
|
||||||
|
type: 7,
|
||||||
|
icon: 'wk wk-icon-mobile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'email',
|
||||||
|
name: '邮箱',
|
||||||
|
type: 14,
|
||||||
|
icon: 'wk wk-icon-email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'date',
|
||||||
|
name: '日期',
|
||||||
|
type: 4,
|
||||||
|
icon: 'wk wk-icon-date'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'datetime',
|
||||||
|
name: '日期时间',
|
||||||
|
type: 13,
|
||||||
|
icon: 'wk wk-icon-datetime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldDateInterval',
|
||||||
|
form_type: 'date_interval',
|
||||||
|
name: '日期区间',
|
||||||
|
type: 48,
|
||||||
|
icon: 'wk wk-icon-range'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldPosition',
|
||||||
|
form_type: 'position',
|
||||||
|
name: '地址',
|
||||||
|
type: 43,
|
||||||
|
icon: 'wk wk-icon-address'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldLocation',
|
||||||
|
form_type: 'location',
|
||||||
|
name: '定位',
|
||||||
|
type: 44,
|
||||||
|
icon: 'wk wk-icon-nav'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'user',
|
||||||
|
name: '人员',
|
||||||
|
type: 10,
|
||||||
|
icon: 'wk wk-icon-user-data'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'structure',
|
||||||
|
name: '部门',
|
||||||
|
type: 12,
|
||||||
|
icon: 'wk wk-icon-users'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldFile',
|
||||||
|
form_type: 'file',
|
||||||
|
name: '附件',
|
||||||
|
type: 8,
|
||||||
|
icon: 'wk wk-icon-file'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldWritingSign',
|
||||||
|
form_type: 'handwriting_sign',
|
||||||
|
name: '手写签名',
|
||||||
|
type: 46,
|
||||||
|
icon: 'wk wk-icon-signature'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldDescText',
|
||||||
|
form_type: 'desc_text',
|
||||||
|
name: '描述文字',
|
||||||
|
type: 50,
|
||||||
|
icon: 'wk wk-icon-des'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'FieldDetailTable',
|
||||||
|
form_type: 'detail_table',
|
||||||
|
name: '明细表格',
|
||||||
|
type: 45,
|
||||||
|
icon: 'wk wk-icon-file'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export const picField = {
|
||||||
|
componentName: 'FieldInput',
|
||||||
|
form_type: 'pic',
|
||||||
|
name: '图片',
|
||||||
|
icon: 'wk '
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue