cankao-admin/src/views/pages/richedit/index.vue

1489 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="index inside_pd">
<div class="colHeader">
<div class="page_title" v-if="Session.get('userInfoLocal').userType == '00'">资讯精选</div>
<div class="page_title" v-if="Session.get('userInfoLocal').userType == '01'">资讯审核</div>
<!-- 普通管理员和审核人员的筛选条件不一样,普通管理员是资讯精选、其他是资讯审核 -->
<!-- 普通管理员的筛选 start -->
<div style="width: 100%; display: flex; align-items: flex-end" v-if="Session.get('userInfoLocal').userType != '00'">
<el-button type="primary" style="margin-bottom: 10px" @click="restData">清空条件</el-button>
<div class="colHeader-right" :style="{ alignItems: 'flex-end', minWidth: '700px' }">
<el-space :size="12" class="colHeader-right-1">
<el-input
v-model="form.keyword"
placeholder="输入标题/内容关键字进行搜索(以空格隔开)"
class="input-with-select"
@keyup.enter="handleSearch"
style="width: 455px"
>
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
<div>
<span>行业分类:</span>
<el-tree-select
v-model="form.industry"
:data="industryList"
multiple
:render-after-expand="false"
filterable
show-checkbox
style="width: 240px"
@check="handleCheckChange"
@clear="handleSearch"
node-key="id"
collapse-tags
collapse-tags-tooltip
clearable
:props="defaultProps"
>
</el-tree-select>
</div>
<el-input
v-model="form.tag"
placeholder="匹配多个概念标签(以空格隔开)"
class="input-with-select"
@keyup.enter="handleSearch"
style="width: 280px"
>
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
</el-space>
<div class="colHeader-right-2">
<el-date-picker
v-model="daterange"
type="daterange"
range-separator="至"
value-format="YYYY-MM-DD"
start-placeholder="选择报道时间"
end-placeholder="选择报道时间"
style="margin-right: 12px"
@change="handleSearch"
/>
<el-select-v2
v-model="form.mediaId"
:options="tagSourceList"
clearable
placeholder="媒体来源"
size="large"
style="width: 240px"
filterable
@change="handleSearch"
/>
<el-select
clearable
v-model="form.deleted"
size="large"
style="width: 150px; margin-left: 10px"
v-if="Session.get('userInfoLocal').userType == '00'"
placeholder="筛选删除状态"
@change="handleSearch"
>
<el-option :value="1" label="已删除资讯"></el-option>
<el-option :value="0" label="未删除资讯"></el-option>
</el-select>
<div style="margin-left: 12px; display: flex; flex-wrap: nowrap; align-items: center">
<span>评分范围:</span>
<el-input
type="number"
v-model="form.minScore"
style="width: 80px"
placeholder="最低"
:min="0"
:max="100"
@keyup.enter="handleSearch"
/>
<i style="color: #ccc"> - </i>
<el-input type="number" v-model="form.maxScore" style="width: 140px" placeholder="最高" :min="0" :max="100" @keyup.enter="handleSearch">
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
</div>
</div>
</div>
</div>
<!-- 普通管理员的筛选 end -->
<div style="width: 100%; display: flex; margin-top: 20px" v-else>
<div class="colHeader-right">
<el-space :size="12" class="colHeader-right-1">
<span>标题检索:</span>
<el-input
v-model="form.keyword"
placeholder="输入标题/内容关键字进行搜索(以空格隔开)"
class="input-with-select"
@keyup.enter="handleSearch"
style="width: 500px"
>
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
<div>
<span>行业分类:</span>
<el-tree-select
v-model="form.industry"
:data="industryList"
multiple
:render-after-expand="false"
filterable
show-checkbox
style="width: 240px"
@check="handleCheckChange"
@clear="handleSearch"
node-key="id"
collapse-tags
collapse-tags-tooltip
clearable
:props="defaultProps"
>
</el-tree-select>
</div>
<el-input
v-model="form.tag"
placeholder="匹配多个概念标签(以空格隔开)"
class="input-with-select"
@keyup.enter="handleSearch"
style="width: 280px"
>
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
</el-space>
<div class="colHeader-right-2" style="gap: 10px">
<span>信号规则:</span>
<el-select
v-model="form.includeRuleIds"
clearable
placeholder="含任一信号规则"
multiple
size="large"
style="width: 180px"
filterable
@change="signalChange($event, 1)"
>
<el-option
v-for="item in signalRulesList"
:key="item.id"
:value="item.id"
:disabled="form.excludeRuleIds?.includes(item.id)"
:label="item.ruleName"
></el-option>
</el-select>
<el-select
v-model="form.excludeRuleIds"
clearable
placeholder="不含任一信号规则"
multiple
size="large"
style="width: 180px"
filterable
@change="signalChange($event, 2)"
>
<el-option
v-for="item in signalRulesList"
:key="item.id"
:value="item.id"
:disabled="form.includeRuleIds?.includes(item.id)"
:label="item.ruleName"
></el-option>
</el-select>
<span>报道时间:</span>
<div>
<el-date-picker
v-model="daterange"
type="daterange"
range-separator="-"
value-format="YYYY-MM-DD"
start-placeholder="选择报道时间"
end-placeholder="选择报道时间"
@change="handleSearch"
/>
</div>
<div style="display: flex; flex-wrap: nowrap; align-items: center">
<span>评分范围:</span>
<el-input
type="number"
v-model="form.minScore"
style="width: 80px"
placeholder="最低"
:min="0"
:max="100"
@keyup.enter="handleSearch"
/>
<i style="color: #ccc"> - </i>
<el-input type="number" v-model="form.maxScore" style="width: 140px" placeholder="最高" :min="0" :max="100" @keyup.enter="handleSearch">
<template #append>
<el-button icon="Search" @click="handleSearch" />
</template>
</el-input>
</div>
</div>
<div class="colHeader-right-2" style="gap: 10px">
<span>媒体来源:</span>
<el-select-v2
v-model="form.mediaId"
:options="tagSourceList"
clearable
placeholder="媒体来源"
size="large"
style="width: 180px"
filterable
@change="handleSearch"
/>
<span>企业检索:</span>
<!-- <el-select
v-model="form.companyName"
clearable
placeholder="请选择"
multiple
size="large"
style="width: 180px"
filterable
@change="handleSearch"
>
<el-option>是</el-option>
<el-option>否</el-option>
</el-select> -->
<el-select
class="search-input"
popper-class="option-box"
v-model="form.companyName"
clearable
filterable
remote
reserve-keyword
remote-show-suffix
default-first-option
:suffix-icon="Search"
placeholder="输入企业名称/企业简称/证券编码进行搜索"
:loading="loading"
:remote-method="getCompany"
@change="getData"
style="width: 180px"
>
<el-option v-for="item in companyList" :key="item.companyName" :label="item.companyName" :value="item.companyName"> </el-option>
</el-select>
<span>先机资讯:</span>
<el-select
v-model="form.exclusive"
clearable
placeholder="是否先机搜索"
size="large"
style="width: 180px"
filterable
@change="handleSearch"
>
<el-option :value="1" label="是"></el-option>
<el-option :value="0" label="否"></el-option>
</el-select>
<span>删除状态:</span>
<el-select
clearable
v-model="form.deleted"
size="large"
style="width: 150px; margin-left: 10px"
placeholder="筛选删除状态"
@change="handleSearch"
>
<el-option :value="1" label="已删除资讯"></el-option>
<el-option :value="0" label="未删除资讯"></el-option>
</el-select>
<el-button type="primary" @click="restData">清空条件</el-button>
</div>
</div>
</div>
</div>
<div v-if="Session.get('userInfoLocal').userType == '00'" style="width: 100%; display: flex; justify-content: flex-end">
<el-switch v-model="hadExpand" inactive-text="聚类模式" @change="handleExpandChange"></el-switch>
</div>
<tableComponents
ref="tableRef"
:tableData="tableData"
style="margin-top: 20px"
@sortChange="sortChange"
:tableLoading="tableLoading"
@currentChange="currentChange"
:hadExpand="hadExpand"
@sizeChange="sizeChange"
>
<!-- <el-table-column type="expand">
<template v-slot="scope">
<z-table :tableData="{ data: scope.row.clusterNews }" style="margin-left: 50px; width: 100%"></z-table>
</template>
</el-table-column> -->
<el-table-column prop="title" label="标题" align="left" width="380">
<template v-slot="scope">
<div style="display: flex; justify-content: flex-start; align-items: center; width: 100%">
<div style="margin-right: 15px" v-if="scope.row.clusterNews && Session.get('userInfoLocal').userType == '00' && hadExpand">
{{ scope.row.clusterNews ? scope.row.clusterNews.length : 0 }}
</div>
<div
style="
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: start;
gap: 5px;
padding: 10px 0;
margin-top: 8px;
"
>
<div
v-if="scope.row.isChild && scope.row.clusterIndex == 0"
style="font-size: 14px; font-weight: bold; margin-left: -20px; margin-bottom: 30px"
>
聚类资讯({{ scope.row.childLength }}条)
</div>
<div style="display: inline-block">
<span style="color: red; font-weight: bold; margin-right: 3px" v-if="scope.row.exclusive == 1">[独家]</span>
<span class="cursor-pointer" @click="goDetail(1, scope.row, true)" v-html="scope.row.title"></span>
</div>
<div class="labels" v-if="Session.get('userInfoLocal').userType == '00'" style="display: flex; justify-content: flex-start">
<div
v-if="scope.row.companyName && scope.row.companyName.length > 0"
style="flex-wrap: wrap; white-space: wrap; display: flex; justify-content: flex-start; gap: 10px"
>
<div v-for="item in scope.row.companyName.split(',')" class="label_item">{{ item }}</div>
</div>
</div>
<div class="labels" v-if="Session.get('userInfoLocal').userType == '00'">
<div style="background-color: #eee6cd" class="label_item" v-if="scope.row.conceptLabels && scope.row.conceptLabels.length > 0">
{{ scope.row.conceptLabels[0] }}
</div>
<div style="background-color: #cfdcf3" class="label_item" v-if="scope.row.industryLabels && scope.row.industryLabels.length > 0">
{{ scope.row.industryLabels[0] }}
</div>
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="信号规则" align="center" width="120" v-if="Session.get('userInfoLocal').userType == '00'">
<template v-slot="scope">
<div v-if="scope.row.ruleName && scope.row.ruleName.length > 0">
<div v-for="item in scope.row.ruleName" :key="item" class="label_item">
{{ item }}
</div>
</div>
<div v-else>-</div>
</template>
</el-table-column>
<el-table-column label="媒体来源" align="center" width="120" v-if="Session.get('userInfoLocal').userType == '00'">
<template v-slot="scope">
<div v-if="scope.row.sourceName">
{{ scope.row.sourceName }}
</div>
<div v-else>-</div>
</template>
</el-table-column>
<el-table-column prop="status" align="center" width="120">
<template #header>
<el-dropdown trigger="click" @command="handleCommand">
<div class="el-dropdown-link">
<text style="color: rgba(0, 0, 0, 0.85); font-size: 14px">发布状态</text>
<el-image :src="icon_table_filter" style="width: 20px; height: 20px"></el-image>
</div>
<template #dropdown>
<div v-if="Session.get('userInfoLocal').userType == '00'">
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="1">未发布</el-dropdown-item>
<el-dropdown-item :command="3">审核中</el-dropdown-item>
<el-dropdown-item :command="4">已二审</el-dropdown-item>
<el-dropdown-item :command="2">已发布</el-dropdown-item>
<el-dropdown-item :command="-1">退改中</el-dropdown-item>
</el-dropdown-menu>
</div>
<div v-else>
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="1" v-if="Session.get('userInfoLocal').userType == '00'">未发布</el-dropdown-item>
<el-dropdown-item :command="3" v-if="Session.get('userInfoLocal').userType != '01'">审核中</el-dropdown-item>
<el-dropdown-item :command="4" v-if="Session.get('userInfoLocal').userType == '02' || Session.get('userInfoLocal').userType == '01'"
>已二审</el-dropdown-item
>
<el-dropdown-item :command="2">已发布</el-dropdown-item>
<el-dropdown-item
:command="-1"
v-if="Session.get('userInfoLocal').userType == '02' || Session.get('userInfoLocal').userType == '01'"
>退改中</el-dropdown-item
>
</el-dropdown-menu>
</div>
</template>
</el-dropdown>
</template>
<template v-slot="scope">
<!-- 新闻状态 0-草稿 1-未发布 2-已发布 -->
<div class="r_point" :style="{ color: '#000' }">
<div class="point" :style="{ backgroundColor: scope.row.status == 2 ? '#52C41A' : '#D9D9D9' }"></div>
<text v-if="scope.row.status == 0" style="color: rgba(0, 0, 0, 0.65)">草稿</text>
<text v-if="scope.row.status == 1" style="color: rgba(0, 0, 0, 0.65)">
{{ scope.row.deleted ? '已删除' : '未发布' }}
</text>
<text v-if="scope.row.status == 2" style="color: rgba(0, 0, 0, 0.65)">已发布</text>
<text v-if="scope.row.status == 3" style="color: rgba(0, 0, 0, 0.65)">审核中</text>
<text v-if="scope.row.status == 4" style="color: rgba(0, 0, 0, 0.65)">已二审</text>
<text v-if="scope.row.status == -1 && !scope.row.deleted" style="color: red"> 退改中 </text>
<text v-if="scope.row.status == -1 && scope.row.deleted"> 已删除 </text>
</div>
</template>
</el-table-column>
<el-table-column align="center" width="120" prop="submitter" label="编辑">
<template v-slot="scope">
{{ scope.row.submitter ? scope.row.submitter : '-' }}
</template>
</el-table-column>
<el-table-column align="center" width="120" prop="submitter" label="二校" v-if="Session.get('userInfoLocal').userType == '01'">
<template v-slot="scope">
{{ scope.row.submitterSecond ? scope.row.submitterSecond : '-' }}
</template>
</el-table-column>
<el-table-column align="center" width="120">
<template #header>
<el-dropdown trigger="click" @command="handleCommandRating">
<div class="el-dropdown-link">
<text style="color: rgba(0, 0, 0, 0.85); font-size: 14px">编辑评分</text>
<el-image :src="icon_table_filter" style="width: 20px; height: 20px"></el-image>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="0">无评分</el-dropdown-item>
<el-dropdown-item :command="10">10</el-dropdown-item>
<el-dropdown-item :command="9">9</el-dropdown-item>
<el-dropdown-item :command="8">8</el-dropdown-item>
<el-dropdown-item :command="7">7</el-dropdown-item>
<el-dropdown-item :command="6">6</el-dropdown-item>
<el-dropdown-item :command="5">5</el-dropdown-item>
<el-dropdown-item :command="4">4</el-dropdown-item>
<el-dropdown-item :command="3">3</el-dropdown-item>
<el-dropdown-item :command="2">2</el-dropdown-item>
<el-dropdown-item :command="1">1</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<template v-slot="scope">
{{ scope.row.rating != 0 && scope.row.rating != null ? scope.row.rating : '-' }}
</template>
</el-table-column>
<el-table-column prop="score" label="资讯评分" sortable="custom" align="center" width="100">
<template v-slot="scope">
<div @click="getScoreDetail(scope.row.id)" :class="[{ 'score-active': isAdmin && curScore === scope.row.id }, { 'score-hover': isAdmin }]">
{{ scope.row.score }}
</div>
</template>
</el-table-column>
<el-table-column label="风险性" align="center" width="220">
<template #header>
<el-dropdown trigger="click" @command="handleCommand2">
<div class="el-dropdown-link">
<text style="color: rgba(0, 0, 0, 0.85); font-size: 14px">风险性</text>
<el-image :src="icon_table_filter" style="width: 20px; height: 20px"></el-image>
</div>
<template #dropdown>
<div>
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="0">无敏</el-dropdown-item>
<el-dropdown-item :command="40">低敏</el-dropdown-item>
<el-dropdown-item :command="70">中敏</el-dropdown-item>
<el-dropdown-item :command="85">高敏</el-dropdown-item>
</el-dropdown-menu>
</div>
</template>
</el-dropdown>
</template>
<template v-slot="scope">
<el-tooltip v-if="scope.row.politicalSensitivity >= 0 && scope.row.politicalSensitivity < 40" content="基本不涉及时政敏感信息,可支持一定范围的传播" placement="top">
<el-tag type="info">{{ scope.row.politicalSensitivity >= 0 && scope.row.politicalSensitivity < 40 ? '无敏' : '' }}</el-tag>
</el-tooltip>
<el-tooltip v-if="scope.row.politicalSensitivity >= 40 && scope.row.politicalSensitivity < 70" content="可能一定程度上涵盖时政相关信息,但一般不涉及确认敏感的议题" placement="top">
<el-tag type="primary">{{ scope.row.politicalSensitivity >= 40 && scope.row.politicalSensitivity < 70 ? '低敏' : '' }}</el-tag>
</el-tooltip>
<el-tooltip v-if="scope.row.politicalSensitivity >= 70 && scope.row.politicalSensitivity < 85" content="可能存在具备政治立场倾向性或有不当表述,建议内部传阅或局部修改后发布" placement="top">
<el-tag type="warning">{{ scope.row.politicalSensitivity >= 70 && scope.row.politicalSensitivity < 85 ? '中敏' : '' }}</el-tag>
</el-tooltip>
<el-tooltip v-if="scope.row.politicalSensitivity >= 85" content="极可能包含高敏感信息,存在不适合在公开场合传播的信息内容" placement="top">
<el-tag type="danger">{{ scope.row.politicalSensitivity >= 85 ? '高敏' : '' }}</el-tag>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="publishTime" label="报道时间" sortable="custom" align="center" />
<el-table-column prop="updateTime" label="状态变动时间" sortable="custom" align="center">
<template v-slot="scope">
<div>
<div>{{ formatTime(scope.row.updateTime) == formatTime(scope.row.createTime) ? scope.row.publishTime : scope.row.updateTime }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100" fixed="right">
<template v-slot="scope">
<div class="option">
<el-button v-if="scope.row.deleted" type="text" style="margin-left: -10px" @click="doRecoverFn(scope.row)">
<text>恢复</text>
</el-button>
<div v-else style="display: flex; align-items: center; flex-direction: column; justify-content: center">
<el-button type="text" :disabled="scope.row.status != 2" class="copyBtn" @click="copyUrl(scope.row)">复制</el-button>
<!-- 新闻状态 0-草稿 | 1-未发布 | 2-已发布 | 3-送审 | 4-已二审 | -1-退改中 -->
<div v-if="Session.get('userInfoLocal').userType == '00'" style="display: flex; flex-direction: column">
<!-- 普通账号 -->
<el-button
v-if="scope.row.status == 0 || scope.row.status == 1 || scope.row.status == -1"
type="text"
@click="goDetail(1, scope.row, false)"
>编辑</el-button
>
<el-button
v-if="scope.row.status == 0 || scope.row.status == 1 || scope.row.status == -1"
type="text"
@click="doApprovalFn(scope.row, scope.row.status)"
>送审</el-button
>
<el-button v-else-if="scope.row.status == 3" type="text" @click="doApprovalFn(scope.row, scope.row.status)">撤审</el-button>
<el-button
v-if="scope.row.status == 0 || scope.row.status == 1 || scope.row.status == -1"
type="text"
style="color: #ff1818"
@click="doDeleteNewsFn(scope.row)"
>删除</el-button
>
</div>
<div v-if="Session.get('userInfoLocal').userType == '02'" style="display: flex; flex-direction: column">
<el-button v-if="scope.row.status == 4" type="text" @click="doApprovalFn(scope.row, scope.row.status)">撤审</el-button>
<!-- 二审账号 -->
<el-button v-if="scope.row.status == 3" type="text" style="color: #ff1818" @click="doNewReturnFn(scope.row)">退改</el-button>
<el-button v-if="scope.row.status == 3" type="text" @click="goDetail(1, scope.row, false)">编辑</el-button>
<el-button v-if="scope.row.status == 3" type="text" @click="doNewCheckFn(scope.row)">复审</el-button>
<el-button type="text" v-if="scope.row.status == 4" @click="doNewsPublishFn(scope.row, 2)">发布</el-button>
</div>
<div v-if="Session.get('userInfoLocal').userType == '01'" style="display: flex; flex-direction: column">
<!-- 终审账号 -->
<el-button v-if="scope.row.status == 3 || scope.row.status == 4" type="text" @click="goDetail(1, scope.row, false)">编辑</el-button>
<el-button v-if="scope.row.status == 4" type="text" style="color: #ff1818" @click="doNewReturnFn(scope.row)">退改</el-button>
<el-button type="text" v-if="scope.row.status == 2" @click="doNewsPublishFn(scope.row, 1)">撤稿</el-button>
<el-button type="text" v-else-if="scope.row.status != -1 && scope.row.status == 4" @click="doNewsPublishFn(scope.row, 2)"
>发布</el-button
>
<el-button v-if="scope.row.status == 3" type="text" style="color: #ff1818; margin-left: 5px" @click="doNewReturnFn(scope.row)"
>退改</el-button
>
</div>
<!-- <el-icon size="16" @click="goRecord(scope.row)">
<Tickets />
</el-icon> -->
</div>
<!-- v-if="isAdmin" -->
<el-button
class="record_btn"
type="text"
v-if="isAdmin || Session.get('userInfoLocal').userType == '02' || Session.get('userInfoLocal').userType == '01'"
@click="goRecord(scope.row)"
>
操作记录
</el-button>
<!-- <el-icon
v-if="isAdmin || Session.get('userInfoLocal').userType == '02' || Session.get('userInfoLocal').userType == '01'"
size="16"
@click="goRecord(scope.row)"
>
<Tickets />
</el-icon> -->
</div>
</template>
</el-table-column>
</tableComponents>
<keep-alive>
<DetailDrawer
v-model="drawer"
:data="newsData"
:readOnly="readOnly"
:type="newstype"
@handleEditStatus="handleEditStatus"
@doNewsPublishFn="doNewsPublishFn"
@doDeleteNewsFn="doDeleteNewsFn"
@getData="getData"
/>
</keep-alive>
<el-dialog v-model="isScoreShow" title="资讯评分详情" width="680" center>
<div class="score-detail">
<el-row class="score-detail-row">
<el-col :span="6" class="score-detail-label">行业分类标注</el-col>
<el-col :span="18">
<el-row>[{{ scoreDetail.industryLabel.join(',') }}]</el-row>
<el-row justify="space-between">
<el-col :span="12">置信度:[{{ scoreDetail.industryConfidence.join(',') }}]</el-col>
<el-col :span="12" style="text-align: right"
>分类评分:<span style="color: #36a4f8">[{{ scoreDetail.industryScore.join(',') }}]</span></el-col
>
</el-row>
</el-col>
</el-row>
<el-row class="score-detail-row">
<el-col :span="6" class="score-detail-label">概念标签标注</el-col>
<el-col :span="18">
<el-row>[{{ scoreDetail.conceptLabel.join(',') }}]</el-row>
<el-row justify="space-between">
<el-col :span="12">置信度:[{{ scoreDetail.conceptConfidence.join(',') }}]</el-col>
<el-col :span="12" style="text-align: right"
>概念评分:<span style="color: #36a4f8">[{{ scoreDetail.conceptScore.join(',') }}]</span></el-col
>
</el-row>
</el-col>
</el-row>
<el-row class="score-detail-row rule" style="border-bottom: 1px solid #ccc; padding-bottom: 12px">
<el-col :span="24">*计算规则</el-col>
<el-col :span="24">资讯行业or概念指标得分=资讯评分*行业or概念中的置信度</el-col>
</el-row>
<el-row class="score-detail-row">
<el-col :span="12">媒体影响力</el-col>
<el-col :span="12" style="text-align: right"
>评分:<span style="color: #36a4f8">{{ scoreDetail.sourceImpact }}</span></el-col
>
</el-row>
<el-row class="score-detail-row">
<el-col :span="12">中国股市相关性</el-col>
<el-col :span="12" style="text-align: right"
>置信度:<span style="color: #36a4f8">{{ scoreDetail.chinaFactor }}</span></el-col
>
</el-row>
<el-row class="score-detail-row">
<el-col :span="12">资讯质量</el-col>
<el-col :span="12" style="text-align: right"
>评分:<span style="color: #36a4f8">{{ scoreDetail.publicOpinionScore }}</span></el-col
>
</el-row>
<el-row class="score-detail-row rule">
<el-col :span="24">*计算规则</el-col>
<el-col :span="24">资讯评分=媒体影响力分*0.04+资讯质量分*0.25+中国股市相关分*35</el-col>
</el-row>
<el-row class="score-detail-row" justify="space-between">
<el-col :span="12">资讯评分</el-col>
<el-col :span="12" style="color: #36a4f8; text-align: right; font-weight: 700">{{ scoreDetail.newsScore }}</el-col>
</el-row>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="isScoreShow = false">关闭</el-button>
</div>
</template>
</el-dialog>
<recordDialog ref="recordDialogRef" @handleClose="recordDialogClose"></recordDialog>
</div>
</template>
<script setup lang="ts" name="loginIndex">
import { computed, onMounted, reactive, ref } from 'vue';
import { NextLoading } from '/@/utils/loading';
import { ElMessage, ElMessageBox } from 'element-plus';
import tableComponents from '/@/components/tableComponents/index.vue';
import { useRoute, useRouter } from 'vue-router';
import icon_table_filter from '/@/assets/icon_table_filter.png';
import DetailDrawer from './DetailDrawer/index.vue';
import {
doNewRevoke,
doNewSubmit,
searchCompany,
getNews,
doNewsPublish,
doDeleteNews,
getColumn,
getNewsScore,
getIndustryHierarchy,
getTagSource,
doRecover,
doNewCheck,
doNewReturn,
getSignalRules,
getRealTotal,
} from '/@/api/api';
import { highlightTitle } from '/@/utils/highlight';
import clipboard from 'clipboard';
import { Session } from '/@/utils/storage';
import recordDialog from './dialog/recordDialog.vue';
import { isMobileByWidth } from '/@/utils/Utils';
import zTable from './zTable.vue';
const recordDialogRef = ref();
/** 管理后台需求文件0519V1.1 start */
const drawer = ref(false);
const newsData = ref<any>();
const readOnly = ref(false);
const newstype = ref(0);
const daterange = ref('');
/** 管理后台需求文件0519V1.1 end */
// 多选的栏目
const checkList = ref([]);
const route = useRoute();
const router = useRouter();
const form = ref({
// orderBy: 'updateTime$desc',
orderBy: null,
// direction: 'desc',
keyword: '',
minScore: '',
maxScore: '',
industry: [],
});
const tableData = reactive({
data: [],
total: 0,
page: 1,
size: 10,
});
const tableLoading = ref(false);
/**
* 进入详情页
* @param type 0创建 1编辑
*/
function goDetail(type, item, readonly) {
readOnly.value = readonly;
newsData.value = item;
newstype.value = type;
drawer.value = true;
}
function goRecord(item) {
recordDialogRef.value.showModal(item);
}
async function doDeleteNewsFn(item) {
ElMessageBox.confirm('是否确认删除本篇资讯?删除后将回收不可发布', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
let { code, data } = await doDeleteNews({
id: item.id,
});
if (code == 200) {
ElMessage.success('操作成功');
drawer.value = false;
getData();
}
})
.catch(() => {});
}
function handleSearch() {
tableData.page = 1;
getData();
}
function initPageData() {
let _sdate = '';
let _edate = '';
if (daterange.value) {
_sdate = daterange.value[0];
_edate = daterange.value[1];
}
const industry = form.value.industry?.length > 0 ? encodeURIComponent(JSON.stringify(form.value.industry)) : '';
return {
...form.value,
industry,
// page: tableData.page,
current: tableData.page,
size: tableData.size,
dateline_from: _sdate || undefined,
dateline_to: _edate || undefined,
range: Session.get('userInfoLocal').userType == '01' ? 'review' : Session.get('userInfoLocal').userType == '02' ? 'secondReview' : 'all',
includeRuleIds: includeRuleIds.value,
excludeRuleIds: excludeRuleIds.value,
clusterSwitch: Session.get('userInfoLocal').userType != '00' ? null : hadExpand.value,
};
}
function handleExpandChange() {
// hadExpand.value = !hadExpand.value;
getData();
}
const hadExpand = ref(true);
// 获取列表
async function getData() {
// return
if (form.value.minScore && form.value.maxScore && Number(form.value.maxScore) < Number(form.value.minScore)) {
ElMessage.error('最高分不能小于最低分');
return;
}
try {
tableLoading.value = true;
let { code, data, total } = await getNews(initPageData());
tableLoading.value = false;
if (code == 200) {
tableData.data = data;
tableData.total = total;
tableData.data.forEach((item, index) => {
item.columns.forEach((childItem, childIndex) => {
if (childIndex < 2) {
if (!item.columnsMin) {
item.columnsMin = [];
}
item.columnsMin.push(childItem);
}
});
item.title = highlightTitle(item.title, form.value.keyword);
if (item.clusterNews && item.clusterNews?.length > 0) {
item.clusterNews.forEach((clusterItem, clusterIndex) => {
clusterItem.childLength = item.clusterNews?.length || 0;
clusterItem.clusterIndex = clusterIndex;
});
}
});
}
} catch (error) {
tableLoading.value = false;
}
}
function getRealTotalFn() {
getRealTotal(initPageData()).then((res) => {
if (res.code == 200) {
tableData.realTotal = res.data;
}
});
}
async function doApprovalFn(item, status) {
let str = '确认初审完成并提交复核?送审后不支持再次编辑';
if (status == 3 || status == 4) {
str = '确认撤销该篇资讯审核?';
} else {
str = '确认初审完成并提交复核?送审后不支持再次编辑';
}
ElMessageBox.confirm(str, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
let { code } =
status == 3 || status == 4
? await doNewRevoke({
id: item.id,
})
: await doNewSubmit({
id: item.id,
});
if (code == 200) {
ElMessage.success('操作成功');
drawer.value = false;
getData();
}
})
.catch(() => {});
}
/**
* 上下架
* @param item
* @param status 1下架 2上架
*/
async function doNewsPublishFn(item, status) {
let str = '请确认要下架该篇资讯?撤稿后前台将不可见本文章';
if (status == 1) {
str = '请确认要下架该篇资讯?撤稿后前台将不可见本文章';
} else {
str = '请确认已审核该篇资讯,发布后前台将展示本资讯';
}
ElMessageBox.confirm(str, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
let { code } =
status == 1
? await doNewRevoke({
id: item.id,
status: status,
})
: await doNewsPublish({
id: item.id,
status: status,
});
if (code == 200) {
ElMessage.success('操作成功');
drawer.value = false;
getData();
}
})
.catch(() => {});
}
/**
* 表格排序改变
* @param row
*/
// 排序规则状态(记录多列排序)
const sortRules = reactive({
score: null, // null | 'score$asc' | 'score$desc'
updateTime: null,
publishTime: null,
});
function sortChange({ prop, order }) {
// 原来的逻辑是每次排序叠加条件
// 现在不需要,每次都是一个排序条件
sortRules['publishTime'] = null;
sortRules['score'] = null;
sortRules['updateTime'] = null;
if (prop == 'updateTime') {
sortRules['publishTime'] = null;
} else if (prop == 'publishTime') {
sortRules['updateTime'] = null;
}
sortRules[prop] = order == 'ascending' ? '$asc' : order == 'descending' ? '$desc' : null;
let sortVal = [];
for (let key in sortRules) {
if (sortRules[key]) {
sortVal.push(key + sortRules[key]);
}
}
form.value.orderBy = encodeURIComponent(sortVal.join(';'));
getData();
}
async function copyUrl(res) {
let clipboardBean = new clipboard('.copyBtn', {
text: function (trigger) {
//返回的就是复制的内容,可以在返回前面对数据进行增强等...
// http://192.168.31.5:8881/#/pages/detail/index?id=0&needPay=0&type=article
ElMessage.success('复制成功');
return import.meta.env.VITE_API_URL_H5 + '/#/pages/realtimeInfo/pc/indexPC?id=' + res.id + '&type=2';
},
});
clipboardBean.on('success', function (e) {
console.log('成功复制...');
//复制完成后销毁clipboard对象预防下一次调用会多次提示
clipboardBean.destroy();
});
clipboardBean.on('error', function (e) {
console.log('失败...');
//复制完成后销毁clipboard对象预防下一次调用会多次提示
clipboardBean.destroy();
});
}
function handleCommand(val) {
form.value.status = val;
getData();
}
function handleCommand2(val) {
form.value.politicalSensitivity = val;
getData();
}
function handleCommandRating(val) {
form.value.rating = val;
getData();
}
const columnList = ref([]);
// 获取栏目
async function getColumnFn(parent) {
let { code, data } = await getColumn({
page: 1,
size: 100000,
parent,
});
if (code == 200) {
return data;
} else {
return [];
}
}
function checkChange(val) {
let str = '';
val.forEach((item, index) => {
if (index < val.length - 1) {
str = str + item + ',';
} else {
str = str + item;
}
});
if (val.length > 0) {
form.value.column = str;
} else {
delete form.value.column;
}
getData();
}
function currentChange(val) {
tableData.page = val;
getData();
}
function sizeChange(val) {
tableData.size = val;
getData();
}
function toDetail(data: any, val: boolean) {
readOnly.value = val;
newsData.value = data;
drawer.value = true;
}
function handleEditStatus(val: boolean) {
readOnly.value = val;
}
// 资讯评分详情
const isScoreShow = ref(false);
const curScore = ref(0);
const scoreDetail = ref<any>({});
const isAdmin = computed(() => {
console.log('🚀 ~ route.query.admin :', route.query.admin);
return route.query.admin == 'superman' || Session.get('userInfoLocal').userType == '02' || Session.get('userInfoLocal').userType == '01'
? true
: false;
});
async function getScoreDetail(id: any) {
if (!isAdmin.value) return;
curScore.value = id;
const result = await getNewsScore({ id });
if (result.code == 200) {
scoreDetail.value = result.data;
isScoreShow.value = true;
}
}
const industryList = ref([]);
const defaultProps = {
children: 'children',
label: 'name',
};
async function getIndustryList() {
const result = await getIndustryHierarchy();
if (result.code == 200) {
industryList.value = result.data;
}
}
function handleCheckChange(node, checked, indeterminate) {
form.value.industry = checked.checkedKeys;
handleSearch();
}
function formatTime(time: string) {
return new Date(time).getTime();
}
// 来源标签列表
const tagSourceList = ref([]);
async function getTagSourceFn() {
let { code, data } = await getTagSource({
page: 1,
size: 100000,
});
if (code == 200) {
tagSourceList.value = data.map((item: any) => {
return {
label: item.name,
value: item.id,
};
});
}
}
const tableRef = ref();
function restData() {
form.value.keyword = null;
form.value.industry = null;
form.value.tag = null;
daterange.value = null;
form.value.minScore = null;
form.value.maxScore = null;
form.value.mediaId = null;
form.value.deleted = null;
form.value.status = null;
form.value.rating = null;
form.value.orderBy = null;
tableRef.value.clearSort();
tableData.page = 1;
form.value.includeRuleIds = null;
form.value.excludeRuleIds = null;
includeRuleIds.value = null;
excludeRuleIds.value = null;
form.value.companyName = null;
form.value.exclusive = null;
getData();
}
// 恢复已删除资讯接口
async function doRecoverFn(item) {
ElMessageBox.confirm('确认恢复该条资讯?请确认无敏感信息', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
let { code } = await doRecover(item);
if (code == 200) {
ElMessage.success('操作成功');
drawer.value = false;
getData();
}
})
.catch(() => {});
}
// 复审
async function doNewCheckFn(item) {
let { code, data } = await doNewCheck({
id: item.id,
});
if (code == 200) {
ElMessage.success('操作成功');
getData();
}
}
// 退改
async function doNewReturnFn(item) {
let { code, data } = await doNewReturn({
id: item.id,
});
if (code == 200) {
ElMessage.success('操作成功');
getData();
}
}
const signalRulesList = ref([
{
label: '全部',
value: 1,
},
{
label: '全部1',
value: 2,
},
]);
async function getSignalRulesFn() {
let { code, data } = await getSignalRules({});
if (code == 200) {
signalRulesList.value = data;
}
}
const includeRuleIds = ref('');
const excludeRuleIds = ref('');
function signalChange(event, type) {
if (type == 1) {
// form.value.signalId1 = signalId1.value;
includeRuleIds.value = event.join(',');
// excludeRuleIds.value = null;
} else {
// form.value.signalId2 = signalId2.value;
excludeRuleIds.value = event.join(',');
// includeRuleIds.value = null;
}
getData();
}
import { debounce } from '/@/utils/utils';
const companyList = ref([]);
const getCompany = debounce(async (val: string) => {
// if (!val) {
// return;
// }
let { code, data } = await searchCompany({
companyName: val,
});
if (code == 200) {
companyList.value = data;
// data.forEach((item) => {
// companyList.value.push({
// label: item.companyName,
// value: item.companyName,
// });
// });
}
}, 500);
// 页面加载时
onMounted(async () => {
if (isMobileByWidth() && (Session.get('userInfoLocal').userType == '01' || Session.get('userInfoLocal').userType == '02')) {
router.push('/richeditMobile');
}
NextLoading.done();
getTagSourceFn();
getData();
getIndustryList();
let arr = [];
arr = await getColumnFn(1);
if (arr) {
arr.forEach((item) => {
columnList.value.push(item);
});
}
let arr1 = [];
arr1 = await getColumnFn(null);
if (arr1) {
arr1.forEach((item) => {
if (item.name == '天下事' || item.name == '早知道') {
columnList.value.push(item);
}
});
}
if (Session.get('userInfoLocal').userType == '00') {
getSignalRulesFn();
}
getCompany();
// 判断有没有折叠菜单
if (Session.get('userInfoLocal').userType != '00') {
hadExpand.value = false;
} else {
// 会进来这里说明这个页面是资讯精选
getRealTotalFn();
hadExpand.value = true;
}
});
</script>
<style scoped lang="scss">
.index {
background-color: white;
padding: 20px;
border-radius: 10px;
}
.option {
display: flex;
flex-direction: column;
text-align: center;
justify-content: center;
align-items: center;
width: 100%;
:deep(.el-button--large) {
padding: 0;
height: 35px;
}
:deep(.is-disabled) {
color: rgba(24, 144, 255, 0.4);
}
}
.r_point {
display: flex;
align-items: center;
gap: 5px;
font-weight: 400;
}
.point {
width: 8px;
height: 8px;
border-radius: 100px;
}
.columns {
display: flex;
gap: 5px;
.column_item {
border: 1px solid #d9d9d9;
background-color: #fafafa;
padding: 2px 5px;
height: 30px;
text-wrap: nowrap;
}
}
:deep(.highlight) {
color: #ff0000;
font-weight: bold;
}
.score-active {
cursor: pointer;
font-weight: 700;
color: #36a4f8;
}
.score-hover {
&:hover {
cursor: pointer;
font-weight: 700;
color: #36a4f8;
}
}
.score-detail {
font-size: 14px;
color: #333333;
.score-detail-row {
margin-top: 24px;
}
.rule {
font-size: 12px;
color: #8e8e8e;
}
}
.colHeader {
align-items: flex-start;
display: flex;
flex-direction: column;
}
.colHeader-right {
flex: 1;
display: flex;
flex-direction: column;
// align-items: flex-end;
// min-width: 700px;
.colHeader-right-1,
.colHeader-right-2 {
display: flex;
// justify-self: flex-end;
align-items: center;
margin-bottom: 10px;
}
}
.labels {
display: flex;
gap: 5px;
flex-wrap: wrap;
.label_item {
height: 24px;
background: #f6f6f6;
border-radius: 2px;
border: 1px solid #e2e2e2;
padding: 0 5px;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #656363;
line-height: 16px;
text-align: left;
font-style: normal;
display: flex;
text-align: center;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
white-space: nowrap;
}
}
.label_item_box {
// width: 100%;
display: flex;
gap: 5px;
}
:deep(.el-table td.el-table__cell div) {
display: flex;
align-items: center;
justify-content: center;
}
.el-button + .el-button {
margin-left: 0px;
}
.record_btn {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: #6b6c6f;
line-height: 20px;
text-align: left;
font-style: normal;
cursor: pointer;
}
:deep(.el-switch__label.is-active) {
color: #4e4e4e;
}
</style>