@form-create/component-ivu-frame
Version:
@form-create/iview 内置组件
328 lines (312 loc) • 11.1 kB
JSX
import toArray from '@form-create/utils/lib/toarray';
import './style.css'
const NAME = 'fcFrame';
export default function createFrame(config) {
return {
name: NAME,
props: {
formCreateInject: {
type: Object,
required: true,
},
type: {
type: String,
default: 'input'
},
field: String,
helper: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
src: {
type: String,
required: true
},
icon: {
type: String,
default: config.fileUpIcon
},
width: {
type: [Number, String],
default: 500
},
height: {
type: String,
default: '370px'
},
maxLength: {
type: Number,
default: 0
},
okBtnText: {
type: String,
default: '确定'
},
closeBtnText: {
type: String,
default: '关闭'
},
modalTitle: String,
handleIcon: {
type: [String, Boolean],
default: undefined
},
title: String,
allowRemove: {
type: Boolean,
default: true
},
onOpen: {
type: Function,
default: () => {
}
},
onOk: {
type: Function,
default: () => {
}
},
onCancel: {
type: Function,
default: () => {
}
},
onLoad: {
type: Function,
default: () => {
}
},
onBeforeRemove: {
type: Function,
default: () => {
}
},
onRemove: {
type: Function,
default: () => {
}
},
onHandle: {
type: Function,
default(src) {
this.previewImage = this.getSrc(src);
this.previewVisible = true;
}
},
modal: {
type: Object,
default: () => ({})
},
srcKey: {
type: [String, Number]
},
value: [Array, String, Number, Object],
previewMask: undefined,
footer: {
type: Boolean,
default: true
},
reload: {
type: Boolean,
default: true
},
closeBtn: {
type: Boolean,
default: true
},
okBtn: {
type: Boolean,
default: true
},
},
data() {
return {
fileList: toArray(this.value),
previewVisible: false,
frameVisible: false,
previewImage: ''
}
},
watch: {
value(n) {
this.fileList = toArray(n);
},
fileList(n) {
const val = this.maxLength === 1 ? (n[0] || '') : n;
this.$emit('input', val);
this.$emit('change', val);
},
src(n) {
this.modalVm && (this.modalVm.src = n);
}
},
methods: {
key(unique) {
return unique;
},
closeModel(close) {
this.$emit(close ? '$close' : '$ok');
if (this.reload) {
this.$off('$ok');
this.$off('$close');
}
this.frameVisible = false;
},
showModel() {
if (this.disabled || false === this.onOpen()) return;
this.frameVisible = true;
},
makeInput() {
const props = {
type: 'text',
value: (this.fileList.map(v => this.getSrc(v))).toString(),
icon: this.icon,
readonly: true,
clearable: false
};
return <Input props={props} on={{'on-click': () => this.showModel()}} key={this.key('input')}/>
},
makeGroup(children) {
if (!this.maxLength || this.fileList.length < this.maxLength)
children.push(this.makeBtn());
return <div key={this.key('group')}>{...children}</div>
},
makeItem(index, children) {
return <div class='fc-files' key={this.key('file' + index)}>{...children}</div>;
},
valid(f) {
const field = this.formCreateInject.field || this.field;
if (field && f !== field)
throw new Error('[frame]无效的字段值');
},
makeIcons(val, index) {
if (this.handleIcon !== false || this.allowRemove === true) {
const icons = [];
if ((this.type !== 'file' && this.handleIcon !== false) || (this.type === 'file' && this.handleIcon))
icons.push(this.makeHandleIcon(val, index));
if (this.allowRemove)
icons.push(this.makeRemoveIcon(val, index));
return <div class='fc-upload-cover' key={this.key('uc')}>{icons}</div>
}
},
makeHandleIcon(val, index) {
return <icon
props={{type: (this.handleIcon === true || this.handleIcon === undefined) ? 'ios-eye-outline' : this.handleIcon}}
on-click={() => this.handleClick(val)} key={this.key('hi' + index)}/>
},
makeRemoveIcon(val, index) {
return <icon props={{type: 'ios-trash-outline'}} on-click={() => this.handleRemove(val)}
key={this.key('ri' + index)}/>
},
makeFiles() {
return this.makeGroup(this.fileList.map((src, index) => {
return this.makeItem(index, [<icon props={{type: config.fileIcon, size: 40}}
on-click={() => this.handleClick(src)}/>, this.makeIcons(src, index)])
}))
},
makeImages() {
return this.makeGroup(this.fileList.map((src, index) => {
return this.makeItem(index, [<img src={this.getSrc(src)}/>, this.makeIcons(src, index)])
}))
},
makeBtn() {
return <div class='fc-upload-btn' on-click={() => this.showModel()}
key={this.key('btn')}>
<icon props={{type: this.icon, size: 20}}/>
</div>
},
handleClick(src) {
return this.onHandle(src);
},
handleRemove(src) {
if (this.disabled) return;
if (false !== this.onBeforeRemove(src)) {
this.fileList.splice(this.fileList.indexOf(src), 1);
this.onRemove(src);
}
},
getSrc(src) {
return !(this.srcKey) ? src : src[this.srcKey];
},
frameLoad(iframe) {
this.onLoad(iframe);
try {
if (this.helper === true) {
iframe['form_create_helper'] = {
api: this.formCreateInject.api,
close: (field) => {
this.valid(field);
this.closeModel();
},
set: (field, value) => {
this.valid(field);
if (!this.disabled)
this.$emit('input', value);
},
get: (field) => {
this.valid(field);
return this.value;
},
onOk: fn => this.$on('$ok', fn),
onClose: fn => this.$on('$close', fn)
};
}
} catch (e) {
console.log(e);
}
},
makeFooter() {
const {okBtnText, closeBtnText, closeBtn, okBtn, footer} = this.$props;
const node = [];
if (!footer) return node;
if (closeBtn)
node.push(<Button
on-click={() => (this.onCancel() !== false && this.closeModel(true))}>{closeBtnText}</Button>);
if (okBtn)
node.push(<Button type="primary"
on-click={() => (this.onOk() !== false && this.closeModel())}>{okBtnText}</Button>);
return node;
}
},
render() {
const type = this.type;
let node;
if (type === 'input')
node = this.makeInput();
else if (type === 'image')
node = this.makeImages();
else
node = this.makeFiles();
const {width, height, src, title, modalTitle} = this.$props;
this.$nextTick(() => {
if (this.$refs.frame) {
this.frameLoad(this.$refs.frame.contentWindow || {});
}
});
return <div class="_fc-frame">{node}
<Modal v-model={this.previewVisible}
props={{mask: this.previewMask, title: modalTitle, footerHide: true}}>
<img style="width: 100%" src={this.previewImage}/>
</Modal>
<Modal props={{width, title, ...this.modal}} v-model={this.frameVisible}
on-on-cancel={() => (this.closeModel(true))}>
{(this.frameVisible || !this.reload) ? <iframe ref="frame" src={src} frameBorder="0" style={{
'height': height,
'border': '0 none',
'width': '100%'
}}/> : null}
<div slot="footer">
{this.makeFooter()}
</div>
</Modal>
</div>
},
mounted() {
this.$on('fc.closeModal', this.closeModal);
}
};
}