Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
traceSourceMb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
yanyanhong
traceSourceMb
Commits
4ad99be5
Commit
4ad99be5
authored
Sep 27, 2020
by
yyh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新模板管理
parent
bbb096e2
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
444 additions
and
539 deletions
+444
-539
index.ts
src/components/index.ts
+3
-1
Add.vue
src/views/template/Add.vue
+31
-504
AddOption.vue
src/views/template/components/AddOption.vue
+11
-16
BaseInfo.vue
src/views/template/components/BaseInfo.vue
+23
-18
WordItem.vue
src/views/template/components/WordItem.vue
+91
-0
WordsManager.vue
src/views/template/components/WordsManager.vue
+285
-0
No files found.
src/components/index.ts
View file @
4ad99be5
import
{
importAll
}
from
'@/utils/utils'
;
import
{
importAll
}
from
'@/utils/utils'
;
const
components
=
importAll
(
require
.
context
(
'@/components/'
,
true
,
/
\.
vue$/
));
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
{
export
default
{
install
(
Vue
:
any
)
{
install
(
Vue
:
any
)
{
Vue
.
component
(
List
.
name
,
List
);
Vue
.
component
(
List
.
name
,
List
);
...
@@ -12,6 +12,8 @@ export default {
...
@@ -12,6 +12,8 @@ export default {
Vue
.
component
(
Button
.
name
,
Button
);
Vue
.
component
(
Button
.
name
,
Button
);
Vue
.
component
(
Popup
.
name
,
Popup
);
Vue
.
component
(
Popup
.
name
,
Popup
);
Vue
.
component
(
Dialog
.
Component
.
name
,
Dialog
.
Component
);
Vue
.
component
(
Dialog
.
Component
.
name
,
Dialog
.
Component
);
Vue
.
component
(
NavBar
.
name
,
NavBar
);
Vue
.
component
(
SwipeCell
.
name
,
SwipeCell
);
Object
.
keys
(
components
).
forEach
((
key
:
string
)
=>
{
Object
.
keys
(
components
).
forEach
((
key
:
string
)
=>
{
Vue
.
component
(
key
,
components
[
key
]);
Vue
.
component
(
key
,
components
[
key
]);
});
});
...
...
src/views/template/Add.vue
View file @
4ad99be5
<
template
>
<
template
>
<div
class=
"template"
>
<div
class=
"template"
>
<base-info
@
next=
"next"
@
cancel=
"cancelCreateTempl"
></base-info>
<base-info
:showBaseInfo
.
sync=
"showBaseInfo"
@
next=
"baseInfoNext"
@
cancel=
"cancelCreateTempl"
></base-info>
<div
v-for=
"(item,index) in data"
:key=
"index"
class=
"template-item van-hairline--top"
>
<words-manager
:data
.
sync=
"words"
@
show-preview=
"showPreview= true;"
@
confirm-words=
"confirm"
></words-manager>
<div
v-if=
"item.type === 3"
>
<transition
name=
"van-slide-up"
>
<div
style=
"display:flex;flex-direction:row;justify-content:space-between;"
class=
"data-item van-hairline--bottom"
>
<preview-template
:data=
"words"
v-if=
"showPreview"
@
cancel=
"showPreview = false"
@
employ=
"employ"
></preview-template>
<div
style=
"color:#353535;font-size:18px;font-weight:500;"
>
{{
item
.
label
}}
</div>
</transition>
<div
style=
"width: 30px;text-align:center;"
>
<common-svg
name=
"cunzhengliebiao-gengduo"
@
click
.
native=
"showActionHandler(index)"
width=
"20px"
height=
"20px"
></common-svg>
</div>
<!--
<div
@
click=
"preAddWord(2,item)"
style=
"color:#3F79FE;font-size:16px;"
>
添加字段
</div>
-->
</div>
<div
v-for=
"(item, index2) in item.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, index)"
></common-svg>
</div>
<div
@
click=
"preAddWord(2,item)"
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>
<div
class=
"add-word"
@
click=
"preAddWord(1)"
>
<common-svg
name=
"tianjia"
style=
"margin-right:10px;"
></common-svg>
添加一级标题
</div>
<p
class=
"tip"
>
比如:基本信息、出厂信息、图片描述……
</p>
<div
class=
"btn-group"
>
<div
role=
"button"
v-show=
"data.length > 0"
class=
"preview"
@
click=
"preview = true"
>
预览
</div>
<div
role=
"button"
class=
"slc-btn-common confirm"
@
click=
"confirm"
>
确定
</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=
"level === 2"
@
click=
"show2 = 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>
<transition
name=
"van-slide-up"
>
<add-option
v-if=
"show2"
@
back=
"show2=false"
@
confirmWordType=
"confirmWordType"
></add-option>
</transition>
<transition
name=
"van-slide-up"
>
<preview-template
:data=
"data"
v-if=
"preview"
@
cancel=
"preview = false"
@
employ=
"employ"
></preview-template>
</transition>
<more-action
:show
.
sync=
"showAction"
:menuList=
"menuList"
></more-action>
</div>
</div>
</
template
>
</
template
>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
Component
,
Prop
,
Vue
}
from
'vue-property-decorator'
;
import
{
Component
,
Prop
,
Vue
}
from
'vue-property-decorator'
;
import
{
List
,
Image
,
Field
,
Dialog
,
GridItem
,
Grid
,
Button
,
Popup
}
from
'vant'
;
import
{
TEMPLATETYPE
,
DataType
}
from
'@/const/enum'
;
import
{
TEMPLATETYPE
,
DataType
}
from
'@/const/enum'
;
import
BaseInfo
from
'./components/BaseInfo.vue'
;
import
BaseInfo
from
'./components/BaseInfo.vue'
;
import
AddOption
from
'./components/AddOption.vue'
;
import
PreviewTemplate
from
'./components/PreviewTemplate.vue'
;
import
PreviewTemplate
from
'./components/PreviewTemplate.vue'
;
// class Type {
import
WordsManager
from
'./components/WordsManager.vue'
;
// private label: string;
// private type: DataType;
// private data: DataType1;
// private options: string[];
// constructor(label: string, type: number, data: any, options: []) {
// this.label = label;
// this.type = type;
// this.data = data;
// this.options = options;
// }
// }
// class DataType1 {
// private type: string;
// private format: string;
// private value: any;
// constructor(type: string, format: string, value: any) {
// this.type = type;
// this.format = format;
// this.value = value;
// }
// protected toString() {
// return `{type: ${this.type}, format: ${this.format}, value: ${this.value}}`;
// }
// }
// class BaseType {
// protected label: string = '';
// protected key: string = '';
// protected type: number = -1;
// protected data: any = {};
// constructor(type: number, label: string, key: string) {
// this.label = label;
// this.key = key;
// this.type = type;
// }
// protected initData(val: any) {
// this.data = val;
// }
// protected createDataUnit(dataUnit: any) {
// throw new Error('未实现错误');
// }
// protected toString() {
// return `{label: ${this.label},key: ${this.key},type: ${this.type},data: ${this.data.toString()}}`;
// }
// }
// class TypeZero extends BaseType {
// constructor(label: string, key: string) {
// super(0, label, key);
// this.initData('');
// }
// protected createDataUnit(value: string) {
// this.data = new DataType1('text', 'string', value);
// return this;
// }
// }
// class TypeOne extends BaseType {
// constructor(label: string, key: string) {
// super(1, label, key);
// this.initData([]);
// }
// protected createDataUnit(value: string) {
// this.data.push(new DataType1('image', 'hash', value));
// return this;
// }
// }
// class TypeTwo extends BaseType {
// constructor(label: string, key: string) {
// super(2, label, key);
// this.initData([]);
// }
// protected createDataUnit(value: string) {
// this.data.push(new DataType1('file', 'hash', value));
// return this;
// }
// }
// class TypeThree extends BaseType {
// constructor(label: string, key: string) {
// super(3, label, key);
// this.initData([]);
// }
// protected createDataUnit(value: any) {
// this.data.push(createType(value.type, value.label, value.key));
// return this;
// }
// }
// class TypeFive extends BaseType {
// private options: string [] = [];
// constructor(label: string, key: string, options: string[] = []) {
// super(5, label, key);
// this.options = options;
// this.initData([]);
// }
// protected createDataUnit(value: any) {
// this.data.push(new DataType1('text', 'string', value));
// return this;
// }
// protected toString() {
// return `{label: ${this.label},key: ${this.key},type:
// ${this.type},data: ${this.data.toString()},options: [${this.options}]}`;
// }
// }
// class TypeSix extends BaseType {
// constructor(label: string, key: string) {
// super(6, label, key);
// this.initData('');
// }
// protected createDataUnit(value: any) {
// this.data.push(new DataType1('data', 'utc', value));
// return this;
// }
// }
// class TypeEight extends BaseType {
// constructor(label: string, key: string) {
// super(8, label, key);
// this.initData([]);
// }
// protected createDataUnit(value: string) {
// this.data.push(new DataType1('media', 'hash', value));
// return this;
// }
// }
// class TypeNine extends BaseType {
// constructor(label: string, key: string) {
// super(9, label, key);
// this.initData([]);
// }
// protected createDataUnit(value: string) {
// this.data.push(new DataType1('media', 'hash', value));
// return this;
// }
// }
// function createType(type: number, label: string, key: string, options: string[] = []) {
// switch (type) {
// case 0: return new TypeZero(label, key);
// case 1: return new TypeOne(label, key);
// case 2: return new TypeTwo(label, key);
// case 3: return new TypeThree(label, key);
// // case 4: return new TypeTwo(label, key);
// case 5: return new TypeFive(label, key, options);
// case 6: return new TypeSix(label, key);
// case 8: return new TypeEight(label, key);
// case 9: return new TypeNine(label, key);
// default: throw new Error('为定义数据类型');
// }
// }
// console.log(createType(0,'3','4').createDataUnit('123').toString());
// console.log(createType(1,'图片','图片').createDataUnit('0xfjdkfjkd').toString());
// console.log(createType(2,'3','4').createDataUnit('0xfjdkfjk').toString());
// console.log(createType(3,'123','3333').createDataUnit({type:1,label:'文本',key:''}).toString());
// console.log(createType(5,'222','4444',['r','f']).createDataUnit('r').createDataUnit('f').toString());
// console.log(createType(6,'3','4'));
// console.log(createType(8,'3','4'));
// console.log(createType(9,'3','4'));
@
Component
({
@
Component
({
components
:
{
components
:
{
BaseInfo
,
BaseInfo
,
AddOption
,
PreviewTemplate
,
PreviewTemplate
,
[
Field
.
name
]:
Field
,
WordsManager
,
[
Dialog
.
Component
.
name
]:
Dialog
.
Component
,
[
Grid
.
name
]:
Grid
,
[
GridItem
.
name
]:
GridItem
,
[
Button
.
name
]:
Button
,
[
Popup
.
name
]:
Popup
,
},
},
})
})
export
default
class
Add
extends
Vue
{
export
default
class
Add
extends
Vue
{
private
templateName
:
string
=
''
;
private
showBaseInfo
:
boolean
=
true
;
private
thumb
:
[]
=
[];
private
baseInfo
:
any
=
{
private
folder
:
any
=
{};
templateName
:
''
,
private
imgUrl
:
string
=
''
;
folder
:
{},
imgUrl
:
''
,
private
show
:
boolean
=
false
;
private
show2
:
boolean
=
false
;
private
level
:
number
=
1
;
private
wordName
:
string
=
''
;
private
wordType
:
number
=
0
;
private
options
:
string
[]
=
[];
private
preview
:
boolean
=
false
;
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
data
:
any
[]
=
[];
private
tempData
:
any
[]
=
[];
get
levelObj
():
any
{
private
showWordsManager
:
boolean
=
false
;
const
obj1
=
{
private
words
:
any
[]
=
[];
title
:
'添加标题'
,
placeholder
:
'一级标题名称'
,
private
showPreview
:
boolean
=
false
;
toast
:
'标题至少2个汉字'
,
};
const
obj2
=
{
title
:
'添加字段'
,
placeholder
:
'字段名称'
,
toast
:
'字段至少2个汉字'
,
};
const
obj
:
any
=
{
obj1
,
obj2
};
return
obj
[
`obj
${
this
.
level
}
`
];
}
private
showAction
:
boolean
=
false
;
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
currentIndex
:
number
=
-
1
;
private
parentIndex
:
number
=
-
1
;
private
flag
:
string
=
''
;
get
templateData
()
{
get
templateData
()
{
const
{
templateName
,
data
,
folder
}
=
this
;
const
{
baseInfo
,
words
}
=
this
;
const
{
templateName
,
folder
}
=
baseInfo
;
return
{
return
{
templateName
,
templateName
,
data
,
words
,
folder
,
folder
,
};
};
}
}
private
deepClone
(
data
:
any
)
{
private
baseInfoNext
(
data
:
any
)
{
return
JSON
.
parse
(
JSON
.
stringify
(
data
));
this
.
baseInfo
=
{...
data
};
}
private
next
(
data
:
any
)
{
this
.
templateName
=
data
.
templateName
;
this
.
thumb
=
data
.
fileList
;
this
.
folder
=
data
.
folder
;
this
.
imgUrl
=
data
.
imgUrl
;
}
}
private
cancelCreateTempl
()
{
private
cancelCreateTempl
()
{
this
.
$router
.
back
();
this
.
$router
.
back
();
}
}
private
showActionHandler
(
index
:
number
,
parentIndex
:
number
=
-
1
)
{
this
.
showAction
=
true
;
this
.
currentIndex
=
index
;
this
.
parentIndex
=
parentIndex
;
}
private
addBefore
()
{
this
.
flag
=
'before'
;
const
{
parentIndex
,
currentIndex
}
=
this
;
if
(
parentIndex
===
-
1
)
{
this
.
preAddWord
(
1
);
return
;
}
this
.
preAddWord
(
2
,
this
.
data
[
parentIndex
]);
}
private
addAfter
()
{
this
.
flag
=
'after'
;
const
{
parentIndex
,
currentIndex
}
=
this
;
if
(
parentIndex
===
-
1
)
{
this
.
preAddWord
(
1
);
return
;
}
this
.
preAddWord
(
2
,
this
.
data
[
parentIndex
]);
}
private
delWord
()
{
const
{
parentIndex
,
currentIndex
}
=
this
;
if
(
parentIndex
===
-
1
)
{
this
.
data
.
splice
(
currentIndex
,
1
);
return
;
}
this
.
data
[
parentIndex
].
data
.
splice
(
currentIndex
,
1
);
this
.
$toast
({
message
:
'删除成功'
,
duration
:
3000
,
});
this
.
showAction
=
false
;
}
private
preAddWord
(
level
:
number
,
item
?:
any
)
{
this
.
level
=
level
;
this
.
show
=
true
;
this
.
wordType
=
level
===
1
?
DataType
.
Unit
:
DataType
.
Input
;
this
.
tempData
=
item
?
item
.
data
:
this
.
data
;
}
private
addWord
(
action
:
string
,
done
:
any
)
{
if
(
action
===
'confirm'
)
{
if
(
this
.
wordName
===
''
)
{
this
.
$toast
(
this
.
levelObj
.
toast
);
done
(
false
);
return
;
}
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
!==
''
)
{
if
(
this
.
flag
===
'after'
)
{
this
.
currentIndex
++
;
}
this
.
tempData
.
splice
(
this
.
currentIndex
,
0
,
tempData
);
}
else
{
this
.
tempData
.
push
(
tempData
);
}
this
.
flag
=
''
;
this
.
wordName
=
''
;
this
.
wordType
=
0
;
this
.
showAction
=
false
;
done
();
}
else
{
done
();
}
}
private
confirmWordType
(
data
:
any
)
{
this
.
show2
=
false
;
this
.
wordType
=
data
.
type
;
this
.
options
=
data
.
type
===
DataType
.
Select
?
data
.
options
:
[];
}
private
commitTemplate
()
{
private
commitTemplate
()
{
if
(
this
.
data
.
length
<=
0
)
{
if
(
this
.
words
.
length
<=
0
)
{
return
Promise
.
reject
(
'请添加字段'
);
return
Promise
.
reject
(
'请添加字段'
);
}
}
return
this
.
$api
.
template
.
customize
(
this
.
templateName
,
this
.
data
,
this
.
folder
.
id
,
{
return
this
.
$api
.
template
.
customize
(
this
.
baseInfo
.
templateName
,
this
.
words
,
this
.
baseInfo
.
folder
.
id
,
{
s_image_url
:
this
.
imgUrl
,
s_image_url
:
this
.
baseInfo
.
imgUrl
,
});
});
}
}
private
confirm
()
{
private
confirm
()
{
...
@@ -483,71 +69,12 @@ export default class Add extends Vue {
...
@@ -483,71 +69,12 @@ export default class Add extends Vue {
}
}
</
script
>
</
script
>
<
style
scoped
lang=
"scss"
>
<
style
scoped
lang=
"scss"
>
.template
{
.template
{
position
:
relative
;
position
:
relative
;
// padding: 17px;
.tip
{
.template-item
{
font-size
:
12px
;
text-align
:
left
;
color
:
#737582
;
display
:
flex
;
margin-bottom
:
100px
;
flex-direction
:
column
;
font-size
:
10px
;
line-height
:
1
.5
;
color
:
#818181
;
background
:
#FFFFFF
;
padding
:
0
17px
;
margin-bottom
:
20px
;
.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
;
}
}
}
.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
);
}
.tip
{
font-size
:
12px
;
color
:
#737582
;
margin-bottom
:
100px
;
}
.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
;
}
}
}
.more-action
{
padding
:
20px
;
box-sizing
:
border-box
;
.content
{
display
:
grid
;
grid-gap
:
10px
;
grid-template-columns
:
repeat
(
3
,
100px
);
}
}
}
}
</
style
>
</
style
>
src/views/template/components/AddOption.vue
View file @
4ad99be5
<
template
>
<
template
>
<van-popup
v-model=
"show"
:style=
"
{'height': '100%', 'width': '100%'}" :overlay="false" get-container="body" >
<van-popup
v-model=
"show"
:style=
"
{'height': '100%', 'width': '100%'}" :overlay="false" get-container="body" >
<div
class=
"add-word1"
>
<div
class=
"add-word1"
>
<van-nav-bar
<van-nav-bar
title=
"选择字段类型"
title=
"选择字段类型"
left-arrow
left-arrow
@
click-left=
"onClickLeft"
></van-nav-bar>
@
click-left=
"onClickLeft"
></van-nav-bar>
<div
<div
v-for=
"(item, index) in data"
v-for=
"(item, index) in data"
:key=
"index"
:key=
"index"
class=
"item van-hairline--bottom van-hairline--top"
class=
"item van-hairline--bottom van-hairline--top"
@
click=
"activeName = item.type"
>
@
click=
"activeName = item.type"
>
...
@@ -39,29 +39,24 @@
...
@@ -39,29 +39,24 @@
</div>
</div>
<div
class=
"btn-group"
>
<div
class=
"btn-group"
>
<div
class=
"slc-btn-common right"
@
click=
"confirmWordType"
>
确定
</div>
<div
class=
"slc-btn-common right"
@
click=
"confirmWordType"
>
确定
</div>
<!-- <van-button block color="#5D7BF6" type="primary" @click="confirmWordType">确定</van-button> -->
</div>
</div>
</div>
</div>
</van-popup>
</van-popup>
</template>
</template>
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
{
Component
,
Prop
,
Vue
,
Emit
}
from
'vue-property-decorator'
;
import
{
Component
,
PropSync
,
Vue
,
Emit
}
from
'vue-property-decorator'
;
import
{
Collapse
,
CollapseItem
,
Field
,
Button
,
NavBar
,
SwipeCell
,
Popup
}
from
'vant'
;
import
{
TEMPLATETYPE
,
DataType
}
from
'@/const/enum'
;
import
{
TEMPLATETYPE
}
from
'@/const/enum'
;
@
Component
({
@
Component
({
components
:
{
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
{
export
default
class
AddOption
extends
Vue
{
@
PropSync
(
'showOptions'
,
{
type
:
Boolean
,
required
:
true
,
})
private
show
!
:
boolean
;
private
activeName
:
number
=
0
;
private
activeName
:
number
=
0
;
private
show
:
boolean
=
true
;
private
data
=
[
private
data
=
[
{
{
title
:
'单行文本'
,
title
:
'单行文本'
,
...
...
src/views/template/components/BaseInfo.vue
View file @
4ad99be5
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
<div
style=
"position:relative;margin-bottom:26px;font-size:18px;"
>
<div
style=
"position:relative;margin-bottom:26px;font-size:18px;"
>
<common-svg
<common-svg
@
click
.
native=
"cancel"
@
click
.
native=
"cancel"
name=
"shanchu5"
name=
"shanchu5"
style=
"position:absolute;left:17px;"
></common-svg>
style=
"position:absolute;left:17px;"
></common-svg>
<span>
创建模板
</span>
<span>
创建模板
</span>
</div>
</div>
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
<div
@
click=
"next"
class=
"slc-btn-common next"
>
下一步
</div>
<div
@
click=
"next"
class=
"slc-btn-common next"
>
下一步
</div>
</div>
</div>
<van-popup
<van-popup
v-model=
"show
2
"
v-model=
"show
SelectFolder
"
position=
"bottom"
>
position=
"bottom"
>
<van-picker
<van-picker
show-toolbar
show-toolbar
...
@@ -45,7 +45,7 @@
...
@@ -45,7 +45,7 @@
</van-popup>
</van-popup>
</
template
>
</
template
>
<
script
lang=
"ts"
>
<
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
{
Collapse
,
CollapseItem
,
Field
,
Button
,
NavBar
,
SwipeCell
,
Popup
,
Uploader
,
Picker
,
Image
}
from
'vant'
;
import
{
TEMPLATETYPE
}
from
'@/const/enum'
;
import
{
TEMPLATETYPE
}
from
'@/const/enum'
;
@
Component
({
@
Component
({
...
@@ -63,8 +63,12 @@ import { TEMPLATETYPE } from '@/const/enum';
...
@@ -63,8 +63,12 @@ import { TEMPLATETYPE } from '@/const/enum';
},
},
})
})
export
default
class
BaseInfo
extends
Vue
{
export
default
class
BaseInfo
extends
Vue
{
private
show
:
boolean
=
true
;
@
PropSync
(
'showBaseInfo'
,
{
private
show2
:
boolean
=
false
;
type
:
Boolean
,
required
:
true
,
})
private
show
!
:
boolean
;
private
showSelectFolder
:
boolean
=
false
;
private
folderList
:
[]
=
[];
private
folderList
:
[]
=
[];
private
templateName
:
string
=
''
;
private
templateName
:
string
=
''
;
private
imgUrl
:
string
=
''
;
private
imgUrl
:
string
=
''
;
...
@@ -73,14 +77,16 @@ export default class BaseInfo extends Vue {
...
@@ -73,14 +77,16 @@ export default class BaseInfo extends Vue {
private
defaultFolderIndex
:
number
=
0
;
private
defaultFolderIndex
:
number
=
0
;
private
defaultFolderName
:
string
=
'未分类文件夹'
;
private
defaultFolderName
:
string
=
'未分类文件夹'
;
private
mounted
()
{
private
mounted
()
{
this
.
$api
.
template
.
folderList
({
this
.
getFolders
();
template_type
:
TEMPLATETYPE
.
USER
,
}
}).
then
((
res
:
any
)
=>
{
private
async
getFolders
()
{
this
.
folderList
=
res
.
results
||
[];
const
{
results
=
[]}
=
await
this
.
$api
.
template
.
folderList
({
const
findDefaultFolder
=
(
folder
:
any
)
=>
folder
.
name
===
this
.
defaultFolderName
;
template_type
:
TEMPLATETYPE
.
USER
,
this
.
folder
=
this
.
folderList
.
find
(
findDefaultFolder
);
});
this
.
defaultFolderIndex
=
this
.
folderList
.
findIndex
(
findDefaultFolder
);
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
()
{
private
next
()
{
const
{
templateName
,
folder
,
imgUrl
}
=
this
;
const
{
templateName
,
folder
,
imgUrl
}
=
this
;
...
@@ -104,14 +110,13 @@ export default class BaseInfo extends Vue {
...
@@ -104,14 +110,13 @@ export default class BaseInfo extends Vue {
this
.
show
=
false
;
this
.
show
=
false
;
}
}
private
onConfirm
(
value
:
any
,
index
:
number
)
{
private
onConfirm
(
value
:
any
,
index
:
number
)
{
this
.
show
2
=
false
;
this
.
show
SelectFolder
=
false
;
this
.
folder
=
value
;
this
.
folder
=
value
;
}
}
private
handleFileChange
(
e
:
any
)
{
private
handleFileChange
(
e
:
any
)
{
const
input
=
e
.
target
;
const
[
file
]
=
e
.
tartet
.
files
;
const
files
=
input
.
files
;
if
(
file
)
{
if
(
files
&&
files
[
0
])
{
this
.
$api
.
file
.
upload
(
file
).
then
((
res
:
any
)
=>
{
this
.
$api
.
file
.
upload
(
files
[
0
]).
then
((
res
:
any
)
=>
{
this
.
imgUrl
=
res
.
url
;
this
.
imgUrl
=
res
.
url
;
});
});
}
}
...
...
src/views/template/components/WordItem.vue
0 → 100644
View file @
4ad99be5
<
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
src/views/template/components/WordsManager.vue
0 → 100644
View file @
4ad99be5
<
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
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment