liyongli il y a 1 an
Parent
commit
d8725b161d
5 fichiers modifiés avec 1253 ajouts et 1 suppressions
  1. 1 1
      src/api/index.js
  2. 2 0
      src/router/index.js
  3. 17 0
      src/router/task.js
  4. 456 0
      src/view/task/convergence.vue
  5. 777 0
      src/view/task/onlineText.vue

+ 1 - 1
src/api/index.js

@@ -314,7 +314,7 @@ export function getAccountList(ori) {
     type: 'ajax',
     method: 'POST',
     headers: {
-      Authorization: localStorage.getItem('token'),
+      Authorization: ori.token || localStorage.getItem('token'),
     },
   });
 }

+ 2 - 0
src/router/index.js

@@ -2,6 +2,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
 
 import allMedia from "./allMedia";
 import easyDiffusion from "./easyDiffusion";
+import task from "./task";
 
 import NotFound from "../errorPage/404.vue";
 
@@ -24,6 +25,7 @@ const router = createRouter({
     },
     ...allMedia,
     ...easyDiffusion,
+    ...task,
     {
         path: "/:pathMatch(.*)*",
         name: "NotFound",

+ 17 - 0
src/router/task.js

@@ -0,0 +1,17 @@
+export default [
+    {
+      path: '/Task',
+      name: 'Task',
+      component: () =>
+        import(/* webpackChunkName: "Task" */ '../view/task/onlineText.vue'),
+    },
+    {
+      path: '/Task_convergence',
+      name: 'Task_convergence',
+      component: () =>
+        import(
+          /* webpackChunkName: "Task" */ '../view/task/convergence.vue'
+        ),
+    },
+  ];
+  

+ 456 - 0
src/view/task/convergence.vue

@@ -0,0 +1,456 @@
+<template>
+  <div>
+    <header_local />
+    <div class="convergence">
+      <el-form :inline="true" :model="condition" size="large">
+        <el-form-item prop="platform">
+          <el-button
+            v-for="(item, index) in btns"
+            :class="{
+              [item.platform]: true,
+              [item.platform + '_active']: condition.platform === index,
+            }"
+            :key="item.id"
+            @click="() => selectPlatform(item, index)"
+          >
+            <span
+              :class="{ icon: true, iconfont: true, [item.class]: true }"
+              style="margin-right: 5px"
+            >
+            </span>
+            {{ item.text }}
+          </el-button>
+        </el-form-item>
+        <br />
+        <el-form-item label="日期" prop="dt">
+          <el-date-picker
+            v-model="condition.dt"
+            type="daterange"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+          />
+        </el-form-item>
+        <el-form-item label="关键词" prop="keyword">
+          <el-input v-model="condition.keyword" clearable placeholder="请输入关键词" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">查询</el-button>
+          <el-button type="primary" @click="onExport">导出</el-button>
+          <el-button type="primary" @click="binding">绑定账号</el-button>
+        </el-form-item>
+      </el-form>
+      <br />
+      <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+        <el-tab-pane label="传播数据" name="T1">
+          <el-table
+            :data="disseminateData.list"
+            style="width: 100%"
+            :header-cell-style="{
+              backgroundColor: '#f4f5f7',
+              color: '#606266',
+            }"
+            ref="table1"
+            align="center"
+            empty-text="暂无数据"
+            @sort-change="e => sort_change(e, 'disseminate')"
+          >
+              <el-table-column
+                align="center"
+                :width="item.width"
+              v-for="(item, i) in config.tableCol.agg[
+                btns[condition.platform].text
+              ]"
+              :key="i"
+                show-overflow-tooltip
+                :prop="item.key"
+                :label="item.label"
+                :sortable="item.sortable"
+                :sort-orders="
+                  item.sortable ? ['ascending', 'descending', null] : []
+                "
+              >
+                <template #default="scope">
+                  {{
+                    item.type == 'number'
+                      ? formatter(scope.row[item.key])
+                      : scope.row[item.key]
+                  }}
+                </template>
+              </el-table-column>
+          </el-table>
+          <el-pagination
+            @current-change="e => changePageDisseminate(e)"
+            background
+            layout="prev, pager, next"
+            :page-count="
+              Math.ceil(disseminateData.total / condition.disseminate.size) || 1
+            "
+          />
+        </el-tab-pane>
+        <el-tab-pane label="稿件数据" name="T2">
+          <el-table
+            :data="manuscriptData.list"
+            style="width: 100%"
+            :header-cell-style="{
+              backgroundColor: '#f4f5f7',
+              color: '#606266',
+            }"
+            ref="table1"
+            align="center"
+            empty-text="暂无数据"
+            @sort-change="e => sort_change(e, 'manuscript')"
+          >
+              <el-table-column
+                align="center"
+              v-for="(item, i) in config.tableCol.list[
+                btns[condition.platform].text
+              ]"
+              :key="i"
+                :width="item.width"
+                show-overflow-tooltip
+                :prop="item.key"
+                :label="item.label"
+                :sortable="item.sortable"
+                :sort-orders="
+                  item.sortable ? ['ascending', 'descending', null] : []
+                "
+              >
+                <template #default="scope">
+                  {{
+                    item.type == 'number'
+                      ? formatter(scope.row[item.key])
+                      : scope.row[item.key]
+                  }}
+                </template>
+              </el-table-column>
+          </el-table>
+          <el-pagination
+            @current-change="e => changePageManuscript(e)"
+            background
+            layout="prev, pager, next"
+            :page-count="
+              Math.ceil(manuscriptData.total / condition.manuscript.size) || 1
+            "
+          />
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import header_local from '../allMedia/components/header.vue';
+import { ref } from 'vue';
+import { getAccountList, getUpdateTime, getAccountData } from '@/api/index';
+import dayjs from 'dayjs';
+import config from '../../config/index';
+import { formatter } from '../../utils/tool';
+
+const condition = ref({
+  platform: 0,
+  keyword: '',
+  dt: [],
+  sort: '',
+  order: '',
+  manuscript: {
+    page: 1,
+    size: 10,
+  },
+  disseminate: {
+    page: 1,
+    size: 10,
+  },
+});
+const activeName = ref('T1');
+const btns = [
+  {
+    text: '微博',
+    platform: 'weibo',
+    class: 'icon-weibo',
+  },
+  {
+    text: '微信',
+    platform: 'weixin',
+    class: 'icon-weixin',
+  },
+  {
+    text: '抖音',
+    platform: 'douyin',
+    class: 'icon-douyin',
+  },
+  {
+    text: '快手',
+    platform: 'kuaishou',
+    class: 'icon-kuaishou',
+  },
+//   {
+//     text: '头条',
+//     platform: 'jinritoutiao',
+//     class: 'icon-jinritoutiao',
+//   },
+  {
+    text: 'B站',
+    platform: 'bzhan',
+    class: 'icon-bzhan',
+  },
+  //   {
+  //     text: '闪视频',
+  //     platform: 'ssp',
+  //     class: 'icon-ssp',
+  //   },
+  //   {
+  //     text: '头条',
+  //     platform: 'sxtt',
+  //     class: 'icon-sxtt',
+  //   },
+];
+
+const manuscriptData = ref({ list: [], total: 0 });
+const disseminateData = ref({ list: [], total: 0 });
+
+let defaultTime = [];
+
+const selectPlatform = (item, index) => {
+  condition.value.platform = index;
+  for (let i = 0; i < defaultTime.length; i++) {
+    const v = defaultTime[i];
+    if (v.platform === item.text) {
+      condition.value.dt = [v.dt, v.dt];
+      break;
+    }
+  }
+  //   页码和条数重置
+  condition.value.sort = undefined;
+  condition.value.order = undefined;
+  condition.value.manuscript.page = 1;
+  condition.value.manuscript.size = 10;
+  condition.value.manuscript.total = 0;
+  condition.value.disseminate.page = 1;
+  condition.value.disseminate.size = 10;
+  condition.value.disseminate.total = 0;
+  getData();
+};
+const onSubmit = () => {
+  getData();
+};
+
+const sort_change = (e, type) => {
+  if (e.order) {
+    condition.value.sort = e.prop;
+    condition.value.order = e.order == 'descending' ? 1 : 0;
+  } else {
+    condition.value.sort = undefined;
+    condition.value.order = undefined;
+  }
+  if (type == 'manuscript') changePageManuscript();
+  else if (type == 'disseminate') changePageDisseminate();
+};
+
+const onExport = () => {
+  if (!condition.value.dt || condition.value.dt.length != 2) return;
+  let start = undefined;
+  let end = undefined;
+  if (condition.value.dt[0])
+    start = dayjs(condition.value.dt[0]).format('YYYY-MM-DD');
+  if (condition.value.dt[1])
+    end = dayjs(condition.value.dt[1]).format('YYYY-MM-DD');
+  let url =
+    config.base.origin + '/new-media/export?start=' + start + '&end=' + end;
+  if (condition.value.sort) url += '&sort=' + condition.value.sort;
+  if (condition.value.order) url += '&order=' + condition.value.order;
+  window.open(url);
+};
+
+const binding = () => {
+  window.open(
+    '#/authorization',
+    'newwindow',
+    'toolbar=no,location=no,resizable=no,height=550,width=750,scrollbars=yes,left=380,top=100'
+  );
+};
+
+const handleClick = () => {};
+
+const getData = () => {
+  let start = undefined;
+  let end = undefined;
+  if (condition.value.dt[0])
+    start = dayjs(condition.value.dt[0]).format('YYYY-MM-DD');
+  if (condition.value.dt[1])
+    end = dayjs(condition.value.dt[1]).format('YYYY-MM-DD');
+  getAccountList({
+    data: {
+      platform: btns[condition.value.platform].text,
+      start,
+      end,
+      page: condition.value.manuscript.page,
+      size: condition.value.manuscript.size,
+      match: condition.value.keyword,
+      sort: condition.value.sort,
+      order: condition.value.order,
+    },
+    token: '90dc3ca8ef93cd730490a76c3ec04d81c701130efd0966c7d512fd2387ef3dbd'
+  }).then(res => {
+    const resData = res || { records: [], total: 0 };
+    manuscriptData.value.list = resData.records;
+    manuscriptData.value.total = resData.total;
+  });
+
+  getAccountData({
+    data: {
+      platform: btns[condition.value.platform].text,
+      start,
+      end,
+      page: condition.value.disseminate.page,
+      size: condition.value.disseminate.size,
+      match: condition.value.keyword,
+      sort: condition.value.sort,
+      order: condition.value.order,
+    },
+  }).then(res => {
+    const resData = res || { records: [], total: 0 };
+    disseminateData.value.list = resData.records;
+    disseminateData.value.total = resData.total;
+  });
+};
+
+const changePageDisseminate = e => {
+  if (e) condition.value.disseminate.page = e;
+  let start = undefined;
+  let end = undefined;
+  if (condition.value.dt[0])
+    start = dayjs(condition.value.dt[0]).format('YYYY-MM-DD');
+  if (condition.value.dt[1])
+    end = dayjs(condition.value.dt[1]).format('YYYY-MM-DD');
+  getAccountData({
+    data: {
+      platform: btns[condition.value.platform].text,
+      start,
+      end,
+      page: condition.value.disseminate.page,
+      size: condition.value.disseminate.size,
+      match: condition.value.keyword,
+      sort: condition.value.sort,
+      order: condition.value.order,
+    },
+  }).then(res => {
+    const resData = res || { records: [], total: 0 };
+    disseminateData.value.list = resData.records;
+    disseminateData.value.total = resData.total;
+  });
+  // 切页
+};
+
+const changePageManuscript = e => {
+  if (e) condition.value.manuscript.page = e;
+  let start = undefined;
+  let end = undefined;
+  if (condition.value.dt[0])
+    start = dayjs(condition.value.dt[0]).format('YYYY-MM-DD');
+  if (condition.value.dt[1])
+    end = dayjs(condition.value.dt[1]).format('YYYY-MM-DD');
+  getAccountList({
+    data: {
+      platform: btns[condition.value.platform].text,
+      start,
+      end,
+      page: condition.value.manuscript.page,
+      size: condition.value.manuscript.size,
+      match: condition.value.keyword,
+      sort: condition.value.sort,
+      order: condition.value.order,
+    },
+    token: '90dc3ca8ef93cd730490a76c3ec04d81c701130efd0966c7d512fd2387ef3dbd'
+  }).then(res => {
+    const resData = res || { records: [], total: 0 };
+    manuscriptData.value.list = resData.records;
+    manuscriptData.value.total = resData.total;
+  });
+  // 切页
+};
+
+getUpdateTime({ data: {} }).then(res => {
+  defaultTime = res || [];
+  for (let i = 0; i < btns.length; i++) {
+    const v = btns[i];
+    if (v.text === defaultTime[0].platform) {
+      condition.value.dt = [defaultTime[0].dt, defaultTime[0].dt];
+      break;
+    }
+  }
+  getData();
+});
+</script>
+
+<style scoped>
+.convergence {
+  height: calc(100vh - 2em);
+  overflow: auto;
+  padding: 1em 1em 0 1em;
+}
+.convergence .platform {
+  width: 8em;
+}
+.convergence .el-form {
+  border-bottom: 1px solid #f3f3f3;
+}
+</style>
+
+<style>
+.convergence .el-form-item .weixin_active,
+.convergence .el-form-item .weixin:hover,
+.convergence .el-form-item .weixin:focus {
+  background-color: #1cc393;
+  border-color: #1cc393;
+  color: #ffffff;
+}
+.convergence .el-form-item .weibo_active,
+.convergence .el-form-item .weibo:hover,
+.convergence .el-form-item .weibo:focus {
+  background-color: #ffb712;
+  border-color: #ffb712;
+  color: #ffffff;
+}
+.convergence .el-form-item .kuaishou_active,
+.convergence .el-form-item .kuaishou:hover,
+.convergence .el-form-item .kuaishou:focus {
+  background-color: #eb3661;
+  border-color: #eb3661;
+  color: #ffffff;
+}
+.convergence .el-form-item .douyin_active,
+.convergence .el-form-item .douyin:hover,
+.convergence .el-form-item .douyin:focus {
+  background-color: #170b1a;
+  border-color: #170b1a;
+  color: #ffffff;
+}
+.convergence .el-form-item .bzhan_active,
+.convergence .el-form-item .bzhan:hover,
+.convergence .el-form-item .bzhan:focus {
+  background-color: #fb7299;
+  border-color: #fb7299;
+  color: #ffffff;
+}
+.convergence .el-form-item .jinritoutiao_active,
+.convergence .el-form-item .jinritoutiao:hover,
+.convergence .el-form-item .jinritoutiao:focus {
+  background-color: #f04142;
+  border-color: #f04142;
+  color: #ffffff;
+}
+.convergence .el-form-item .ssp_active,
+.convergence .el-form-item .ssp:hover,
+.convergence .el-form-item .ssp:focus {
+  background-color: #c11616;
+  border-color: #c11616;
+  color: #ffffff;
+}
+.convergence .el-form-item .sxtt_active,
+.convergence .el-form-item .sxtt:hover,
+.convergence .el-form-item .sxtt:focus {
+  background-color: #0083eb;
+  border-color: #0083eb;
+  color: #ffffff;
+}
+</style>

+ 777 - 0
src/view/task/onlineText.vue

@@ -0,0 +1,777 @@
+<template>
+  <div>
+    <div class="edito">
+      <div
+        class="onlineTextMain"
+        v-loading="loading"
+        element-loading-background="rgba(225,225,225,0.1)"
+      >
+        <div class="flex1">
+          <div class="btn-grounp">
+            文章内容
+            <el-button
+              type="primary"
+              style="
+                float: right;
+                margin-top: 0.3em;
+                margin-right: 0.5em;
+                padding: 0 1.8em;
+              "
+              @click="getServer"
+              :loading="loading"
+            >
+              校验
+            </el-button>
+            <el-button
+              class="clearError"
+              type="primary"
+              style="
+                float: right;
+                margin-top: 0.3em;
+                margin-right: 0.5em;
+                padding: 0 1.8em;
+              "
+              @click="exportFun"
+            >
+              导出
+            </el-button>
+            <el-button
+              class="clearError"
+              type="primary"
+              style="float: right; margin-top: 0.3em; margin-right: 0em"
+              @click="clearError"
+              :icon="Delete"
+            >
+              清空
+            </el-button>
+          </div>
+          <div class="Fle">
+            <Editor v-model:rawText="rawText" />
+          </div>
+        </div>
+        <div class="flex2">
+          <div class="btn-grounp">校对结果</div>
+          <div style="padding: 1em 1em 0 1em">
+            <div class="tabs">
+              <div
+                class="tab"
+                @click="() => changeTabAll()"
+                style="background-color: #2974ff; color: #fff"
+              >
+                <p>全部错误</p>
+                {{ search.tabs[0] ? search.tabs[0].num : 0 }}
+              </div>
+              <div
+                class="tab"
+                @click="() => changeTab(1)"
+                v-if="tabSelect[1]"
+                :style="{
+                  backgroundColor: getTypeError(1, 'rgba'),
+                  color: getTypeError(1, 'rgb'),
+                }"
+              >
+                <p>严重错误</p>
+                {{ search.tabs[1] ? search.tabs[1].num : 0 }}
+              </div>
+              <div class="tab" @click="() => changeTab(1)" v-else>
+                <p>严重错误</p>
+                {{ search.tabs[1] ? search.tabs[1].num : 0 }}
+              </div>
+              <div
+                class="tab"
+                @click="() => changeTab(3)"
+                v-if="tabSelect[3]"
+                :style="{
+                  backgroundColor: getTypeError(3, 'rgba'),
+                  color: getTypeError(3, 'rgb'),
+                }"
+              >
+                <p>一般错误</p>
+                {{ search.tabs[3] ? search.tabs[3].num : 0 }}
+              </div>
+              <div class="tab" @click="() => changeTab(3)" v-else>
+                <p>一般错误</p>
+                {{ search.tabs[3] ? search.tabs[3].num : 0 }}
+              </div>
+              <div
+                class="tab"
+                @click="() => changeTab(2)"
+                v-if="tabSelect[2]"
+                :style="{
+                  backgroundColor: getTypeError(2, 'rgba'),
+                  color: 'rgba(73, 92, 202, 1)',
+                }"
+              >
+                <p>疑错</p>
+                {{ search.tabs[2] ? search.tabs[2].num : 0 }}
+              </div>
+              <div class="tab" @click="() => changeTab(2)" v-else>
+                <p>疑错</p>
+                {{ search.tabs[2] ? search.tabs[2].num : 0 }}
+              </div>
+              <div
+                class="tab"
+                v-if="tabSelect[4]"
+                @click="() => changeTab(4)"
+                :style="{
+                  backgroundColor: getTypeError(4, 'rgba'),
+                  color: 'rgba(156, 133, 255, 1)',
+                }"
+              >
+                <p>
+                  自定义错误
+                  <el-popover
+                    placement="top-start"
+                    :width="200"
+                    trigger="hover"
+                    content="若自定义的词语(除正词外)与系统通用逻辑检测出的错误重叠,则该词语会展示两条错误。例:“尊守”为系统检出的错误,若同时设置“尊守”为禁用词,则当文章中出现“尊守”时,会展示两条错误,一条为系统检出,一条为自定义禁用词错误。"
+                  >
+                    <template #reference>
+                      <div
+                        style="
+                          display: inline-block;
+                          border: 1px solid rgb(156, 133, 255);
+                          vertical-align: middle;
+                          border-radius: 50%;
+                          width: 1.2em;
+                          height: 1.2em;
+                          line-height: 1.2em;
+                          text-align: center;
+                          color: #5e5e5e;
+                        "
+                      >
+                        ?
+                      </div>
+                    </template>
+                  </el-popover>
+                </p>
+                {{ search.tabs[4] ? search.tabs[4].num : 0 }}
+              </div>
+              <div class="tab" v-else @click="() => changeTab(4)">
+                <p>
+                  自定义错误
+                  <el-popover
+                    placement="top-start"
+                    :width="200"
+                    trigger="hover"
+                    content="若自定义的词语(除正词外)与系统通用逻辑检测出的错误重叠,则该词语会展示两条错误。例:“尊守”为系统检出的错误,若同时设置“尊守”为禁用词,则当文章中出现“尊守”时,会展示两条错误,一条为系统检出,一条为自定义禁用词错误。"
+                  >
+                    <template #reference>
+                      <div
+                        style="
+                          display: inline-block;
+                          border: 1px solid rgb(156, 133, 255);
+                          vertical-align: middle;
+                          border-radius: 50%;
+                          width: 1.2em;
+                          height: 1.2em;
+                          line-height: 1.2em;
+                          text-align: center;
+                          color: #5e5e5e;
+                        "
+                      >
+                        ?
+                      </div>
+                    </template>
+                  </el-popover>
+                </p>
+                {{ search.tabs[4] ? search.tabs[4].num : 0 }}
+              </div>
+            </div>
+            <div>
+              <el-radio-group v-model="tabAct">
+                <el-radio :label="0"
+                  >未处理: {{ search.list.length }}</el-radio
+                >
+                <el-radio :label="1"
+                  >已忽略: {{ search.list1.length }}</el-radio
+                >
+                <el-radio :label="2"
+                  >已替换: {{ search.list2.length }}</el-radio
+                >
+              </el-radio-group>
+            </div>
+          </div>
+          <div class="search">
+            <div v-if="tabAct === 0">
+              <div v-for="(item, index) in search.list" :key="index">
+                <div v-for="(v, i) in item.htmlWords" :key="'son' + i">
+                  <div
+                    v-if="tabSelect[item.um_error_level]"
+                    class="searchEnd"
+                    :style="{
+                      borderColor: getTypeError(item.um_error_level, 'rgb'),
+                      backgroundColor:
+                        select === index
+                          ? getTypeError(item.um_error_level, 'rgba')
+                          : '',
+                    }"
+                    @click="() => changeselect(index, item.type.belongId)"
+                  >
+                    <p style="display: flex">
+                      <span
+                        v-text="v.word"
+                        :style="{
+                          flex: 1,
+                          color: getTypeError(item.um_error_level, 'rgb'),
+                        }"
+                      ></span>
+                      <span
+                        style="flex: 1; text-align: right; color: #2dc76d"
+                        v-text="item.suggest[i]"
+                      ></span>
+                    </p>
+                    <p style="line-height: 2.5em">
+                      <span
+                        :style="{
+                          float: 'left',
+                          fontSize: '12px',
+                        }"
+                      >
+                        <span style="vertical-align: middle; margin-right: 5px">
+                          错误原因:{{ item.youmeiWordName }}
+                        </span>
+                        <el-popover
+                          v-if="item.explanation"
+                          placement="top-start"
+                          :width="200"
+                          trigger="hover"
+                          :content="item.explanation"
+                        >
+                          <template #reference>
+                            <div
+                              style="
+                                display: inline-block;
+                                border: 1px solid #5e5e5e;
+                                vertical-align: middle;
+                                border-radius: 50%;
+                                width: 1.2em;
+                                height: 1.2em;
+                                line-height: 1.2em;
+                                text-align: center;
+                                color: #5e5e5e;
+                              "
+                            >
+                              ?
+                            </div>
+                          </template>
+                        </el-popover>
+                      </span>
+                      <span style="float: right; text-align: right">
+                        <span
+                          class="btn"
+                          v-if="item.suggest[i]"
+                          @click.stop="
+                            () =>
+                              clearEle(
+                                item.colorPosition,
+                                item.suggest[i],
+                                index,
+                                2
+                              )
+                          "
+                          >替换</span
+                        >
+                        <span
+                          class="btn"
+                          v-if="isDel(item.type.belongId)"
+                          @click.stop="
+                            () =>
+                              removeEle(
+                                item.colorPosition,
+                                item.suggest[i],
+                                index,
+                                2
+                              )
+                          "
+                          >删除
+                        </span>
+                        <span
+                          class="btn"
+                          @click.stop="
+                            () =>
+                              clearEle(
+                                item.colorPosition,
+                                item.wordHtml,
+                                index,
+                                1
+                              )
+                          "
+                          >忽略</span
+                        >
+                      </span>
+                      <span style="clear: both; display: block"></span>
+                    </p>
+                  </div>
+                </div>
+              </div>
+              <el-empty
+                description="所选类型下暂无信息"
+                v-if="!search.list || !search.list.length"
+              />
+            </div>
+            <div v-if="tabAct === 1">
+              <div v-for="(item, index) in search.list1 || []" :key="index">
+                <div v-for="(v, i) in item.htmlWords" :key="'son' + i">
+                  <div
+                    class="searchEnd"
+                    v-if="tabSelect[item.um_error_level]"
+                    :style="{
+                      borderColor: getTypeError(item.um_error_level, 'rgb'),
+                      backgroundColor:
+                        select === index
+                          ? getTypeError(item.um_error_level, 'rgba')
+                          : '',
+                    }"
+                    @click="() => changeselect(index, item.type.belongId)"
+                  >
+                    <p style="display: flex">
+                      <span
+                        v-text="v.word"
+                        :style="{
+                          flex: 1,
+                          color: getTypeError(item.um_error_level, 'rgb'),
+                        }"
+                      ></span>
+                      <span
+                        style="flex: 1; text-align: right; color: #2dc76d"
+                        v-text="item.suggest[i]"
+                      ></span>
+                    </p>
+                    <p style="line-height: 2.5em">
+                      <span
+                        :style="{
+                          float: 'left',
+                          fontSize: '12px',
+                        }"
+                      >
+                        <span style="vertical-align: middle; margin-right: 5px">
+                          错误原因:{{ item.youmeiWordName }}
+                        </span>
+                        <el-popover
+                          v-if="item.explanation"
+                          placement="top-start"
+                          :width="200"
+                          trigger="hover"
+                          :content="item.explanation"
+                        >
+                          <template #reference>
+                            <div
+                              style="
+                                display: inline-block;
+                                border: 1px solid #5e5e5e;
+                                vertical-align: middle;
+                                border-radius: 50%;
+                                width: 1.2em;
+                                height: 1.2em;
+                                line-height: 1.2em;
+                                text-align: center;
+                                color: #5e5e5e;
+                              "
+                            >
+                              ?
+                            </div>
+                          </template>
+                        </el-popover>
+                      </span>
+                      <span style="float: right; text-align: right">
+                        <span
+                          class="btn"
+                          @click.stop="() => back(item, index, 1)"
+                          >撤销</span
+                        >
+                      </span>
+                      <span style="clear: both; display: block"></span>
+                    </p>
+                  </div>
+                </div>
+              </div>
+              <el-empty
+                description="所选类型下暂无信息"
+                v-if="!search.list1 || !search.list1.length"
+              />
+            </div>
+            <div v-if="tabAct === 2">
+              <div v-for="(item, index) in search.list2 || []" :key="index">
+                <div v-for="(v, i) in item.htmlWords" :key="'son' + i">
+                  <div
+                    class="searchEnd"
+                    v-if="tabSelect[item.um_error_level]"
+                    :style="{
+                      borderColor: getTypeError(item.um_error_level, 'rgb'),
+                      backgroundColor:
+                        select === index
+                          ? getTypeError(item.um_error_level, 'rgba')
+                          : '',
+                    }"
+                    @click="() => changeselect(index, item.type.belongId)"
+                  >
+                    <p style="display: flex">
+                      <span
+                        v-text="v.word"
+                        :style="{
+                          flex: 1,
+                          color: getTypeError(item.um_error_level, 'rgb'),
+                        }"
+                      ></span>
+                      <span
+                        style="flex: 1; text-align: right; color: #2dc76d"
+                        v-text="item.suggest[i]"
+                      ></span>
+                    </p>
+                    <p style="line-height: 2.5em">
+                      <span
+                        :style="{
+                          float: 'left',
+                          fontSize: '12px',
+                        }"
+                      >
+                        <span style="vertical-align: middle; margin-right: 5px">
+                          错误原因:{{ item.youmeiWordName }}
+                        </span>
+                        <el-popover
+                          v-if="item.explanation"
+                          placement="top-start"
+                          :width="200"
+                          trigger="hover"
+                          :content="item.explanation"
+                        >
+                          <template #reference>
+                            <div
+                              style="
+                                display: inline-block;
+                                border: 1px solid #5e5e5e;
+                                vertical-align: middle;
+                                border-radius: 50%;
+                                width: 1.2em;
+                                height: 1.2em;
+                                line-height: 1.2em;
+                                text-align: center;
+                                color: #5e5e5e;
+                              "
+                            >
+                              ?
+                            </div>
+                          </template>
+                        </el-popover>
+                      </span>
+                      <span style="float: right; text-align: right">
+                        <span
+                          class="btn"
+                          @click.stop="() => back(item, index, 2)"
+                        >
+                          撤销
+                        </span>
+                      </span>
+
+                      <span style="clear: both; display: block"></span>
+                    </p>
+                  </div>
+                </div>
+              </div>
+              <el-empty
+                description="所选类型下暂无信息"
+                v-if="!search.list2 || !search.list2.length"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import Editor from '@/components/editor.vue';
+import config from '@/config/index';
+import { ElMessage } from 'element-plus';
+import { Delete } from '@element-plus/icons-vue';
+import { reactive, ref, nextTick } from 'vue';
+import errType from '../../../config/errtype';
+document.title = '稿前校对';
+const loading = ref(false);
+
+const rawText = ref('');
+const tabSelect = reactive([true, true, true, true, true]);
+const urlData = geturl();
+let search = reactive({
+  list: [],
+  list1: [],
+  list2: [],
+  tabs: [
+    {
+      num: 0,
+    },
+  ],
+});
+const tabAct = ref(0);
+const select = ref(0);
+function clearError() {
+  rawText.value = '';
+  search.list = [];
+  search.list1 = [];
+  search.list2 = [];
+  search.tabs = [{ num: 0 }];
+}
+
+function getTypeError(key, type) {
+  if (type == 'rgb') return type + '(' + errType[key] + ')';
+  if (type == 'rgba') return type + '(' + errType[key] + ', 0.1)';
+  return '';
+}
+
+function changeselect(index) {
+  const oldEle = document.querySelector(
+    "[data-umpos='" + search.list[select.value].colorPosition + "']"
+  );
+  const newEle = document.querySelector(
+    "[data-umpos='" + search.list[index].colorPosition + "']"
+  );
+  oldEle.style.backgroundColor = '';
+  newEle.style.backgroundColor =
+    'rgba(' + errType[search.list[index].um_error_level] + ', 0.5)';
+  select.value = index;
+}
+
+function clearEle(colorPosition, text, i, type) {
+  const newEle = document.querySelector("[data-umpos='" + colorPosition + "']");
+  newEle.setAttribute('style', '');
+  newEle.innerText = text;
+  const item = JSON.parse(JSON.stringify(search.list[i]));
+  search['list' + type].push(item);
+  search.list.splice(i, 1);
+  rawText.value = document.querySelector('.Fle .text').innerHTML;
+}
+
+function isDel(id) {
+  const Del = {
+    105: true,
+    108: true,
+    112: true,
+    111: true,
+    201: true,
+  };
+  return Del[id];
+}
+
+function removeEle(colorPosition, text, i) {
+  const newEle = document.querySelector("[data-umpos='" + colorPosition + "']");
+  newEle.remove();
+  rawText.value = document.querySelector('.text').innerHTML;
+  search.list.splice(i, 1);
+}
+
+function back(v, i, type) {
+  const newEle = document.querySelector(
+    "[data-umpos='" + v.colorPosition + "']"
+  );
+  newEle.style.borderColor = 'rgb(' + errType[v.um_error_level] + ')';
+  const item = JSON.parse(JSON.stringify(search['list' + type][i]));
+  search.list.push(item);
+  search['list' + type].splice(i, 1);
+}
+function getServer() {
+  if (!window.fetch) return;
+  loading.value = true;
+  const ele = document.createElement('div');
+  ele.innerHTML = rawText.value;
+  if (!urlData.spm) {
+    if (location.replace) location.replace('https://home.sxtvs.net/');
+    else location.href = 'https://home.sxtvs.net/';
+  }
+  window
+    .fetch('https://topic.smcic.net/youmei/check', {
+      method: 'POST',
+      body: JSON.stringify({
+        raw: ele.innerText,
+        text: rawText.value || config.base.default_text || '',
+      }),
+      headers: {
+        'Content-Type': 'application/json',
+        spm: urlData.spm || '',
+      },
+    })
+    .then(json => json.json())
+    .then(res => {
+      loading.value = false;
+      if (!res || res.code !== 0)
+        return ElMessage({
+          type: 'error',
+          message: res.message || '请稍后再试!',
+          onClose() {
+            if (res.code !== 1000) return;
+            if (location.replace) location.replace('https://home.sxtvs.net/');
+            else location.href = 'https://home.sxtvs.net/';
+          },
+        });
+      search.list = res.data.checklist || [];
+      search.list1 = [];
+      search.list2 = [];
+      rawText.value = res.data.rawText || '';
+      nextTick(() => {
+        const tabs = [
+          {
+            num: 0,
+          },
+        ];
+        for (let i = 0; i < search.list.length; i++) {
+          const item = search.list[i];
+          const ele = document.querySelector(
+            "[data-umpos='" + item.colorPosition + "']"
+          );
+          ele.style.borderBottom =
+            '3px solid rgb(' + errType[item.um_error_level] + ')';
+          if (!tabs[item.um_error_level])
+            tabs[item.um_error_level] = {
+              num: 0,
+            };
+          tabs[0].num += 1;
+          tabs[item.um_error_level].num += 1;
+          if (i !== 0) continue;
+          ele.style.backgroundColor =
+            'rgba(' + errType[item.um_error_level] + ',0.5)';
+        }
+        search.tabs = tabs;
+      });
+    });
+}
+
+function geturl() {
+  const searchText = location.hash.split('?')[1] || '';
+  let search = searchText.replace('?', '').split('&');
+  let obj = {};
+  for (let i = 0; i < search.length; i++) {
+    const v = search[i].split('=');
+    obj[v[0]] = v[1] || '';
+  }
+  return obj;
+}
+
+function changeTab(i) {
+  tabSelect[i] = !tabSelect[i];
+}
+
+function changeTabAll() {
+  let t = tabSelect.filter(v => !v).length ? true : false;
+  for (let i = 0; i < tabSelect.length; i++) {
+    tabSelect[i] = t;
+  }
+}
+
+// 导出word
+function exportFun() {
+  /**
+   * wps: kswps
+   * docx: msword
+   */
+  let blob = new Blob([`<body>${rawText.value}</body>`], {
+    type: 'application/kswps',
+  });
+  let url = URL.createObjectURL(blob);
+  let link = document.createElement('a');
+  link.setAttribute('href', url);
+  link.setAttribute('download', `智能校对.docx`);
+  link.click();
+}
+</script>
+
+<style scoped>
+.onlineTextMain {
+  padding: 1em;
+  display: flex;
+}
+
+.onlineTextMain > div {
+  flex: 3;
+  margin-right: 0.5em;
+  border: 1px solid #eee;
+  height: calc(100vh - 106px);
+}
+.onlineTextMain .flex2 {
+  flex: 2;
+}
+.onlineTextMain > div:last-child {
+  margin-right: 0;
+}
+.btn-grounp {
+  color: #666;
+  background-color: #f9fafc;
+  line-height: 2.52em;
+  padding-left: 0.5em;
+  border-bottom: 1px solid #eee;
+}
+.search {
+  padding: 1em;
+  font-size: 12px;
+  height: calc(100% - 172px);
+  overflow: auto;
+}
+.searchEnd {
+  border: 1px solid;
+  border-top: 4px solid;
+  margin-bottom: 1em;
+  padding: 5px 35px;
+  font-size: 14px;
+  line-height: 1.5em;
+}
+.btn {
+  display: inline-block;
+  background: rgba(41, 116, 255, 0.1);
+  color: #2974ff;
+  padding: 3px 15px;
+  height: 1.5em;
+  line-height: 1.5em;
+  margin-left: 0.3em;
+  cursor: pointer;
+}
+
+.flex1 {
+  line-height: 1.5em;
+  min-height: 1.5em;
+}
+.flex1 span {
+  display: inline-block;
+}
+.tabs {
+  display: flex;
+  margin: 0.5em 0;
+}
+.tab {
+  flex: 1;
+  margin-left: 0.3em;
+  border-radius: 2px;
+  background-color: rgba(144, 144, 144, 0.1);
+  color: #909090;
+  line-height: 1.6em;
+  padding: 3px 15px;
+  text-align: center;
+  font-size: 12px;
+  cursor: pointer;
+}
+
+.Fle {
+  height: calc(100vh-226px);
+}
+.tab p {
+  white-space: nowrap;
+}
+.clearError {
+  float: right;
+}
+</style>
+
+<style>
+.edito .el-popper.is-light,
+.edito .el-popper .el-popper__arrow::before {
+  background-color: #2974ff !important;
+  color: #fff;
+  border-color: #2974ff !important;
+}
+.edito {
+  min-width: 1280px;
+  margin: 0 auto;
+}
+.example-showcase .el-loading-mask {
+  z-index: 9;
+}
+</style>