Vue + Rich-Text-Editor: Druckvorlagendesign

Vorwort:

Einige Projekte müssen gedruckt werden. Wenn nur wenige Stellen gedruckt werden müssen, müssen Sie im Allgemeinen nur die Vorlage zum Drucken korrigieren. Unsere Projekte sind jedoch immer unterschiedlich. Es ist klar, dass die Anforderungen erfüllt werden können, solange die Vorlage festgelegt ist. Das Hinzufügen einer flexiblen Druckvorlage, die auch das Ziehen und Ausfüllen von Text erfordert, tötet wirklich viele Gehirnzellen!

brauchen:

Die Front-End-Seite ist ein einfaches dreispaltiges Layout, wie in der folgenden Abbildung dargestellt. Im Grunde sieht es so aus: Im linken Rahmen befindet sich ein Suchfeld sowie der Inhalt, der in den Rich-Text-Editor gezogen werden muss In der Mitte befindet sich der Rich-Text, der zum Bearbeiten der Vorlage verwendet wird. Editor, auf der rechten Seite befinden sich verschiedene Einstellungen (die gleichen wie die echte ヽ(ー_ー)ノ,)

Die wichtigste Voraussetzung besteht darin, die Felder auf der linken Seite in den Rich-Text-Editor zu ziehen. Die Felder sind in Basisfelder und einige Tabellenfelder unterteilt. Da die Druckvorlage des Projekts hauptsächlich zum Bearbeiten verschiedener Arten von Druckdokumenten verwendet wird, ist sie nützlich. Es gibt viele Tabellen, und die Basisfelder können nur in andere Bereiche des Rich-Textes gezogen und nicht in der Tabelle platziert werden. Die Felder der Tabelle können nur in der Tabelle platziert werden und können nicht per Drag & Drop in andere Bereiche gezogen werden. (Hinweis: Für diese Art von Projektanforderungen ist es im Allgemeinen erforderlich, die Zielbeschriftung zum Ziehen und Ablegen zu bestimmen. Wenn es sich um diese Beschriftung handelt, platzieren Sie sie. Wenn nicht, geben Sie einfach die Eingabeaufforderung zurück.)

Ich werde nicht viel über das Frontend-Layout sagen. Ich glaube, dieses Layout ist für jeden ein Kinderspiel (┓(;´_`)┏)

Kerninhalt: Rich-Text-Bearbeitung zum Ausfüllen von Feldern per Drag-and-Drop

Vorbereitung: Version von Wangeditor v4 (ursprünglich hatte ich vor, die Version v5 zu verwenden. Ich habe beim Schreiben zuvor v4 für Experimente verwendet und dann vergessen, sie zu ändern, da es schwieriger ist, den Bearbeitungsteil des Editors entsprechend zu bedienen die Vorlageneinstellungen auf der rechten Seite. Ich bin zu faul, die Version zu ändern.)

Offizielle Website : Einführung · wangEditor-Benutzerdokumentation

Rendern von Drag-and-Drop-Feldern: Da der Rich-Text-Editor am Ende HTML-Fragmente enthält, die an anderen Stellen verwendet werden müssen, kann das Front-End die Daten nicht ausfüllen, wenn sie erneut verwendet werden. Daher lassen wir hier die Rückseite -end Füllen Sie die Daten aus. Wir verwenden das Backend, um die Daten einzugeben. Der zurückgegebene „Feldname“ und „Variablenname“ (vom Backend definiert und zum Abgleichen der Fülldaten verwendet) bearbeiten die Vorlage und zeigen sie an ist der „Feldname“ und die Drag-and-Drop-Füllung ist der „Variablenname“ (versteckt) (^_ −)☆.

Beispiel:

Es gibt noch einen weiteren wichtigen Punkt: Wie unterscheidet man beim Drag & Drop zwischen „Basisfeldern“ und „Tabellenfeldern“?

Die Methode, die ich hier verwende, besteht darin, beim Abrufen der Back-End-Daten eine Datenverarbeitung durchzuführen, da die vom Back-End bereitgestellten Daten separat sind.

Zum Beispiel: [{Basisfeld},{Stücklistenfeld},{Prozessfeld}...]

Daher wird bei der Datenverarbeitung dem „Basisfeld“ und den „anderen Feldern“ eine Kennung hinzugefügt, um zu unterscheiden, welches Feld gezogen wird. Das Basisfeld wird hinzugefügt: Quellfeld, die anderen Felder werden hinzugefügt: Stückliste und schließlich Dieses Logo wird in den Klassennamen des Drag-Elements gerendert: class=source-field (speziell im Bild oben gezeigt)

     async searchList(){
       let data=this.listQuery
      // 模板字段以及模糊查询
        await templateField(data).then(res=>{
         let datas=[]
         for (const key in res.data) {
               datas.push({name:key,every:res.data[key]})
         }
         let m=[]
         datas.forEach(item=>{
           if(item.name.includes('基础信息字段')){
            item.every.forEach((item,index)=>{
               item.class='source-field'  //添加标识
               item.id=index+1
            })
             m.unshift(item)
           }else{
            item.every.forEach((item,index)=>{
               item.class='BOM'     //添加标识
               item.id=index+1
            })
            m.push(item)
           }
        })
         this.fieldList=m
         })
      },

Nachdem das Feld gerendert wurde, wird es durch Ziehen gefüllt:

Zu den gängigen Drag-and-Drop-Füllungen gehören: h5 native Drag-and-SortableJS usw.

h5 Drag & Drop: HTML5 Drag & Drop

sortablejs- Website: Sortable.js chinesische Website

Zuerst habe ich sortablejs zum Ziehen und Ablegen verwendet. Schließlich stellte ich fest, dass der Text des gezogenen Elements nicht im Rich-Text-Editor platziert werden konnte, da die Kapselung von sortablejs und die Kapselung des Rich-Text-Editors in Konflikt zu stehen schienen Ich musste aufgeben. Nach langer Zeit gab ich schließlich auf (╬◣д◢)) und verwendete schließlich natives Ziehen. Natives Ziehen muss zur Bezeichnung hinzugefügt werden: Draggable = True, was bedeutet, dass Ziehen ausgeführt werden kann. Native Drag hat auch Veranstaltungen. Ich werde hier nicht auf Details eingehen, Sie können sich die offizielle Website ansehen.

 Da wir Text per Drag-and-Drop verschieben müssen, müssen wir die Daten hier verarbeiten und in das vom Backend benötigte Format zusammenfügen.

Grundlegende Feldfüllung: Beispiel: Bestellnummer: {$orderNumber}

Ausfüllen von Tabellenfeldern: Beispiel: {$orderNumber}

Das native Drag-Ereignis, das wir derzeit verwenden, ist: Wenn das Ziehen beginnt: @dragstart="onDragStart"

   onDragStart(event) {
         let flag=event.target.classList.contains('source-field')
         let BOM=event.target.classList.contains('BOM')
         event.dataTransfer.setData("flag",flag)
         event.dataTransfer.setData("BOM",BOM)
         let text=event.target.innerText
         let children= event.target.children[0].innerText
         // 判断数据拼接的方式
         if(flag){
            this.itemText = text+':${'+children+'}';
            this.$refs.editor.getItemText(this.itemText)
         }
         if(BOM) {
           this.itemText = '${'+children+'}';
           this.$refs.editor.getItemText(this.itemText)
         }
      },

Wenn wir ein Ereignis auslösen, bestimmen wir, welches Element das Ereignis auslöst (e.target)
1. Bestimmen Sie den Inhalt innerHTML innerText
2. Tag-Name nodeName (bei der Beurteilung muss der Tag-Name großgeschrieben werden)
3. Attribut e.target.hasAttribute ("Attributname"); wenn es wahr ist, ist es falsch, wenn es nicht
4 ist. Klassenname e.target.classList.contains("Klassenname"); wenn es wahr ist, wenn nicht, ist es falsch


Der Klassenname, den wir hier beurteilen: Weil wir anhand der Kennung, die ich bei der Verarbeitung der Daten zuvor hinzugefügt habe, beurteilen müssen, welches Feld gezogen wird, und entscheiden müssen, welche Art von Spleißmethode der Text platziert werden soll (wie im obigen Code gezeigt).

 Gleichzeitig fügen wir dem Ereignisobjekt basierend auf der Beurteilung eine Kennung hinzu, die später zur Bestimmung des Platzierungsorts verwendet wird (da die Felder des Anforderungsformulars nur im Formular platziert werden können und die Basisfelder nicht im Formular platziert werden können). Formular). An diesem Punkt ist das Ziehen im Wesentlichen abgeschlossen und der nächste Schritt ist die Platzierung; ❥(ゝω・✿ฺ)

 Hier müssen wir zu der mit Rich-Text-Bearbeitung geschriebenen Komponente gehen und die Überwachung verwenden, um Drag-and-Drop-Ereignisse zu überwachen: drgover und drop. Drgover muss das Standardereignis blockieren.

 // 监听拖放事件
       this.$refs.editor.addEventListener("dragover", this.onDragOver);
       this.$refs.editor.addEventListener("drop", this.onDrop);

 // 拖放事件
      onDragOver(event) {
         event.preventDefault();
      },
      // 拖放事件
      onDrop(event) {
         event.preventDefault();
         let Td=event.target.tagName
         let flag=event.dataTransfer.getData('flag')
         let BOM=event.dataTransfer.getData('BOM')

         // 判断基础信息字段不能拖动到表格中
         if (flag==='true') {
            if (flag==='true'&&Td=='TD'||flag==='true'&&Td=='TH') {
               this.$message.error('基础信息字段不能拖动到表格中');
             return
            }
             this.fillUp()
         }

        // 判断子列表信息只能放在表格中
         if (BOM==='true') {
            if (BOM==='true'&&Td=='TD') {
              this.fillUp()
              return
            } 
            this.$message.error('子列表字段只能拖拽到表格中,请先创建表格');
         }
      },
      // 富文本编辑器内容填充方法
      fillUp(){
           const selection = window.getSelection();
           let k=selection.anchorNode
           console.log(k.parentNode.tagName);
        //    console.log(k);
           if(!k.tagName&&k.parentNode.tagName!=='P'&&k.parentNode.tagName!=='SPAN'&&k!=='#text'&&k.parentNode.tagName!=='FONT'&&k.parentNode.tagName!=='B'){
                this.$message.error('拖放位置已有内容!');
           };

           if(k.tagName==='P'||k.parentNode.tagName==='P'||k.tagName==='TH'||k.tagName=='TD'||k=='#text'
              ||k.parentNode.tagName=='SPAN'||k.parentNode.tagName==='FONT'||k.parentNode.tagName=='B'){
              const range = selection.getRangeAt(0);
              const text = this.itemText;
              const node = document.createTextNode(text);
              range.deleteContents();
              range.insertNode(node);
            }
      },

Hier schauen wir uns zunächst die [Methode zum Füllen von Rich-Text-Editor-Inhalten] im obigen Code an.

window.getSelection() gibt ein Selection-Objekt zurück, das den vom Benutzer ausgewählten Textbereich oder die Position des Cursors darstellt.

Hier verwenden wir das Attribut des Auswahlobjekts: AnchorNode (gibt den Knoten zurück, an dem sich der Startpunkt der Auswahl befindet), um den Knoten an der Cursorposition abzurufen. Hier verwende ich es, um zu bestimmen, ob die Drag-and-Drop-Position Inhalt hat, denn wenn das Original ist Wenn Text in der Tabelle ausgewählt wird, wird der Stil der Tabelle beim Ziehen und Ablegen verwechselt. Daher wird hier ein Block erstellt, der nur platziert werden kann, wenn kein Text vorhanden ist.

Beim Platzieren müssen wir die getRangeAt-Methode verwenden, um den Knoten zurückzugeben, an dem die Auswahl beginnt. Da der Benutzer normalerweise nur einen Bereich auswählen kann, gibt es nur eine Auswahl, daher lautet diese Methode im Allgemeinen: getRangeAt(0)

Nachdem Sie den Knoten zurückgegeben haben, müssen Sie den ursprünglichen Drag-and-Drop-Text this.itemText abrufen, einen Knoten basierend auf dem Drag-and-Drop-Text erstellen und dann die Methode deleteContents() verwenden, um den gesamten Inhalt des ausgewählten Bereichs aus dem Dokumentbaum zu löschen , und fügen Sie dann den erstellten Knoten in den zuvor zurückgegebenen Knoten ein; an diesem Punkt haben wir das Ausfüllen per Drag-and-Drop in der Rich-Text-Bearbeitung abgeschlossen; (๑>ڡ<)☆

Ausführliche Erklärung von window.getSelection(): Über window.getSelection_xiao xus Blog-CSDN-Blog

Nachdem die Rich-Text-Ausfüllung abgeschlossen ist, müssen wir nun die Position des Feldes per Drag & Drop bestimmen.

         event.preventDefault();
         let Td=event.target.tagName
         let flag=event.dataTransfer.getData('flag')
         let BOM=event.dataTransfer.getData('BOM')

         // 判断基础信息字段不能拖动到表格中
         if (flag==='true') {
            if (flag==='true'&&Td=='TD'||flag==='true'&&Td=='TH') {
               this.$message.error('基础信息字段不能拖动到表格中');
             return
            }
             this.fillUp()
         }

        // 判断子列表信息只能放在表格中
         if (BOM==='true') {
            if (BOM==='true'&&Td=='TD') {
              this.fillUp()
              return
            } 
            this.$message.error('子列表字段只能拖拽到表格中,请先创建表格');
         }

Der obige Code ist Teil des Drag-and-Drop-Ereignisses. Der vollständige Code ist oben.

Stellen Sie zunächst fest, dass die Basisfelder nicht in die Tabelle eingefügt werden können:

Da das Tag, das wir schließlich in die Tabelle eingefügt haben, <td></td> ist, müssen wir hier den tagNamen des Zieltags abrufen und dann das Logo verwenden, um das Basisfeld und das Tabellenfeld zu unterscheiden, bevor wir es erhalten Der Hauptzweck besteht darin, das Logo zur Beurteilung zu verwenden. Wenn die Identifizierung des Basisfelds wahr ist und der tagName des Ziel-Tags TD ist, wird in einem Popup-Fenster Folgendes angezeigt: „Das Basisfeld kann nicht in die Tabelle gezogen werden“ und Rückkehr, andernfalls wird die Rich-Text-Füllmethode aufgerufen.

Die Methode zur Beurteilung, ob Tabellenfelder nur in der Tabelle platziert werden können, ist dieselbe wie oben. Einzelheiten finden Sie im Code, der hier weggelassen wird ❥(ゝω・✿ฺ)

Endlich: Zu diesem Zeitpunkt ist die gesamte Kernbeschreibung abgeschlossen. Viele Details werden möglicherweise nicht erwähnt (z. B. Vorlageneinstellungen zur Steuerung des Bearbeitungsbereichs), da ich auch den Fluss überquere, indem ich die Steine ​​​​erfühle, und es viele Tage gedauert hat um es zu schreiben. Wenn etwas nicht stimmt, hoffe ich, dass mir jeder helfen kann. Bitte korrigieren Sie mich, wenn es Ihnen nicht gefällt, danke! Ich werde später auch über die Verwendung von Bearbeitungsvorlagen schreiben, was ein weiteres großes Problem darstellt (beim Drucken) (⌒.−)=★

Je suppose que tu aimes

Origine blog.csdn.net/Xhfc_pf1996/article/details/130383986
conseillé
Classement