初始化项目
This commit is contained in:
24
README.md
Normal file
24
README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# projectnew
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
17
public/index.html
Normal file
17
public/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
36
src/App.vue
Normal file
36
src/App.vue
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
|
||||||
|
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import HelloWorld from './components/vditor2Bd.vue'
|
||||||
|
// import HelloWorld from './components/homePage3.vue'
|
||||||
|
// import HelloWorld from './components/quill.vue'
|
||||||
|
// import HelloWorld from './components/tinyMCE.vue'
|
||||||
|
// import HelloWorld from './components/vditor.vue'
|
||||||
|
// import HelloWorld from './components/wang.vue'
|
||||||
|
import HelloWorld from './components/XMLwang.vue'
|
||||||
|
// import HelloWorld from './components/vditor2.vue'
|
||||||
|
// import HelloWorld from './components/ueditor.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
components: {
|
||||||
|
HelloWorld,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#app {
|
||||||
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: center;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
286
src/assets/quill_table .css
Normal file
286
src/assets/quill_table .css
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
.ql-editor table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-editor table td {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 5px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-formats button.ql-table::after,
|
||||||
|
.ql-formats .ql-picker.ql-table .ql-picker-label::before {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-label::before {
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABcSURBVEhL3YsxDgBACML8/6fvNhd0aGCyCUuBOsULR5hGToStSHl8oB4fqMcH6rtIRZhGToStSHl8oB4fqMcH6rtIRZhGToStSHl8oB4fqMcH6rtIRZhGTk5Q9QFCcv8BMZAsCwAAAABJRU5ErkJggg==');
|
||||||
|
}
|
||||||
|
|
||||||
|
button.ql-table[value="append-row"]::after {
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAC5SURBVEhL7ZNBCsIwFERzKxceQHGjqLcSFMHzKOpN1BOIe53BDgxJCjbRlX3woJnf/F9KEnq6MIE3+KyUPcYw4QpzG0q8wAQVa2nt0w8QfzpgCU/w0XiEc5ij84ANVC2WtRjVEuKLtoP8cs+EZzO4jbLsReP1ZkEvDeHZ1lR4doADW7PHCH4E/zc3tcHa/f1Yxs8H8LSwiRSe7RmUsoDeTHg2ZVDDGnpDdwW/Ao8iT4suGp+Z9dQSwgttSY+8S9IcOwAAAABJRU5ErkJggg==');
|
||||||
|
}
|
||||||
|
|
||||||
|
button.ql-table[value="append-col"] {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.ql-table[value="append-col"]::after {
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADXSURBVEhL3ZVLCsJADIbnVi48gOJGUW8lqCuPo6g3UU8g7vX/GQMhnUdmUZR+8MGQyaOUlIbBMYMP+K7InCls5g5TDVPeYDNSXMOb1+FvBuzhKB7b8A5Ywwt8fT3DJaziGbCDkmflXRFJzMEn1w0FHVswkMMWWq5QNxN07MRADlto4fsu3fPuGY9pfj6A2yI5Ok/HjgzksIWWFdTNBB2bM5DDFqbYQt1Qu4FFJLEGV5HbIh8az8X1FLwDDnAcj214B3jzOvQ+oPcfDn+DLEw11DJnAgdPCB8kS4+90nxt3AAAAABJRU5ErkJggg==');
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-table,
|
||||||
|
.ql-contain {
|
||||||
|
width: auto !important;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table svg {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-label {
|
||||||
|
padding: 2px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-options {
|
||||||
|
width: 178px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-item {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-item {
|
||||||
|
border: 1px solid #444;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-table .ql-picker-item:hover {
|
||||||
|
border-color: #06c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item:nth-child(5):before {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_1_1]:before {
|
||||||
|
content: "1x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_1_2]:before {
|
||||||
|
content: "1x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_1_3]:before {
|
||||||
|
content: "1x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_1_4]:before {
|
||||||
|
content: "1x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_1_5]:before {
|
||||||
|
content: "1x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_2_1]:before {
|
||||||
|
content: "2x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_2_2]:before {
|
||||||
|
content: "2x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_2_3]:before {
|
||||||
|
content: "2x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_2_4]:before {
|
||||||
|
content: "2x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_2_5]:before {
|
||||||
|
content: "2x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_3_1]:before {
|
||||||
|
content: "3x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_3_2]:before {
|
||||||
|
content: "3x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_3_3]:before {
|
||||||
|
content: "3x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_3_4]:before {
|
||||||
|
content: "3x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_3_5]:before {
|
||||||
|
content: "3x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_4_1]:before {
|
||||||
|
content: "4x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_4_2]:before {
|
||||||
|
content: "4x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_4_3]:before {
|
||||||
|
content: "4x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_4_4]:before {
|
||||||
|
content: "4x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_4_5]:before {
|
||||||
|
content: "4x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_5_1]:before {
|
||||||
|
content: "5x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_5_2]:before {
|
||||||
|
content: "5x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_5_3]:before {
|
||||||
|
content: "5x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_5_4]:before {
|
||||||
|
content: "5x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_5_5]:before {
|
||||||
|
content: "5x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_6_1]:before {
|
||||||
|
content: "6x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_6_2]:before {
|
||||||
|
content: "6x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_6_3]:before {
|
||||||
|
content: "6x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_6_4]:before {
|
||||||
|
content: "6x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_6_5]:before {
|
||||||
|
content: "6x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_7_1]:before {
|
||||||
|
content: "7x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_7_2]:before {
|
||||||
|
content: "7x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_7_3]:before {
|
||||||
|
content: "7x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_7_4]:before {
|
||||||
|
content: "7x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_7_5]:before {
|
||||||
|
content: "7x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_8_1]:before {
|
||||||
|
content: "8x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_8_2]:before {
|
||||||
|
content: "8x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_8_3]:before {
|
||||||
|
content: "8x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_8_4]:before {
|
||||||
|
content: "8x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_8_5]:before {
|
||||||
|
content: "8x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_9_1]:before {
|
||||||
|
content: "9x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_9_2]:before {
|
||||||
|
content: "9x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_9_3]:before {
|
||||||
|
content: "9x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_9_4]:before {
|
||||||
|
content: "9x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_9_5]:before {
|
||||||
|
content: "9x5";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_10_1]:before {
|
||||||
|
content: "10x1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_10_2]:before {
|
||||||
|
content: "10x2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_10_3]:before {
|
||||||
|
content: "10x3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_10_4]:before {
|
||||||
|
content: "10x4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker-item[data-value=newtable_10_5]:before {
|
||||||
|
content: "10x5";
|
||||||
|
}
|
||||||
421
src/components/wang.vue
Normal file
421
src/components/wang.vue
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
<template>
|
||||||
|
<div class="editor-container">
|
||||||
|
<div class="toolbar">
|
||||||
|
<button @click="insertImage">上传图片</button>
|
||||||
|
<button @click="insertVideo">上传视频</button>
|
||||||
|
<button @click="loadAllContent">加载所有内容</button>
|
||||||
|
<button @click="generateTOC">生成目录</button>
|
||||||
|
<button @click="deleteAllVideos">删除所有视频</button>
|
||||||
|
<button @click="loadFwb">模拟加载</button>
|
||||||
|
<button @click='test'>测试</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="main" class="content-preview"></div>
|
||||||
|
<div id="nav" class="toc-container"></div>
|
||||||
|
<div id="editor" ref="editor"></div>
|
||||||
|
<div id="editor2" ref="editor2"></div>
|
||||||
|
<!-- <button @click="callWpfMethod">调用WPF方法</button> -->
|
||||||
|
<input type="text" v-model="val1">
|
||||||
|
<input type="text" v-model="val2">
|
||||||
|
<button @click="sendMessageToHost('李四','张三')">传递</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WangEditor from 'wangeditor'
|
||||||
|
// import axios from 'axios';
|
||||||
|
// window.handleMessageFromDotNet = function(msg) {
|
||||||
|
// alert("Received message from C#: " + msg);
|
||||||
|
// }
|
||||||
|
export default {
|
||||||
|
name: 'RichTextEditor',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
val1:'',
|
||||||
|
val2:'',
|
||||||
|
wpfData: '',
|
||||||
|
message: '',
|
||||||
|
editor: null,
|
||||||
|
editor2:null,
|
||||||
|
editorContent: '',
|
||||||
|
editorContent2:'',
|
||||||
|
hasVideoSelected: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initEditor()
|
||||||
|
// this.initEditor2();
|
||||||
|
// window.receiveMessageFromWpf = this.receiveMessageFromWpf;
|
||||||
|
|
||||||
|
console.log('chrome对象是否存在:', !!window.chrome);
|
||||||
|
console.log('webview对象是否存在:', !!window.chrome?.webview);
|
||||||
|
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 销毁编辑器
|
||||||
|
if (this.editor) {
|
||||||
|
this.editor.destroy()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
test() {
|
||||||
|
|
||||||
|
},
|
||||||
|
sendMessageToHost() {
|
||||||
|
this.$sendToDotNet(this.val1,this.val2);
|
||||||
|
|
||||||
|
},
|
||||||
|
loadFwb() {
|
||||||
|
this.editor2.txt.html(this.editorContent)
|
||||||
|
|
||||||
|
// 创建编辑器
|
||||||
|
|
||||||
|
},
|
||||||
|
initEditor() {
|
||||||
|
this.editor = new WangEditor(this.$refs.editor)
|
||||||
|
|
||||||
|
// 配置编辑器
|
||||||
|
this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
|
||||||
|
this.editor.config.onchange = (html) => {
|
||||||
|
this.editorContent = html
|
||||||
|
}
|
||||||
|
let dm = this.editor.config.menus;
|
||||||
|
console.log("默认菜单",dm)
|
||||||
|
|
||||||
|
// 完全自定义菜单
|
||||||
|
this.editor.config.menus = [
|
||||||
|
'image', // 图片
|
||||||
|
'video', // 视频
|
||||||
|
'head', // 标题
|
||||||
|
'bold', // 粗体
|
||||||
|
// 'fontSize',//字号
|
||||||
|
// 'fontName',//字体
|
||||||
|
'italic', // 斜体
|
||||||
|
'underline', // 下划线
|
||||||
|
'strikeThrough', // 删除线
|
||||||
|
// 'line',//行高
|
||||||
|
'lineHeight',//
|
||||||
|
// 'foreColor', // 文字颜色
|
||||||
|
// 'backColor', // 背景颜色
|
||||||
|
// 'link', // 链接
|
||||||
|
'list', // 列表
|
||||||
|
// 'todo',//
|
||||||
|
'justify', // 对齐方式
|
||||||
|
// 'quote', // 引用
|
||||||
|
// 'emoticon',//表情
|
||||||
|
'table', // 表格
|
||||||
|
// 'code', // 代码
|
||||||
|
'splitLine',//分割线
|
||||||
|
'undo', // 撤销
|
||||||
|
'redo' // 重做
|
||||||
|
]
|
||||||
|
|
||||||
|
// 创建编辑器
|
||||||
|
this.editor.create();
|
||||||
|
|
||||||
|
|
||||||
|
this.editor2 = new WangEditor(this.$refs.editor2)
|
||||||
|
|
||||||
|
// 配置编辑器
|
||||||
|
this.editor2.config.uploadImgShowBase64 = true // 使用 base64 保存图片
|
||||||
|
this.editor2.config.onchange = (html) => {
|
||||||
|
console.log("22222",html)
|
||||||
|
// this.editorContent2 = html
|
||||||
|
}
|
||||||
|
this.editor2.create()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// 上传图片
|
||||||
|
insertImage() {
|
||||||
|
const imgUrl = 'http://youneed.top:10017/uploads/1.jpg'
|
||||||
|
this.editor.cmd.do('insertHTML', `<img src="${imgUrl}" style="max-width: 100%;" alt="图片">`)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 插入视频(可靠版本)
|
||||||
|
insertVideo() {
|
||||||
|
const videoUrl = 'http://youneed.top:10017/uploads/video.mp4'
|
||||||
|
const videoId = `video-${Date.now()}`
|
||||||
|
|
||||||
|
// 创建视频HTML
|
||||||
|
const videoHtml = `
|
||||||
|
<div class="video-wrapper" data-video-id="${videoId}">
|
||||||
|
<video controls width="50%" style='margin:auto' data-video-id="${videoId}">
|
||||||
|
<source src="${videoUrl}" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
<div class="video-controls" style='display:none;'>
|
||||||
|
<span class="video-delete" data-video-id="${videoId}">× 删除</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p><br></p>
|
||||||
|
`
|
||||||
|
|
||||||
|
// 使用编辑器命令插入
|
||||||
|
this.editor.cmd.do('insertHTML', videoHtml)
|
||||||
|
|
||||||
|
// 添加删除事件监听
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const btn = document.querySelector(`button[data-video-id="${videoId}"]`)
|
||||||
|
if (btn) {
|
||||||
|
btn.onclick = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.deleteVideoById(videoId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 根据ID删除视频(修正版)
|
||||||
|
deleteVideoById(videoId) {
|
||||||
|
const container = document.querySelector(`.video-container[data-video-id="${videoId}"]`)
|
||||||
|
if (container) {
|
||||||
|
container.remove()
|
||||||
|
this.editor.txt.html(this.editor.txt.html()) // 刷新编辑器
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
bindDel(){
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
deleteAllVideos() {
|
||||||
|
const videoWrappers = document.querySelectorAll('.video-wrapper')
|
||||||
|
if (videoWrappers.length === 0) {
|
||||||
|
alert('没有找到可删除的视频')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
videoWrappers.forEach(wrapper => {
|
||||||
|
wrapper.remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 删除可能残留的空段落
|
||||||
|
const editor = this.$refs.editor
|
||||||
|
const paragraphs = editor.querySelectorAll('p')
|
||||||
|
paragraphs.forEach(p => {
|
||||||
|
if (p.textContent.trim() === '' && p.children.length === 0) {
|
||||||
|
p.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 修正:使用正确的方式通知内容变更
|
||||||
|
if (this.editor.txt) {
|
||||||
|
this.editor.txt.html(this.editor.txt.html()) // 强制更新编辑器内容
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`已删除 ${videoWrappers.length} 个视频`)
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 加载所有内容到 main 容器
|
||||||
|
loadAllContent() {
|
||||||
|
const mainContainer = document.getElementById('main')
|
||||||
|
mainContainer.innerHTML = this.editorContent;
|
||||||
|
console.log("this.editorContent",this.editorContent)
|
||||||
|
// 为main容器中的标题添加ID
|
||||||
|
this.addHeadingIds(mainContainer)
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// 为标题元素添加ID
|
||||||
|
addHeadingIds(container) {
|
||||||
|
const headings = container.querySelectorAll('h1, h2, h3, h4, h5, h6')
|
||||||
|
headings.forEach((heading, index) => {
|
||||||
|
if (!heading.id) {
|
||||||
|
heading.id = `heading-${index}-${Date.now()}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 生成带锚点的目录
|
||||||
|
generateTOC() {
|
||||||
|
const navContainer = document.getElementById('nav')
|
||||||
|
navContainer.innerHTML = '' // 清空原有目录
|
||||||
|
|
||||||
|
// 确保main容器已加载内容
|
||||||
|
if (!document.getElementById('main').innerHTML) {
|
||||||
|
this.loadAllContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainContainer = document.getElementById('main')
|
||||||
|
const headings = mainContainer.querySelectorAll('h1, h2, h3, h4, h5, h6')
|
||||||
|
|
||||||
|
if (headings.length === 0) {
|
||||||
|
navContainer.innerHTML = '<p>没有找到标题元素,无法生成目录。</p>'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const tocList = document.createElement('ul')
|
||||||
|
tocList.style.listStyleType = 'none'
|
||||||
|
tocList.style.paddingLeft = '0'
|
||||||
|
|
||||||
|
headings.forEach(heading => {
|
||||||
|
const level = parseInt(heading.tagName.substring(1))
|
||||||
|
const listItem = document.createElement('li')
|
||||||
|
listItem.style.marginLeft = `${(level - 1) * 15}px`
|
||||||
|
listItem.style.marginBottom = '5px'
|
||||||
|
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = `#${heading.id}`
|
||||||
|
link.textContent = heading.textContent
|
||||||
|
link.style.textDecoration = 'none'
|
||||||
|
link.style.color = '#333'
|
||||||
|
|
||||||
|
// 添加平滑滚动效果
|
||||||
|
link.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
document.getElementById(heading.id).scrollIntoView({
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
listItem.appendChild(link)
|
||||||
|
tocList.appendChild(listItem)
|
||||||
|
})
|
||||||
|
|
||||||
|
const tocContainer = document.createElement('div')
|
||||||
|
tocContainer.style.border = '1px solid #ddd'
|
||||||
|
tocContainer.style.padding = '15px'
|
||||||
|
tocContainer.style.marginBottom = '20px'
|
||||||
|
tocContainer.style.background = '#f9f9f9'
|
||||||
|
tocContainer.style.borderRadius = '4px'
|
||||||
|
|
||||||
|
const tocTitle = document.createElement('h2')
|
||||||
|
tocTitle.textContent = '目录'
|
||||||
|
tocTitle.style.marginTop = '0'
|
||||||
|
|
||||||
|
tocContainer.appendChild(tocTitle)
|
||||||
|
tocContainer.appendChild(tocList)
|
||||||
|
navContainer.appendChild(tocContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// 方式1:直接访问全局变量
|
||||||
|
this.$watch(
|
||||||
|
() => this.$dotNetMessage,
|
||||||
|
(newMsg) => {
|
||||||
|
console.log('收到消息:', newMsg)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 方式2:监听全局事件
|
||||||
|
window.addEventListener('dotnet-message', (e) => {
|
||||||
|
console.log('通过事件收到:', e.detail)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.editor-container {
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar button {
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #409eff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar button:hover {
|
||||||
|
background: #66b1ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor,#editor2 {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
min-height: 300px;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-preview {
|
||||||
|
margin-top: 20px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
padding: 15px;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
#main th,
|
||||||
|
#main td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
#main th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 视频容器样式 */
|
||||||
|
.video-wrapper {
|
||||||
|
position: relative;
|
||||||
|
margin: 15px 0;
|
||||||
|
/* border: 1px solid #ddd; */
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-controls {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-delete {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 8px;
|
||||||
|
background: rgba(255, 0, 0, 0.7);
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-delete:hover {
|
||||||
|
background: rgba(255, 0, 0, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 确保视频响应式 */
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
/* 禁用菜单项样式 */
|
||||||
|
.disabled-menu-item {
|
||||||
|
opacity: 0.5 !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 如果需要工具提示也禁用 */
|
||||||
|
.w-e-toolbar .w-e-menu:nth-child(1),
|
||||||
|
.w-e-toolbar .w-e-menu:nth-child(2) {
|
||||||
|
/* background-color:#096; */
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
55
src/main.js
Normal file
55
src/main.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
Vue.prototype.$axios = axios;
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
// axios.defaults.baseURL = 'http://localhost:3000';
|
||||||
|
axios.defaults.baseURL = 'http://192.168.31.181:3000';
|
||||||
|
// axios.defaults.baseURL = 'https://api.example.com';
|
||||||
|
|
||||||
|
// 可以在此处配置请求头、超时等
|
||||||
|
axios.defaults.headers.common['Authorization'] = 'Bearer token';
|
||||||
|
axios.defaults.timeout = 10000;
|
||||||
|
|
||||||
|
|
||||||
|
window.handleMessageFromDotNet = function(msg) {
|
||||||
|
Vue.prototype.$dotNetMessage = msg
|
||||||
|
// 可以触发全局事件
|
||||||
|
const event = new CustomEvent('dotnet-message', { detail: msg })
|
||||||
|
window.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const sendToDotNet = (type, payload) => {
|
||||||
|
if (!window.chrome?.webview?.postMessage) {
|
||||||
|
console.error('WebView2 环境未就绪!当前环境:', window.chrome ? '有chrome对象' : '无chrome对象');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// const message = JSON.stringify(type, payload)
|
||||||
|
// console.log("开始给C#发送的信息",message)
|
||||||
|
|
||||||
|
let message = {
|
||||||
|
// 'Type':'',
|
||||||
|
'Payload':payload
|
||||||
|
}
|
||||||
|
console.log("传参",message,JSON.stringify(message))
|
||||||
|
window.chrome.webview.postMessage(message)
|
||||||
|
// if (window.chrome?.webview?.postMessage) {
|
||||||
|
// const message = JSON.stringify({ type, payload })
|
||||||
|
// console.log("开始给C#发送的信息",message)
|
||||||
|
// window.chrome.webview.postMessage(message)
|
||||||
|
// } else {
|
||||||
|
// console.warn('WebView2环境未就绪')
|
||||||
|
// // 可选:开发环境模拟
|
||||||
|
// if (process.env.NODE_ENV === 'development') {
|
||||||
|
// console.log('[模拟发送]', { type, payload })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.prototype.$sendToDotNet = sendToDotNet
|
||||||
|
new Vue({
|
||||||
|
render: h => h(App),
|
||||||
|
}).$mount('#app')
|
||||||
18
vue.config.js
Normal file
18
vue.config.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const { defineConfig } = require('@vue/cli-service')
|
||||||
|
module.exports = defineConfig({
|
||||||
|
transpileDependencies: true
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devServer: {
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://youneed.top:10017',
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
'^/api': ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user