423 lines
19 KiB
Vue
423 lines
19 KiB
Vue
<template>
|
||
<view style="width:100%;position: relative;">
|
||
<view style="min-height:10em;border:1px solid #dddddd;margin:0;background:#fafafa;">
|
||
<view v-for="(item,index) in mdlines" :key="index" @tap="rightmenu(index)" :class="item.vms">
|
||
<view v-if="item.cls == 'md-pic'">
|
||
<image :src="item.content" style="width:100%;display:block;" mode="widthFix"></image>
|
||
</view>
|
||
<view v-else :class="item.cls">{{item.content}}</view>
|
||
</view>
|
||
</view>
|
||
<view class="_edittip" style="top:-0.5em;">编辑区</view>
|
||
<input type="hidden" :name="name" :value="valuetxt" style="display:none;" />
|
||
<view style="position:relative;margin:0;border:1px solid #dddddd;">
|
||
<textarea :name="name + '_unup'" class="_textarea" v-model="etext" :fixed="true" auto-height maxlength="-1" />
|
||
<view style="display:flex;align-items: center;background:#ffffff;border-top:1px solid #dddddd;">
|
||
<view class="_icon _photo" @tap="upimg"></view>
|
||
<view style="position: absolute;bottom:0;left:4em;font-size:0.6em;color:#cccccc;">{{imgtip}}</view>
|
||
<view style="flex:1;text-align:right;padding:0 1em;">首行样式</view>
|
||
<ciy-picker name="linecls" v-model="elinecls" :range="styles" style="width:8em;"></ciy-picker>
|
||
<view class="_icon _uptxt" @tap="uptxt"></view>
|
||
</view>
|
||
<view class="_edittip" style="top:-1.5em;">录入区</view>
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
//下拉选择
|
||
//多行文本,每一行按照选择生成。
|
||
//按钮 上箭头,上传
|
||
//每段长按,删除、编辑、插入(在上)。
|
||
|
||
|
||
// 所见即所得的结果
|
||
// 添加文字段落
|
||
// 添加一张或多张图片
|
||
var app = getApp();
|
||
export default {
|
||
behaviors: ['uni://form-field-group']
|
||
, props: {
|
||
name: {
|
||
type: String
|
||
}
|
||
, value: {
|
||
type: String
|
||
, default: ''
|
||
}
|
||
, imgact: {
|
||
type: String
|
||
, default: 'cp|1280|60'
|
||
}
|
||
, uploadurl: {
|
||
type: String
|
||
, default: ''
|
||
}
|
||
, }
|
||
, data() {
|
||
return {
|
||
Gvalue: false
|
||
, valuetxt: '' //最终结果
|
||
, valuelines: [] //带格式的原始行
|
||
, mdlines: [] //显示的行
|
||
, eimgs: ''
|
||
, etext: ''
|
||
, imgtip: ''
|
||
, elinecls: 'md-content'
|
||
, styles: [{
|
||
id: 'md-content'
|
||
, pre: ''
|
||
, name: '正文'
|
||
}
|
||
, {
|
||
id: 'md-h1'
|
||
, pre: '#'
|
||
, name: '大标题'
|
||
}
|
||
, {
|
||
id: 'md-h1 _center'
|
||
, pre: '#c'
|
||
, name: '大标题居中'
|
||
}
|
||
, {
|
||
id: 'md-h1 _right'
|
||
, pre: '#r'
|
||
, name: '大标题靠右'
|
||
}
|
||
, {
|
||
id: 'md-h2'
|
||
, pre: '##'
|
||
, name: '二号标题 [n]'
|
||
}
|
||
, {
|
||
id: 'md-h3'
|
||
, pre: '###'
|
||
, name: '三号标题 [n.m]'
|
||
}
|
||
, {
|
||
id: 'md-h4'
|
||
, pre: '####'
|
||
, name: '四号标题 [n.m.k]'
|
||
}
|
||
, {
|
||
id: 'md-content _center'
|
||
, pre: '@c'
|
||
, name: '正文居中'
|
||
}
|
||
, {
|
||
id: 'md-content _right'
|
||
, pre: '@r'
|
||
, name: '正文靠右'
|
||
}
|
||
]
|
||
};
|
||
}
|
||
, watch: {
|
||
value(newD, oldD) {
|
||
if (this.Gvalue)
|
||
this.Gvalue = false;
|
||
else {
|
||
this.valuetxt = newD;
|
||
this.fillmdlines();
|
||
}
|
||
}
|
||
}
|
||
, mounted() {
|
||
this.valuetxt = this.value || '';
|
||
this.fillmdlines();
|
||
this.$emit('change', {
|
||
name: this.name
|
||
, from: 'create'
|
||
, value: this.valuetxt
|
||
});
|
||
}
|
||
, methods: {
|
||
fillmdlines() {
|
||
var markdown = this.valuetxt;
|
||
if (markdown.substr(0, 4) == '[MD]')
|
||
markdown = markdown.substr(4).trim();
|
||
var mds = markdown.split('\n');
|
||
var mdls = [];
|
||
for (var m in mds) {
|
||
if (mds[m].trim().length == 0) {
|
||
continue;
|
||
}
|
||
var mdl = {};
|
||
if (mds[m][0] == '#') { //标题1/2/3
|
||
if (mds[m].substr(0, 4) == '####') {
|
||
mdl.cls = 'md-h4';
|
||
mdl.content = 'n.m.k、' + mds[m].substr(4);
|
||
} else if (mds[m].substr(0, 3) == '###') {
|
||
mdl.cls = 'md-h3';
|
||
mdl.content = 'n.m、' + mds[m].substr(3);
|
||
} else if (mds[m].substr(0, 2) == '##') {
|
||
mdl.cls = 'md-h2';
|
||
mdl.content = 'n、' + mds[m].substr(2);
|
||
} else if (mds[m].substr(1, 1) == 'c') {
|
||
mdl.cls = 'md-h1 _center';
|
||
mdl.content = mds[m].substr(2);
|
||
} else if (mds[m].substr(1, 1) == 'r') {
|
||
mdl.cls = 'md-h1 _right';
|
||
mdl.content = mds[m].substr(2);
|
||
} else {
|
||
mdl.cls = 'md-h1';
|
||
mdl.content = mds[m].substr(1);
|
||
}
|
||
} else if (mds[m][0] == '@') { //c居中,r靠右
|
||
if (mds[m][1] == 'c') {
|
||
mdl.cls = 'md-content _center';
|
||
mdl.content = mds[m].substr(2);
|
||
} else if (mds[m][1] == 'r') {
|
||
mdl.cls = 'md-content _right';
|
||
mdl.content = mds[m].substr(2);
|
||
} else {
|
||
mdl.cls = 'md-content';
|
||
mdl.content = mds[m].substr(1);
|
||
}
|
||
} else if (mds[m][0] == '!') { //图片
|
||
var mis = mds[m].split('|');
|
||
var url = mis[0];
|
||
url = url.substring(1);
|
||
var alt = '';
|
||
if (mis[1])
|
||
alt = ' alt="' + mis[1].replace('"', "") + '"';
|
||
if (url.substr(0, 4).toLowerCase() != 'http')
|
||
url = this.file_stor(url);//xx
|
||
mdl.cls = 'md-pic';
|
||
mdl.content = url;
|
||
} else if (mds[m][0] == '_') {} else {
|
||
mdl.cls = 'md-content';
|
||
mdl.content = mds[m];
|
||
}
|
||
if (mdl.cls) {
|
||
mdl.idx = m;
|
||
mdl.vms = '';
|
||
mdls.push(mdl);
|
||
}
|
||
}
|
||
this.mdlines = mdls;
|
||
this.valuetxt = '[MD]' + markdown;
|
||
}
|
||
, rightmenu(idx) {
|
||
for (var i in this.mdlines)
|
||
this.mdlines[i].vms = '';
|
||
this.mdlines[idx].vms = '_sel';
|
||
var menus = [];
|
||
menus.push({
|
||
name: '插入'
|
||
, url: 'ins'
|
||
});
|
||
if (this.mdlines[idx].cls != 'md-pic') {
|
||
menus.push({
|
||
name: '编辑'
|
||
, url: 'edit'
|
||
});
|
||
}
|
||
menus.push({
|
||
name: '删除'
|
||
, url: 'del'
|
||
});
|
||
|
||
uni.showActionSheet({
|
||
itemList: menus.map(item => item.name)
|
||
, success: res => {
|
||
var menu = menus[res.tapIndex];
|
||
if (menu.url == 'del') {
|
||
app.askmsg('确认删除?', () => {
|
||
var ls = this.valuetxt.split('\n');
|
||
ls.splice(this.mdlines[idx].idx, 1);
|
||
this.valuetxt = ls.join('\n');
|
||
this.fillmdlines();
|
||
this.$emit('change', {
|
||
name: this.name
|
||
, from: 'delete'
|
||
, value: this.valuetxt
|
||
});
|
||
});
|
||
} else if (menu.url == 'edit') {
|
||
this.etext = this.mdlines[idx].content;
|
||
this.elinecls = this.mdlines[idx].cls;
|
||
this.mdlines[idx].vms = '_edit';
|
||
} else if (menu.url == 'ins') {
|
||
this.mdlines[idx].vms = '_ins';
|
||
}
|
||
}
|
||
, complete: res => {
|
||
if (this.mdlines[idx].vms == '_sel')
|
||
this.mdlines[idx].vms = '';
|
||
}
|
||
});
|
||
}
|
||
, doedit(pre, txt) {
|
||
var lineidx = -1;
|
||
var op = '_append';
|
||
for (var i in this.mdlines) {
|
||
if (this.mdlines[i].vms) {
|
||
lineidx = this.mdlines[i].idx;
|
||
op = this.mdlines[i].vms;
|
||
break;
|
||
}
|
||
}
|
||
|
||
var ls = this.valuetxt.split('\n');
|
||
if (op == '_append')
|
||
ls.push(pre + txt);
|
||
else if (op == '_edit') {
|
||
ls.splice(lineidx, 1, pre + txt);
|
||
} else {
|
||
ls.splice(lineidx, 0, pre + txt);
|
||
}
|
||
this.valuetxt = ls.join('\n');
|
||
this.fillmdlines();
|
||
}
|
||
, uptxt() {
|
||
var txt = this.etext;
|
||
if (txt == '')
|
||
return app.toast('请填写内容');
|
||
|
||
var pre = '';
|
||
for (var i = 0; i < this.styles.length; i++) {
|
||
if (this.styles[i].id == this.elinecls)
|
||
pre = this.styles[i].pre;
|
||
}
|
||
this.etext = '';
|
||
this.doedit(pre, txt);
|
||
this.$emit('change', {
|
||
name: this.name
|
||
, from: 'uptxt'
|
||
, pre: pre
|
||
, content: txt
|
||
, value: this.valuetxt
|
||
});
|
||
}
|
||
, upimg: function(b) {
|
||
if (this.Grunning)
|
||
return app.toast('上传中...');
|
||
//if (app.boi && app.boi.inboi()) {
|
||
var thos = this;
|
||
uni.chooseImage({
|
||
count: 9
|
||
, sizeType: ['original', 'compressed']
|
||
, success: res => {
|
||
console.log('choose', res);
|
||
var upcount = res.tempFilePaths.length;
|
||
thos.Grunning = true;
|
||
thos.imgtip = '上传 0/' + upcount;
|
||
var upidx = 0;
|
||
for (var u in res.tempFilePaths) {
|
||
(function(idx, img) {
|
||
var updata = {};
|
||
updata.imgact = thos.imgact;
|
||
uni.uploadFile({
|
||
url: thos.uploadurl
|
||
, filePath: img
|
||
, name: 'file'
|
||
, formData: updata
|
||
, header: {
|
||
'ciyauth': app.getstorage("_auth")
|
||
, 'ciyorg': app.getstorage("_org")
|
||
}
|
||
, success: res => {
|
||
var jsonup = app.json_parse(res.data);
|
||
if (jsonup === null)
|
||
jsonup = {
|
||
code: 0
|
||
, errmsg: 'JSON Parse ERROR:' + res.data.substr(0, 30)
|
||
}
|
||
upidx++;
|
||
if (jsonup.code != 1) {
|
||
thos.Grunning = false;
|
||
thos.imgtip = '';
|
||
if (jsonup.code == 2) {
|
||
app.askmsg('您尚未登录,请登录后上传\n立即前往登录?', () => {
|
||
uni.navigateTo({
|
||
url: '/main/login'
|
||
});
|
||
});
|
||
} else
|
||
thos.alert('上传失败:' + jsonup.errmsg);
|
||
return;
|
||
}
|
||
thos.doedit('!', jsonup.url);
|
||
thos.$emit('change', {
|
||
name: thos.name
|
||
, from: 'upimg'
|
||
, url: jsonup.url
|
||
, value: thos.valuetxt
|
||
});
|
||
thos.imgtip = '上传 ' + upidx + '/' + upcount;
|
||
if (upidx == upcount) {
|
||
thos.Gvalue = true;
|
||
thos.imgtip = '';
|
||
thos.Grunning = false;
|
||
}
|
||
}
|
||
});
|
||
})(u, res.tempFilePaths[u]);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
._edittip {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0.5em;
|
||
background: #fffad7;
|
||
border: 1px solid #dddddd;
|
||
padding: 0.2em 0.5em;
|
||
font-size: 0.6em;
|
||
border-radius: 0.5em;
|
||
line-height: 1.3em;
|
||
}
|
||
|
||
._center {
|
||
text-align: center;
|
||
}
|
||
|
||
._right {
|
||
text-align: right;
|
||
}
|
||
|
||
._ins {
|
||
border-top: 3px solid #cc0000;
|
||
}
|
||
|
||
._sel {
|
||
border: 1px solid #cc0000;
|
||
border-radius: 0.3em;
|
||
}
|
||
|
||
._edit {
|
||
border: 2px solid #009000;
|
||
}
|
||
|
||
._textarea {
|
||
display: block;
|
||
padding: 0.5em;
|
||
min-height: 5em;
|
||
background: #ffffff;
|
||
line-height:1.2em;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
._photo {
|
||
background-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTQyOC41NzYgMzc4LjM2OGE1MC4xNzYgNTAuMTc2IDAgMSAwLTEwMC4zNTIgMCA1MC4xNzYgNTAuMTc2IDAgMCAwIDEwMC4zNTIgMG0wIDB6IG0xNjYuOTQ0IDI1Ni40NDhoNDEuNTA0di00MS41MDRjMC0zMC41NiAxOC4zMzYtNTYuOCA0NC41MTItNjguNzM2bC02Ljk0NC0yMy44MDh2LTEuNjY0aDAuMDY0bC00NS40MDgtMTM3LjE4NC0xNTguNDk2IDIwNC41MTItNDIuNDk2LTcxLjk2OC0xNjguNTc2IDE3MC4xMTJoMjc2LjA5NmE3NS4zNiA3NS4zNiAwIDAgMSA1OS43NDQtMjkuNzZtMjY3LjcxMi0zNjEuNjY0YTExMi43MDQgMTEyLjcwNCAwIDAgMC0xMTIuMzg0LTExMi4zODRIMjczLjE1MmExMTIuNzA0IDExMi43MDQgMCAwIDAtMTEyLjM4NCAxMTIuMzg0djQ3Ny42NjRhMTEyLjcwNCAxMTIuNzA0IDAgMCAwIDExMi4zODQgMTEyLjM4NGgzMzcuMTg0di0wLjAzMmwwLjEyOCAwLjAzMmEyMS4wODggMjEuMDg4IDAgMSAwIDAtNDIuMTc2bC0wLjEyOCAwLjAzMnYtMC4wMzJIMjczLjE1MmE3MC4zMDQgNzAuMzA0IDAgMCAxLTcwLjI0LTcwLjI0VjI3My4xNTJjMC0zOC43NTIgMzEuNDg4LTcwLjI0IDcwLjI0LTcwLjI0aDQ3Ny42NjRjMzguNzUyIDAgNzAuMjQgMzEuNDg4IDcwLjI0IDcwLjI0djMzNS4xMzZjMCAwLjI1Ni0wLjEyOCAwLjQ0OC0wLjEyOCAwLjY3MmEyMS4wODggMjEuMDg4IDAgMSAwIDQyLjE3NiAwbC0wLjA2NC0wLjI1NmgwLjE5MlYyNzMuMTUybS0yMS44ODggNDE2LjIyNGgtMTA3LjQyNHYtMTA3LjQyNGEyMS4wODggMjEuMDg4IDAgMSAwLTQyLjE3NiAwdjEwNy40MjRINTg0LjMyYTIxLjA4OCAyMS4wODggMCAxIDAgMCA0Mi4xNzZoMTA3LjQyNHYxMDcuNDI0YTIxLjA4OCAyMS4wODggMCAxIDAgNDIuMTc2IDBWNzMxLjUyaDEwNy40MjRhMjEuMDg4IDIxLjA4OCAwIDEgMCAwLTQyLjE0NCIgZmlsbD0iIzQ4OENDQiI+PC9wYXRoPjwvc3ZnPg==");
|
||
}
|
||
|
||
._uptxt {
|
||
background-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUxMiAxMDIuNGM1NC42MTMzMzMgMCAxMDYuOTM5NzMzIDExLjM2NjQgMTU3LjAxMzMzMyAzMS44NDY0IDQ3Ljc4NjY2NyAyMC40OCA5My4yODY0IDUwLjA3MzYgMTMxLjk5MzYgODguNzQ2NjY3IDM4LjY3MzA2NyAzNi40MjAyNjcgNjguMjY2NjY3IDgxLjkyIDg4Ljc0NjY2NyAxMzEuOTkzNiAyMC40OCA1MC4wNzM2IDMxLjg0NjQgMTAyLjQgMzEuODQ2NCAxNTcuMDEzMzMzIDAgNTQuNjEzMzMzLTExLjM2NjQgMTA2LjkzOTczMy0zMS44NDY0IDE1Ny4wMTMzMzMtMjAuNDggNDcuNzg2NjY3LTUwLjA3MzYgOTMuMjg2NC04OC43NDY2NjcgMTMxLjk5MzYtMzYuNDIwMjY3IDM4LjY3MzA2Ny04MS45MiA2OC4yNjY2NjctMTMxLjk5MzYgODguNzQ2NjY3LTUwLjA3MzYgMjAuNDgtMTAyLjQgMzEuODQ2NC0xNTcuMDEzMzMzIDMxLjg0NjQtNTQuNjEzMzMzIDAtMTA2LjkzOTczMy0xMS4zNjY0LTE1Ny4wMTMzMzMtMzEuODQ2NC00Ny43ODY2NjctMjAuNDgtOTMuMjg2NC01MC4wNzM2LTEzMS45OTM2LTg4Ljc0NjY2Ny0zOC42NzMwNjctMzYuNDIwMjY3LTY4LjI2NjY2Ny04MS45Mi04OC43NDY2NjctMTMxLjk5MzYtMjAuNDgtNTAuMDczNi0zMS44NDY0LTEwMi40LTMxLjg0NjQtMTU3LjAxMzMzMyAwLTU0LjYxMzMzMyAxMS4zNjY0LTEwNi45Mzk3MzMgMzEuODQ2NC0xNTcuMDEzMzMzIDIwLjQ4LTQ3Ljc4NjY2NyA1MC4wNzM2LTkzLjI4NjQgODguNzQ2NjY3LTEzMS45OTM2IDM4LjcwNzItMzguNjczMDY3IDgxLjkyLTY4LjI2NjY2NyAxMzEuOTkzNi04OC43NDY2NjcgNTAuMDczNi0yMC40OCAxMDIuNC0zMS44NDY0IDE1Ny4wMTMzMzMtMzEuODQ2NHpNMjk1LjA4MjY2NyA1OTYuNjE2NTMzbC0yMS43MDg4IDk0LjkyNDggMzUuMjI1NiAzNS4yMjU2IDk0LjkyNDgtMjEuNzA4OC0xMDguNDQxNi0xMDguNDQxNnogbTIwOS4zNzM4NjYtMjg3LjA2MTMzM2wtMTc4Ljg1ODY2NiAxNzguODkyOGMtNC43NDQ1MzMgMzAuMTczODY3IDEuODQzMiA1MC4zMTI1MzMgMzIuOTcyOCA0Ny43ODY2NjdsMTIzLjkwNC0xMjAuMDgxMDY3IDEwLjk5MDkzMyAxMC45OTA5MzMtMTIwLjcyOTYgMTE2Ljk0MDhjNy41MDkzMzMgNDkuMDQ5NiAzOS41OTQ2NjcgNjguMjY2NjY3IDgyLjY3MDkzMyA3NC4yMDU4NjctNS42NjYxMzMgMzQuMjY5ODY3IDMuNDQ3NDY3IDU1LjAyMjkzMyA0NS45MDkzMzQgNDUuOTA5MzMzbDE3OC44NTg2NjYtMTc4Ljg5MjgtMTc1LjcxODQtMTc1Ljc1MjUzM3ogbTU1LjYzNzMzNC01NS4yOTZMNTIzLjk0NjY2NyAyOTAuMzcyMjY3bDE3NS43NTI1MzMgMTc1LjcxODQgMzYuMTQ3Mi0zNi4xNDcyYzE5Ljc5NzMzMy0xOS43OTczMzMgMTkuNzk3MzMzLTUyLjQ5NzA2NyAwLTcyLjI5NDRsLTEwMy40MjQtMTAzLjQyNGE1MS40Mzg5MzMgNTEuNDM4OTMzIDAgMCAwLTcyLjMyODUzMyAweiIgZmlsbD0iIzg1QzJGRiI+PC9wYXRoPjwvc3ZnPg==");
|
||
}
|
||
|
||
._icon {
|
||
width: 3em;
|
||
height: 3em;
|
||
background-size: cover;
|
||
}
|
||
</style> |