Commit 4ad99be5 authored by yyh's avatar yyh

更新模板管理

parent bbb096e2
import { importAll } from '@/utils/utils';
const components = importAll(require.context('@/components/', true, /\.vue$/ ));
import { List, Image, Empty, Field, Dialog, GridItem, Grid, Button, Popup } from 'vant';
import { List, Image, Empty, Field, Dialog, GridItem, Grid, Button, Popup, NavBar, SwipeCell } from 'vant';
export default {
install(Vue: any) {
Vue.component(List.name, List);
......@@ -12,6 +12,8 @@ export default {
Vue.component(Button.name, Button);
Vue.component(Popup.name, Popup);
Vue.component(Dialog.Component.name, Dialog.Component);
Vue.component(NavBar.name, NavBar);
Vue.component(SwipeCell.name, SwipeCell);
Object.keys(components).forEach((key: string) => {
Vue.component(key, components[key]);
});
......
This diff is collapsed.
<template>
<van-popup v-model="show" :style="{'height': '100%', 'width': '100%'}" :overlay="false" get-container="body" >
<div class="add-word1">
<van-nav-bar
<div class="add-word1">
<van-nav-bar
title="选择字段类型"
left-arrow
@click-left="onClickLeft"></van-nav-bar>
@click-left="onClickLeft"></van-nav-bar>
<div
v-for="(item, index) in data"
v-for="(item, index) in data"
:key="index"
class="item van-hairline--bottom van-hairline--top"
@click="activeName = item.type">
......@@ -39,29 +39,24 @@
</div>
<div class="btn-group">
<div class="slc-btn-common right" @click="confirmWordType">确定</div>
<!-- <van-button block color="#5D7BF6" type="primary" @click="confirmWordType">确定</van-button> -->
</div>
</div>
</van-popup>
</template>
<script lang="ts">
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
import { Collapse, CollapseItem, Field, Button, NavBar, SwipeCell, Popup } from 'vant';
import { TEMPLATETYPE } from '@/const/enum';
import { Component, PropSync, Vue, Emit } from 'vue-property-decorator';
import { TEMPLATETYPE, DataType } from '@/const/enum';
@Component({
components: {
[Collapse.name]: Collapse,
[CollapseItem.name]: CollapseItem,
[Field.name]: Field,
[Button.name]: Button,
[NavBar.name]: NavBar,
[SwipeCell.name]: SwipeCell,
[Popup.name]: Popup,
},
})
export default class AddOption extends Vue {
@PropSync('showOptions', {
type: Boolean,
required: true,
})
private show!: boolean;
private activeName: number = 0;
private show: boolean = true;
private data = [
{
title: '单行文本',
......
......@@ -9,7 +9,7 @@
<div style="position:relative;margin-bottom:26px;font-size:18px;">
<common-svg
@click.native="cancel"
name="shanchu5"
name="shanchu5"
style="position:absolute;left:17px;"></common-svg>
<span>创建模板</span>
</div>
......@@ -31,7 +31,7 @@
<div @click="next" class="slc-btn-common next">下一步</div>
</div>
<van-popup
v-model="show2"
v-model="showSelectFolder"
position="bottom" >
<van-picker
show-toolbar
......@@ -45,7 +45,7 @@
</van-popup>
</template>
<script lang="ts">
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
import { Component, Prop, PropSync, Vue, Emit } from 'vue-property-decorator';
import { Collapse, CollapseItem, Field, Button, NavBar, SwipeCell, Popup, Uploader, Picker , Image } from 'vant';
import { TEMPLATETYPE } from '@/const/enum';
@Component({
......@@ -63,8 +63,12 @@ import { TEMPLATETYPE } from '@/const/enum';
},
})
export default class BaseInfo extends Vue {
private show: boolean = true;
private show2: boolean = false;
@PropSync('showBaseInfo', {
type: Boolean,
required: true,
})
private show!: boolean;
private showSelectFolder: boolean = false;
private folderList: [] = [];
private templateName: string = '';
private imgUrl: string = '';
......@@ -73,14 +77,16 @@ export default class BaseInfo extends Vue {
private defaultFolderIndex: number = 0;
private defaultFolderName: string = '未分类文件夹';
private mounted() {
this.$api.template.folderList({
template_type: TEMPLATETYPE.USER,
}).then((res: any) => {
this.folderList = res.results || [];
const findDefaultFolder = (folder: any) => folder.name === this.defaultFolderName;
this.folder = this.folderList.find( findDefaultFolder );
this.defaultFolderIndex = this.folderList.findIndex( findDefaultFolder );
});
this.getFolders();
}
private async getFolders() {
const { results = []} = await this.$api.template.folderList({
template_type: TEMPLATETYPE.USER,
});
this.folderList = results;
const findDefaultFolder = (folder: any) => folder.name === this.defaultFolderName;
this.folder = this.folderList.find( findDefaultFolder );
this.defaultFolderIndex = this.folderList.findIndex( findDefaultFolder );
}
private next() {
const { templateName, folder, imgUrl} = this;
......@@ -104,14 +110,13 @@ export default class BaseInfo extends Vue {
this.show = false;
}
private onConfirm(value: any , index: number) {
this.show2 = false;
this.showSelectFolder = false;
this.folder = value;
}
private handleFileChange(e: any) {
const input = e.target;
const files = input.files;
if (files && files[0]) {
this.$api.file.upload(files[0]).then((res: any) => {
const [file] = e.tartet.files;
if (file) {
this.$api.file.upload(file).then((res: any) => {
this.imgUrl = res.url;
});
}
......
<template>
<div>
<div v-if="word.type === 3">
<div style="display:flex;flex-direction:row;justify-content:space-between;" class="data-item van-hairline--bottom">
<div style="color:#353535;font-size:18px;font-weight:500;">{{word.label}}</div>
<div style="width: 30px;text-align:center;">
<common-svg name="cunzhengliebiao-gengduo" width="20px" height="20px" @click.native="showActionHandler(wordIndex)"></common-svg>
</div>
</div>
<div v-for="(item, index2) in word.data" :key="index2" class="data-item van-hairline--bottom" style="margin-top:10px;">
<div style="font-size:15px;color:#353535;">{{item.label}}</div>
<div style="font-size:10px;color:#818181;">字段类型: {{typeObj[item.type]}}</div>
<common-svg name="cunzhengliebiao-gengduo" class="icon" width="20px" height="20px" @click.native="showActionHandler(index2, wordIndex)"></common-svg>
</div>
<div
@click="preAddWord(DataType.Input,word)"
style="color:#B6B5BA;font-size:16px;text-align:center;padding:12px;background:#FFFFFF;">
<common-svg name="tianjia1" width="16px" height="16px" style="margin-right:5px"></common-svg>添加下一级</div>
</div>
<div v-else>
出错了
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
import { Collapse, CollapseItem, Field, Button, NavBar, SwipeCell, Popup } from 'vant';
import { TEMPLATETYPE, DataType } from '@/const/enum';
@Component({
components: {
[Collapse.name]: Collapse,
[CollapseItem.name]: CollapseItem,
[Field.name]: Field,
[Button.name]: Button,
[NavBar.name]: NavBar,
[SwipeCell.name]: SwipeCell,
[Popup.name]: Popup,
},
})
export default class WordItem extends Vue {
@Prop({
required: true,
type: Object,
})
private word!: any;
@Prop()
private wordIndex!: number;
private typeObj: any = {
0: '单行文本',
1: '图片',
2: 'pdf文件',
3: '一级标题',
5: '选择',
6: '日期',
8: '视频',
9: '音频',
};
private DataType: any = DataType;
@Emit('show-action-handler')
private showActionHandler(index: number, parentIndex: number = -1) {
return {
index,
parentIndex,
};
}
@Emit('pre-add-word')
private preAddWord(level: number, word: any) {
return {
wordType: level,
word,
};
}
}
</script>
<style scoped lang="scss">
.data-item{
display: grid;
grid-template-columns: auto 30px;
grid-template-rows: repeat(2, 20px);
grid-auto-flow: column;
align-items: center;
padding: 10px 0;
.icon{
grid-row: span 2;
place-self: center;
}
}
</style>
\ No newline at end of file
<template>
<div class="template">
<word-item
v-for="(item,index) in words"
:word="item" :word-index="index"
@show-action-handler="showActionHandler"
:key="index"
@pre-add-word="preAddWord"
class="template-item van-hairline--top"></word-item>
<div class="add-word"
@click="preAddWord({wordType: DataType.Unit})">
<common-svg name="tianjia" style="margin-right:10px;"></common-svg>添加一级标题
</div>
<p class="tip">比如:基本信息、出厂信息、图片描述……</p>
<div class="btn-group">
<div role="button" v-show="words.length > 0" class="preview" @click="$emit('show-preview')">预览</div>
<div role="button" class="slc-btn-common confirm" @click="$emit('confirm-words')">确定</div>
</div>
<van-dialog
v-model="show"
:before-close="addWord"
:title="levelObj.title"
show-cancel-button>
<van-field v-model="wordName" label="" :placeholder="levelObj.placeholder"/>
<div
v-if="wordType !== DataType.Unit"
@click="showOptions = true;"
style="text-align:left;display:flex;justify-content:space-between;padding:16px;color:#999999;font-size:14px;"><span>字段类型</span> <span>{{typeObj[wordType]}}</span></div>
</van-dialog>
<add-option :showOptions.sync="showOptions" @back="showOptions=false" @confirmWordType="confirmWordType"></add-option>
<more-action :show.sync="showMoreAction" :menuList="menuList"></more-action>
</div>
</template>
<script lang="ts">
import { Component, Prop, PropSync, Vue } from 'vue-property-decorator';
import { List, Image, Field, Dialog, GridItem, Grid, Button, Popup } from 'vant';
import { TEMPLATETYPE, DataType } from '@/const/enum';
import WordItem from './WordItem.vue';
import AddOption from './AddOption.vue';
@Component({
components: {
WordItem,
AddOption,
},
})
export default class Add extends Vue {
@PropSync('data', {
required: true,
type: Array,
})
private words!: any[];
private wordType: number = DataType.Unit;
private DataType: any = DataType;
private wordName: string = '';
private flag: string = '';
private options: string[] = [];
private currentWords: any[] = [];
private showOptions: boolean = false;
private show: boolean = false;
private showMoreAction: boolean = false;
private currentAction: any = {
index: -1,
parentIndex: -1,
};
private menuList: any[] = [
{
icon: 'zaishangtianjia',
text: '在上添加',
action: this.addBefore.bind(this),
},
{
icon: 'zaixiatianjia',
text: '在下添加',
action: this.addAfter.bind(this),
},
{
icon: 'shanchu4',
text: '删除',
action: this.delWord.bind(this),
},
];
private typeObj: any = {
0: '单行文本',
1: '图片',
2: 'pdf文件',
3: '一级标题',
5: '选择',
6: '日期',
8: '视频',
9: '音频',
};
private typeValue: any = {
0: {
data : {
type : 'text',
format : 'string',
value : '',
},
type: 0,
key: '',
label: '单行文本',
},
1: {
data : {
type : 'image',
format : 'hash',
value : [],
},
type: 1,
key: '',
label: '图片',
},
2: {
data : {
type : 'file',
format : 'hash',
value : [],
},
type: 2,
key: '',
label: 'pdf',
},
3: {
data : [],
type: 3,
key: '',
label: '一级标题',
},
5: {
data : {
type : 'text',
format : 'string',
value : '',
},
type: 5,
key: '',
options: [],
label: '选择',
},
6: {
data : {
type : 'date',
format : 'utc',
value : 0,
},
type: 6,
key: '',
label: '日期',
},
8: {
data : {
type : 'video',
format : 'hash',
value : [],
},
type: 8,
key: '',
label: '视频',
},
9: {
data : {
type : 'audio',
format : 'hash',
value : [],
},
type: 9,
key: '',
label: '音频',
},
};
private showActionHandler({ index, parentIndex}: any) {
this.showMoreAction = true;
this.currentAction = {index, parentIndex};
}
private addBefore() {
const { index, parentIndex } = this.currentAction;
const wordType = parentIndex === -1 ? DataType.Unit : DataType.Input;
const word = parentIndex !== -1 ? this.words[parentIndex] : null;
this.preAddWord({ wordType, word}, 'before');
}
private addAfter() {
const { index, parentIndex } = this.currentAction;
const wordType = parentIndex === -1 ? DataType.Unit : DataType.Input;
const word = parentIndex !== -1 ? this.words[parentIndex] : null;
this.preAddWord({ wordType, word }, 'after');
}
private delWord() {
const { index, parentIndex } = this.currentAction;
const tempWords = parentIndex === -1 ? this.words : this.words[parentIndex].data;
tempWords.splice(index, 1);
}
private confirmWordType({type = DataType.Input, options}: any) {
this.wordType = type;
this.options = options;
this.showOptions = false;
}
get levelObj(): any {
if (this.wordType === DataType.Unit) {
return {
title: '添加标题',
placeholder: '一级标题名称',
toast: '标题至少2个汉字',
};
}
return {
title: '添加字段',
placeholder: '字段名称',
toast: '字段至少2个汉字',
};
}
private preAddWord({ wordType, word }: any, flag: string = '') {
this.show = true;
this.wordType = wordType;
this.currentWords = word ? word.data : this.words;
this.flag = flag;
}
private deepClone(data: any) {
return JSON.parse(JSON.stringify(data));
}
private addWord(action: string, done: any) {
if (action !== 'confirm') { return done(); }
if (this.wordName === '') {
this.$toast(this.levelObj.toast);
return done(false);
}
let tempData = {...this.deepClone((this.typeValue as any)[this.wordType]), label: this.wordName};
if (this.wordType === DataType.Select) {
tempData = { ...tempData, options: this.options};
}
if (this.flag === 'before') {
this.currentWords.splice( this.currentAction.index , 0 , tempData);
} else if (this.flag === 'after') {
let { index } = this.currentAction;
this.currentWords.splice( ++index , 0 , tempData);
} else {
this.currentWords.push(tempData);
}
this.wordName = '';
this.wordType = DataType.Unit;
this.flag = '';
done();
}
}
</script>
<style scoped lang="scss">
.template-item{
text-align: left;
display: flex;
flex-direction: column;
font-size: 10px;
line-height: 1.5;
color: #818181;
background: #FFFFFF;
padding: 0 17px;
margin-bottom: 20px;
}
.add-word{
padding: 17px;
margin: 0 20px;
margin-top: 20px;
font-size: 16px;
color: #3F79FE;
border-radius:6px;
border:1px dashed rgba(63,121,254,1);
}
.btn-group{
.preview{
align-self: center;
color: #353535;
background: #F0F1F5;
border-radius:4px;
width: 107px;
padding: 9px;
margin-right: 10px;
}
.confirm{
flex: auto;
align-self: center;
width: 228px;
padding: 9px;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment