***利用右边的选项卡给左边选中数据设置对应的色值***
下面是全部代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/vue"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/BrowserFS/2.0.0/browserfs.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/BrowserFS/2.0.0/browserfs.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/promise-polyfill/8.2.1/polyfill.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.js"></script>
<!-- 引入样式 -->
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>绿城需求样式</title>
</head>
<style>
body {
font-size: 16px;
}
/* 外层样式 */
.quter_layer {
border: 1px solid red;
height: 90vh;
/* width: 100%; */
margin: 0 25px;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
/* 左侧样式 */
.con_left {
width: 70%;
height: 100%;
border: 1px solid gold;
overflow-y: auto;
font-size: 18px;
font-weight: 500;
padding-left: 20px;
}
.con_left_cont {
overflow-y: auto;
}
.con_left_cont_item {
padding: 10px;
}
/* 右侧样式 */
.con_right {
width: 26.5%;
height: 100%;
border: 1px solid #cec0ff;
}
.con_right_title {
padding: 15px 25px;
}
.con_right_cont {
margin: 0 20px 20px 20px;
height: 91.5%;
overflow-y: auto;
}
.right_cont_item {
background: #f9f9f9;
margin-bottom: 10px;
}
.right_cont_item_title {
cursor: pointer;
color: #fff;
font-weight: 600;
padding: 13px 20px;
position: relative;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.right_cont_item_con {
padding: 15px 20px;
}
.contenttext {
margin: 0 auto;
width: 35%;
height: 500px;
overflow-y: auto;
border: 1px solid red;
}
.picker_box {
display: inline-block;
}
.box {
/* background: #5f8c2d; */
color: #fff;
padding: 8px 10px;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.box_con {
width: 93%;
display: inline-block;
}
.dot {
display: inline-block;
position: relative;
right: -5px;
width: 16px;
height: 16px;
line-height: 14px;
font-size: 12px;
border-radius: 100%;
text-align: center;
color: #fff;
cursor: pointer;
box-shadow: 0 0 4px #ddd;
transition: all 0.3s ease-in;
}
.dot:hover {
box-shadow: 0 0 4px #fff;
transform: scale(1.1);
}
/* 公共样式 */
.tip {
position: absolute;
right: 20px;
}
.checked_text {
position: relative;
top: 1px;
left: 3px;
}
</style>
<body>
<div id="app">
<div class="quter_layer">
<div
class="con_left"
ref="contenttext"
id="contenttext"
@mouseup.stop="getContText($event)"
>
<pre><div v-html="contText" ></div></pre>
</div>
<div class="con_right">
<div class="con_right_title">会议意见</div>
<div class="con_right_cont">
<div
class="right_cont_item"
v-for="(cor,i) in colorCardComputed"
:key="i"
>
<div
v-if="!isEdit"
class="right_cont_item_title"
:style="{background:cor.color}"
@click="locationHandler(cor)"
>
{{cor.title}}
<span class="tip">
{{cor.index + 1}}/{{cor.colorPickSumList.length}}
</span>
</div>
<div
v-if="isEdit"
class="right_cont_item_title"
:style="{background:cor.color}"
@click="colorHandler(cor)"
>
{{cor.title}}
<span @click.stop>
<el-checkbox
style="margin-left: 15px"
v-model="cor.checked"
@change="checkHandler(cor)"
></el-checkbox>
<span class="checked_text">{{cor.checkedText}}</span>
</span>
<span class="tip">{{cor.colorPickSumList.length}}</span>
</div>
<div class="right_cont_item_con">{{cor.cont}}</div>
<div v-if="isEdit && cor.checked">
<el-input
type="textarea"
:rows="3"
placeholder="请输入备注"
v-model="cor.selectSec" >
</el-input>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var Vnode = {}
var childNodes = null
var vm = new Vue({
el: '#app',
data: {
isEdit: true,
contText:
'激 买卖合同\n报审序号:\n合同编号:\n买受人:有限公司\n出卖人:有限公司\n签订地点:北科技有限公司\n签订时间:年月日\n根据《中华人民共和国合同法》等现行法律法规,本着自愿、平等、诚实信用的原则,双方就激光晒图纸等生产物资买卖事宜,协商一致,签订本合同。\n第一条标的、数量、价款及交(提)货时间(详见附表)\n合同总价:128.39元人民币,大写:壹拾元叁角玖分人民币。本合同标的金额为暂定,合同标的数量和金额须经买受人确认,以实际发生的数量和金额为准进行结算付款。\n合同价款构成:包含货款、增值税(税率13%)、运费、搬运装卸费、包装费等以及运输过程中发生的一切费用。买方不再另行支付其它费用。\n第二条质量标准及要求:\n因标的物质量不符合质量要求,买受人有权拒绝接受标的物或者解除合同。买受人拒绝接受标的物或者解除合同的,标的物毁损、灭失的风险由出卖人承担。\n第三条出卖人对质量负责的条件、质量保证金及质量保证期\n出卖人对质量负责的条件:产品实行“三保四包”(保质、保量、保及时、包修、包换、包退、包损失)\n质量保证金为标的金额的%,即人民币(大写):。\n质量保证期自买受人对标的物验收合格之日起个月,质量保证金在质量保证期满后日内支付。\n第四条包装标准、包装物的供应与回收:按照甲方要求将物资运送至指定地点,保证原包装。\n第五条随机的必备品、配件、工具数量及供应办法:随原件配备。\n第六条合理损耗标准及计算方法:\n第七条标的物所有权自交付并经买受人验收合格之时起转移,但买受人未履行支付价款义务的,标的物属于甲方所有。标的物毁损、灭失的风险随标的物所有权转移而转移。\n第八条交(提)货方式、地点:按照甲方要求杂指定时间运送至指定地点。\n第九条运输方式及到达站(港)和费用负担:乙方负责。\n第十条检验标准、方法、地点及期限\n1.检验标准:按照甲方要求执行。\n2.检验方法:经甲方验收合格。\n3.检验地点:思瑞公司。\n4.检验期限:10天。\n第十一条成套设备的安装与调试:出卖人负责免费安装调试,并对调试过程中的安全事宜负责。\n第十二条结算方式、时间及地点:验收合格后30日内,买方通过(转账结算)方式支付合同标的金额的100%\n第十三条出卖人依法出具全额增值税发票。\n第十四条担保方式(也可另立担保合同):无\n第十五条本合同经双方协商一致,可以变更,并订立书面变更协议。\n第十六条本合同解除的条件:\n1.因不可抗力致使不能实现合同目的;\n2.双方协商一致;\n3.出卖人交付不符合本合同约定的质量标准的标的物的,买受人有权解除合同;\n4.出卖人逾期10日交付标的物的,买受人有权解除合同;\n5.双方约定的其他情形:无\n第十七条有下列情形之一的,本合同的权利义务终止:\n1.合同已经按照约定履行;\n2.双方解除合同;\n3.法律规定的其他情形:无\n第十八条违约责任\n1.当事人一方不履行合同义务或者履行合同义务不符合约定的,应当承担继续履行、采取补救措施或者赔偿损失等违约责任。\n2.出卖人交付的标的物不符合质量要求的,应当按照合同金额的5%支付违约金,并赔偿由此给买受人造成的损失。\n3.如果出卖人未能按照合同约定向买受人交付标的物,每逾期一日,应当按照合同金额的5%向买受人支付违约金。\n4.买受人无正当理由未按约定支付合同价款的,每延迟一日,向出卖人支付延迟支付金额×(合同订立时1年期贷款市场报价利率365)的违约金。\n5.其他:无\n第十九条合同争议的解决方式\n本合同在履行过程中发生的争议,由双方当事人协商解决;协商不成的,按下列第二种方式解决。\n(一)提交大庆仲裁委员会仲裁。\n(二)依法向买受人所在地人民法院起诉。\n(三)提交双方上级部门协调解决。\n第二十条履行期限\n2020-10-10至2020-10-31\n第二十一条履行责任人\n买受人指定常咏为本合同买受人的履行负责人,买受人授权其代表买受人在合同履行过程中交付、接收相关资料及在相关履行资料上签字。如无买受人书面明确授权,其他任何人无权代表买受人签字。联系电话:17645858000\n第二十二条其他约定事项\n1.出卖人就交付的标的物负有保证第三人不得向买受人主张任何权利的义务。如第三人就标的物向买受人主张权利,应当由出卖人负责处理由此发生的争议,并承担由此给买受人造成的全部损失。\n2.买受人能够证明第三人可能就标的物主张权利的,可以中止支付相应的价款,直至出卖人依法提供相应的担保。\n3.本合同未尽事项,由双方根据国家法律、法规及有关规定协商另行订立补充协议,双方共同遵照执行。\n4.本合同经双方法定代表人(负责人)或授权代表签字,并加盖单位公章或合同专用章之日起生效。\n5.本合同一式4份,买受人执3份,出卖人执1份,每份具有同等法律效力。\n6.出卖人声明:本合同订立时,出卖人是属于中小企业。\n7.以下附件作为本合同的组成部分:无\n8.其它:无\n出卖人(合同专用章):北京慧点科技有限公司\n住所:大庆市让胡路区阳光佳苑四期\n法定代表人负责人授权代表(签字):\n电话13931201213\n账号:23050162340000000007\n开户银行:建设银行大庆景园支行\n税号:91242604MA18X2QB7C\n买受人(合同专用章):北京旷视科技有限公司\n住所:大庆市让胡路区西宾路\n法定代表人负责人授权代表(签字):\n电话:590388\n税号:912303749653847Q\n开户银行:工行大庆市铁人支行\n帐号:09050234209221010425', colorCard: [
{
color: 'red',
title: '营销',
cont: '关注交付、产权时间约定。双方团队权责界定清晰。',
checked: false,
checkedText: '123',
selectSec: '',
},
{
color: '#cec0ff',
title: '产品',
cont: '商业部分代建费支付不定。',
checked: false,
checkedText: '123',
selectSec: '',
},
{
color: '#89479B',
title: '财务',
cont: '商业部分代板房的区域设定。',
checked: true,
checkedText: '123',
selectSec: '',
},
{
color: '#E88024',
title: '本体',
cont: '商业部分代建费支付的区域设定。',
checked: true,
checkedText: '123',
selectSec: '',
},
],
domText: '',
// childNodes: '',
range: '',
startOffset: '',
endOffset: '',
conScrollTop: '',
hasSelectText: '',
hasSelectTextFlag: false,
index: -1,
checked: true,
conTarr: [],
},
computed: {
colorCardComputed() {
var count = 0
this.colorCard = this.colorCard.map((m) => {
return {
colorPickSumList: [],
index: -1,
...m,
}
})
Object.keys(Vnode).forEach((v) => {
this.colorCard.forEach((cor) => {
if (v.indexOf(cor.color) > -1) {
cor.colorPickSumList = [
...new Set([
...cor.colorPickSumList,
...[Vnode[v].backColorBack],
]),
]
}
})
})
return this.colorCard
},
},
watch: {},
created() {
this.contText = this.contText.replace(/\n/g, '\n\n')
},
mounted() { },
methods: {
getContText(e) {
if (e.target.innerHTML == 'x' && e.target.id == 'dot') {
console.log('删除方法')
var attrNode = $(event.target).parent()[0].attributes.attr.value
console.log(attrNode)
if (Vnode.hasOwnProperty(attrNode)) {
this.contText = this.contText.replace(
Vnode[attrNode].vvnode,
Vnode[attrNode].original
)
setTimeout(() => {
delete Vnode[attrNode]
}, 10)
}
this.colorCard.forEach((cor) => {
console.log(cor)
if (attrNode.indexOf(cor.color) > -1) {
let i = cor.colorPickSumList.findIndex( (find) => find === attrNode)cor.colorPickSumList.splice(i, 1)
}
})
return
}
var txt
txt = window.getSelection()
if (txt.toString().length > 1) {
this.domText = txt.toString()
} else return
this.conScrollTop = e.offsetY
childNodes = e.target.childNodes
this.hasSelectText =
childNodes &&
childNodes.length > 0 &&
childNodes[0].parentNode.parentNode.outerHTML
var vvnodeArr = Object.values(Vnode).map((m) => m.vvnode)
this.hasSelectTextFlag = vvnodeArr.includes(this.hasSelectText)
if (this.hasSelectTextFlag) {
console.log(
'抱歉您选中了,已标注选项,如果需要将已标注选中,需将标注选项删除!'
)
return
}
this.range = window.getSelection().getRangeAt(0)
this.startOffset = this.range.startOffset
this.endOffset = this.range.endOffset
},
// 复选框
checkHandler(cor) {
console.log(cor)
},
locationHandler(cor) {
var backColor = cor.color
console.log('----定位处理器-----')
var jumpArr = Object.keys(Vnode)
.map((m) => {
if (m.indexOf(backColor) > -1) return Vnode[m].jumpScrollTop
else return null
})
.filter((fil) => fil)
if (jumpArr.length === 0) return console.log('无需定位')
cor.index = cor.index >= jumpArr.length - 1 ? 0 : cor.index + 1
$('#contenttext')[0].scrollTop = jumpArr[cor.index]
},
// 设置样式处理器
colorHandler(cor) {
console.log(cor)
console.log('----色卡处理器-----')
var backColor = cor.color
if (this.hasSelectTextFlag) {
return this.$message({
showClose: true,
message:
'抱歉您选中了,已标注选项,如果需要将已标注选中,需将标注选项删除!',
center: true,
type: 'warning',
})
}
if (!this.domText) return
if (childNodes.length == 1) {
var nodeText = childNodes[0].textContent.trim()
var prefix = nodeText.substring(0, this.startOffset)
var middleText = nodeText.substring(
this.startOffset,
this.endOffset
)
var suffix = nodeText.substring(this.endOffset, nodeText.length)
//解决 \n样式会跑偏的的问题
var middleTextArr = middleText.split('\n').filter((fill) => fill)
var nIndex = middleText.indexOf('\n')
var nLastIndex = middleText.lastIndexOf('\n')
let obj = {}
let backColorBack = Vnode.hasOwnProperty(backColor)
? backColor + '@' + Object.values(Vnode).length: backColor
var middleTextArrNode = middleTextArr.map((o, i) => {
var n = ''
if (i === middleTextArr.length - 1) {
n = '<div class="picker_box"><div style="background:' + backColor + '" attr="' +backColorBack +'" class="box"><div class="box_con">' +o + '</div><span style="background:' +backColor +'" class="dot" id="dot">x</span></div></div>'
} else {
n = '<div class="picker_box"><div style="background:' +backColor +'" attr="' + backColorBack +'" class="box"><div class="box_con">' + o + '</div></div></div>'
}
return n
})
var middle = middleTextArrNode.join('\n\n')
obj['vvnode'] = middle
obj['original'] = this.domText
obj['backColorBack'] = backColorBack
obj['jumpScrollTop'] = +this.conScrollTop + 30
Vnode[backColorBack] = obj
if (nIndex === 0) {
middle = '\n' + middle
var noNIndexText = middleText.replace('\n', '')
var noNIndexTextIndex = noNIndexText.indexOf('\n')
if (noNIndexTextIndex === 0) {
middle = '\n' + middle
}
}
if (nLastIndex === middleText.length - 1) middle = middle + '\n'
//解决 \n样式会跑偏的的问题
this.contText = prefix + middle + suffix
}
if (childNodes.length > 1) {
if (this.range.startContainer == this.range.endContainer) {
for (var idx in childNodes) {
if (
childNodes[idx] == this.range.startContainer ||
childNodes[idx] == this.range.startContainer.parentNode
) {
var nodeText = childNodes[idx].textContent
var prefix = nodeText.substring(0, this.startOffset)
var middleText = nodeText.substring(
this.startOffset,
this.endOffset
)
var suffix = nodeText.substring(
this.endOffset,
nodeText.length
)
//解决 \n样式会跑偏的的问题
var middleTextArr = middleText.split('\n').filter((fill) => fill)
var nIndex = middleText.indexOf('\n')
var nLastIndex = middleText.lastIndexOf('\n')
let obj = {}
var backColorBack = Vnode.hasOwnProperty(backColor)
? backColor + '@' + Object.values(Vnode).length
: backColor
var middleTextArrNode = middleTextArr.map((o, i) => {
var n = ''
if (i === middleTextArr.length - 1) {
n = '<div class="picker_box"><div style="background:' +
backColor + '" attr="' +backColorBack + '" class="box"><div class="box_con">' + o + '</div><span style="background:' +
backColor +
'" class="dot" id="dot">x</span></div></div>'
} else {
n = '<div class="picker_box"><div style="background:' +
backColor + '" attr="' + backColorBack +
'" class="box"><div class="box_con">' + o + '</div></div></div>'
}
return n
})
var middle = middleTextArrNode.join('\n\n')
obj['vvnode'] = middle
obj['original'] = this.domText
obj['backColorBack'] = backColorBack
obj['jumpScrollTop'] = +this.conScrollTop + 30
Vnode[backColorBack] = obj
if (nIndex === 0) {
middle = '\n' + middle
var noNIndexText = middleText.replace('\n', '')
var noNIndexTextIndex = noNIndexText.indexOf('\n')
if (noNIndexTextIndex === 0) {
middle = '\n' + middle
}
}
if (nLastIndex === middleText.length - 1)
middle = middle + '\n'
//解决 \n样式会跑偏的的问题
$(childNodes[idx]).replaceWith(prefix + middle + suffix)
this.contText = $('#contenttext').html()
}
}
} else {
//多个span合并
var repalce_span = ''
this.$message({
showClose: true,
message:
'抱歉您选中了,已标注选项,如果需要将已标注选中,需将标注选项删除!',
center: true,
type: 'warning',
})
console.log( '抱歉您选中了,已标注选项,如果需要将已标注选中,需将标注选项删除!' )
return
}
}
// 计算当然色值设置的个数
Object.keys(Vnode).forEach((v) => {
this.colorCard.forEach((cor) => {
if (Vnode[v].backColorBack.indexOf(cor.color) > -1) {
cor.colorPickSumList = [
...new Set([
...cor.colorPickSumList,
...[Vnode[v].backColorBack],
]),
]
}
})
})
console.log(Vnode)
this.domText = ''
},
},
})
</script>
</html>