|
|
@@ -0,0 +1,788 @@
|
|
|
+<template>
|
|
|
+ <div class="intelligent-tagging">
|
|
|
+ <!-- 顶部通知栏 -->
|
|
|
+ <div class="top-notification">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ <span>系统已自动生成标签推荐结果,请您勾选确认准确标签,针对不符合标签可提交反馈内容以优化后续推荐服务;若无适用标签,可通过手动选标完成打标操作。</span>
|
|
|
+ <div class="button-group">
|
|
|
+ <el-button v-if="taggingState === 2 || taggingState === 3" class="cancel-btn" @click="handleCancel">取消</el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ class="confirm-btn"
|
|
|
+ :disabled="selectedTags.length === 0"
|
|
|
+ @click="handleConfirmTagging"
|
|
|
+ >确认打标</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 已选标签 -->
|
|
|
+ <div class="selected-tags">
|
|
|
+ <div class="tags-label">已选标签:</div>
|
|
|
+ <div class="tags-list">
|
|
|
+ <el-tag
|
|
|
+ v-for="(tag, index) in selectedTags"
|
|
|
+ :key="index"
|
|
|
+ :type="getTagType(index)"
|
|
|
+ class="selected-tag"
|
|
|
+ closable
|
|
|
+ @close="handleTagRemove(index)"
|
|
|
+ >
|
|
|
+ {{ tag.tag_name }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 主体内容 -->
|
|
|
+ <div class="main-content">
|
|
|
+ <!-- 左侧标签体系导航 -->
|
|
|
+ <div class="tag-system-nav">
|
|
|
+ <h3 class="nav-title">标签体系</h3>
|
|
|
+ <div class="nav-list">
|
|
|
+ <div
|
|
|
+ v-for="(system, index) in tagSystems"
|
|
|
+ :key="index"
|
|
|
+ class="nav-item"
|
|
|
+ :class="{ 'active': currentSystem === system }"
|
|
|
+ @click="handleSystemSelect(system)"
|
|
|
+ >
|
|
|
+ {{ system }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧内容区域 -->
|
|
|
+ <div class="content-area">
|
|
|
+ <!-- 智能推荐组件 -->
|
|
|
+ <IntelligentRecommend
|
|
|
+ v-if="currentMode === 'intelligent'"
|
|
|
+ :recommendations="tagRecommendations"
|
|
|
+ :current-system="currentSystem"
|
|
|
+ @tagSelect="handleTagSelect"
|
|
|
+ @switchToManual="switchToManual"
|
|
|
+ @retryIntelligentTagging="retryIntelligentTagging"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 人工打标组件 -->
|
|
|
+ <ManualTagging
|
|
|
+ v-else
|
|
|
+ :current-system="currentSystem"
|
|
|
+ :tag-systems-data="tagSystemsData"
|
|
|
+ :selected-tags="selectedTags"
|
|
|
+ @search="handleSearch"
|
|
|
+ @tagCheck="handleTagCheck"
|
|
|
+ @switchToIntelligent="switchToIntelligent"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import IntelligentRecommend from './components/IntelligentRecommend.vue';
|
|
|
+import ManualTagging from './components/ManualTagging.vue';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'ExternalEdit',
|
|
|
+ components: {
|
|
|
+ IntelligentRecommend,
|
|
|
+ ManualTagging
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ businessAttr: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ queryResult: {
|
|
|
+ type: Object,
|
|
|
+ default: null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ testData:{
|
|
|
+ "user_id": "12345",
|
|
|
+ "user_nm": "张三",
|
|
|
+ "contract_no": "TET-2026-03-081613",
|
|
|
+ "user_org": "XX公司",
|
|
|
+ "user_endpoint": "XX网点",
|
|
|
+ },
|
|
|
+ // 当前模式:intelligent(智能推荐)或 manual(人工打标)
|
|
|
+ currentMode: 'intelligent',
|
|
|
+
|
|
|
+ // 当前选中的标签体系
|
|
|
+ currentSystem: '',
|
|
|
+
|
|
|
+ // 标签体系列表
|
|
|
+ tagSystems: [],
|
|
|
+
|
|
|
+ // 完整的标签体系数据
|
|
|
+ tagSystemsData: [],
|
|
|
+
|
|
|
+ // 已选标签(包含标签体系id、标签名称、标签编码)
|
|
|
+ selectedTags: [],
|
|
|
+
|
|
|
+ // 标签推荐结果
|
|
|
+ tagRecommendations: [],
|
|
|
+
|
|
|
+ // 原始推荐数据(用于过滤)
|
|
|
+ originalRecommendations: [],
|
|
|
+
|
|
|
+ // 原始接口返回数据(用于对比判断是否有修改)
|
|
|
+ originalResponseData: null,
|
|
|
+
|
|
|
+ // 打标状态:0-打标执行中;1-打标完成;2-客户经理已经确认;3-结果已推送
|
|
|
+ taggingState: null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // 加载标签体系列表
|
|
|
+ this.loadTagSystems();
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ queryResult: {
|
|
|
+ handler(newVal) {
|
|
|
+ if (newVal) {
|
|
|
+ this.setRecommendations(newVal);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 检查是否有选中的标签
|
|
|
+ hasSelectedTag() {
|
|
|
+ return this.selectedTags.length > 0;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 关闭窗口
|
|
|
+ handleClose() {
|
|
|
+ this.$emit('close');
|
|
|
+ },
|
|
|
+
|
|
|
+ // 取消
|
|
|
+ handleCancel() {
|
|
|
+ this.$emit('close');
|
|
|
+ },
|
|
|
+
|
|
|
+ // 确认打标
|
|
|
+ handleConfirmTagging() {
|
|
|
+ // 检查是否有智能推荐数据或已选标签
|
|
|
+ const hasRecommendations = this.tagRecommendations.length > 0 || this.originalRecommendations.length > 0;
|
|
|
+ if (!this.hasSelectedTag && !hasRecommendations) {
|
|
|
+ this.$message.warning('请至少选择一个标签或等待智能推荐结果');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组装打标数据
|
|
|
+ const taggingData = this.assembleTaggingData();
|
|
|
+ console.log('确认打标数据:', taggingData);
|
|
|
+
|
|
|
+ // 触发确认事件,传递打标数据给父组件
|
|
|
+ this.$emit('confirm', taggingData);
|
|
|
+
|
|
|
+ // 调用反馈接口
|
|
|
+ yufp.service.request({
|
|
|
+ url: backend.tagServer + "/api/fastapi/feedback",
|
|
|
+ method: 'post',
|
|
|
+ data: taggingData,
|
|
|
+ callback: (code, error, response) => {
|
|
|
+ if (response.code == '0') {
|
|
|
+ this.$message.success('打标成功');
|
|
|
+ // 调用父组件的refresh方法重置页面状态
|
|
|
+ this.$emit('refresh');
|
|
|
+ } else {
|
|
|
+ this.$message.error(response.message || '打标失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 组装打标数据
|
|
|
+ assembleTaggingData() {
|
|
|
+ // 从testData中获取基础信息
|
|
|
+ const { user_id, user_nm, contract_no, user_org, user_endpoint } = this.testData;
|
|
|
+
|
|
|
+ // 获取business_attr
|
|
|
+ const business_attr = this.businessAttr;
|
|
|
+
|
|
|
+ // 计算feedback字段
|
|
|
+ const feedback = this.calculateFeedback();
|
|
|
+
|
|
|
+ // 组装feedback_result
|
|
|
+ const feedback_result = this.assembleFeedbackResult();
|
|
|
+
|
|
|
+ // 构建最终数据
|
|
|
+ return {
|
|
|
+ user_id: user_id || '',
|
|
|
+ user_nm: user_nm || '',
|
|
|
+ feedback: feedback,
|
|
|
+ feedback_result: JSON.stringify(feedback_result),
|
|
|
+ contract_no: contract_no || '',
|
|
|
+ user_org: user_org || '',
|
|
|
+ user_endpoint: user_endpoint || '',
|
|
|
+ business_attr: business_attr || ''
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ // 计算feedback字段
|
|
|
+ calculateFeedback() {
|
|
|
+ // 检查是否有初始数据
|
|
|
+ if (!this.originalResponseData || !this.originalResponseData.data || !this.originalResponseData.data.result) {
|
|
|
+ return 'reject';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取初始数据中passr=true的标签
|
|
|
+ const initialSelectedTags = this.originalResponseData.data.result
|
|
|
+ .filter(item => item.passr === true)
|
|
|
+ .map(item => item.tag_code);
|
|
|
+
|
|
|
+ // 获取当前已选标签
|
|
|
+ const currentSelectedTags = this.selectedTags.map(tag => tag.tag_code);
|
|
|
+
|
|
|
+ // 排序后比较
|
|
|
+ initialSelectedTags.sort();
|
|
|
+ currentSelectedTags.sort();
|
|
|
+
|
|
|
+ // 检查长度是否一致
|
|
|
+ if (initialSelectedTags.length !== currentSelectedTags.length) {
|
|
|
+ return 'reject';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查标签是否完全一致
|
|
|
+ for (let i = 0; i < initialSelectedTags.length; i++) {
|
|
|
+ if (initialSelectedTags[i] !== currentSelectedTags[i]) {
|
|
|
+ return 'reject';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 'agree';
|
|
|
+ },
|
|
|
+
|
|
|
+ // 组装feedback_result
|
|
|
+ assembleFeedbackResult() {
|
|
|
+ // 获取所有展示的标签数据(智能推荐或人工打标)
|
|
|
+ let allDisplayedTags = [];
|
|
|
+
|
|
|
+ // 从智能推荐中获取标签
|
|
|
+ if (this.currentMode === 'intelligent' && this.tagRecommendations.length > 0) {
|
|
|
+ allDisplayedTags = this.tagRecommendations;
|
|
|
+ } else if (this.currentMode === 'manual' && this.originalRecommendations.length > 0) {
|
|
|
+ allDisplayedTags = this.originalRecommendations;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建已选标签的集合,用于快速查找
|
|
|
+ const selectedTagCodes = new Set(this.selectedTags.map(tag => tag.tag_code));
|
|
|
+ const selectedTagsMap = new Map(this.selectedTags.map(tag => [tag.tag_code, tag]));
|
|
|
+
|
|
|
+ // 组装feedback_result
|
|
|
+ const feedbackResult = [];
|
|
|
+
|
|
|
+ // 处理所有展示的标签
|
|
|
+ allDisplayedTags.forEach(tag => {
|
|
|
+ const isSelected = selectedTagCodes.has(tag.tag_code);
|
|
|
+ feedbackResult.push({
|
|
|
+ id: tag.id || '',
|
|
|
+ desc: isSelected ? '' : (tag.feedback || ''),
|
|
|
+ passr: isSelected,
|
|
|
+ tag_code: tag.tag_code || '',
|
|
|
+ tag_name: tag.tag_name || '',
|
|
|
+ tag_path: tag.tag_path || '',
|
|
|
+ category_id: tag.category_id || ''
|
|
|
+ });
|
|
|
+ // 从已选标签集合中移除已处理的标签
|
|
|
+ selectedTagCodes.delete(tag.tag_code);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 处理已选标签中存在但展示标签中不存在的标签
|
|
|
+ selectedTagCodes.forEach(tagCode => {
|
|
|
+ const tag = selectedTagsMap.get(tagCode);
|
|
|
+ if (tag) {
|
|
|
+ feedbackResult.push({
|
|
|
+ id: tag.id || '',
|
|
|
+ desc: '',
|
|
|
+ passr: true,
|
|
|
+ tag_code: tag.tag_code || '',
|
|
|
+ tag_name: tag.tag_name || '',
|
|
|
+ tag_path: tag.tag_path || '',
|
|
|
+ category_id: tag.category_id || ''
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return feedbackResult;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择标签
|
|
|
+ handleTagSelect(selectedTags) {
|
|
|
+ // 从选中的标签中提取完整信息,按照要求的数据结构
|
|
|
+ const selectedTagInfos = selectedTags
|
|
|
+ .map(tag => ({
|
|
|
+ id: tag.id || '',
|
|
|
+ desc: tag.feedback || '',
|
|
|
+ passr: tag.selected || tag.passr || false,
|
|
|
+ tag_code: tag.tag_code || '',
|
|
|
+ tag_name: tag.tag_name || '',
|
|
|
+ tag_path: tag.tag_path || '',
|
|
|
+ category_id: tag.category_id || ''
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 更新已选标签
|
|
|
+ this.selectedTags = selectedTagInfos;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 切换到人工打标
|
|
|
+ switchToManual() {
|
|
|
+ this.currentMode = 'manual';
|
|
|
+ // 切换后,手动触发一次标签树数据加载,确保数据正确
|
|
|
+ // 注意:实际加载逻辑在ManualTagging组件的watch中处理
|
|
|
+ },
|
|
|
+
|
|
|
+ // 切换到智能推荐
|
|
|
+ switchToIntelligent() {
|
|
|
+ this.currentMode = 'intelligent';
|
|
|
+ // 更新智能推荐的选中状态
|
|
|
+ this.updateIntelligentSelectedState();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新智能推荐的选中状态
|
|
|
+ updateIntelligentSelectedState() {
|
|
|
+ if (!this.tagRecommendations.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历推荐标签,检查是否在已选标签列表中
|
|
|
+ this.tagRecommendations.forEach(tag => {
|
|
|
+ // 检查是否在已选标签列表中(通过标签编码匹配)
|
|
|
+ tag.selected = this.selectedTags.some(selectedTag =>
|
|
|
+ selectedTag.tag_code === tag.tag_code
|
|
|
+ );
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 重新发起智能打标
|
|
|
+ retryIntelligentTagging() {
|
|
|
+ this.$message.info('重新发起智能打标');
|
|
|
+ // 这里可以添加重新发起智能打标的逻辑
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择标签体系
|
|
|
+ handleSystemSelect(system) {
|
|
|
+ // 如果点击的是当前已选中的体系,则取消选中
|
|
|
+ if (this.currentSystem === system) {
|
|
|
+ this.currentSystem = '';
|
|
|
+ } else {
|
|
|
+ this.currentSystem = system;
|
|
|
+ }
|
|
|
+ // 过滤智能推荐数据,只展示当前体系下的推荐标签
|
|
|
+ this.filterRecommendationsBySystem();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 根据当前选中的标签体系过滤智能推荐数据
|
|
|
+ filterRecommendationsBySystem() {
|
|
|
+ // 保存原始推荐数据
|
|
|
+ if (!this.originalRecommendations) {
|
|
|
+ this.originalRecommendations = [...this.tagRecommendations];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找当前选中的标签体系对应的id
|
|
|
+ const selectedSystem = this.tagSystemsData.find(system => system.categoryNm === this.currentSystem);
|
|
|
+
|
|
|
+ // 如果没有选中标签体系,展示全部数据
|
|
|
+ if (!selectedSystem || !selectedSystem.id) {
|
|
|
+ this.tagRecommendations = [...this.originalRecommendations];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤推荐数据,只保留与当前体系id匹配的推荐标签
|
|
|
+ this.tagRecommendations = this.originalRecommendations.filter(tag => {
|
|
|
+ return tag.category_id == selectedSystem.id;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 加载标签体系列表
|
|
|
+ loadTagSystems() {
|
|
|
+ yufp.service.request({
|
|
|
+ url: backend.tagServer + "/api/aitag-tagcategory/enablelistnoauth",
|
|
|
+ method: 'get',
|
|
|
+ data: {},
|
|
|
+ callback: (code, error, response) => {
|
|
|
+ if (response.code == '0') {
|
|
|
+ // 处理返回的标签体系数据
|
|
|
+ const systems = response.data || [];
|
|
|
+ // 保存完整的标签体系数据
|
|
|
+ this.tagSystemsData = systems;
|
|
|
+ // 更新标签体系列表,使用categoryNm字段
|
|
|
+ this.tagSystems = systems.map(system => system.categoryNm || '').filter(name => name);
|
|
|
+
|
|
|
+ // 默认选中第一个标签体系
|
|
|
+ if (this.tagSystems.length > 0) {
|
|
|
+ this.currentSystem = this.tagSystems[0];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$message.error(response.message || '获取标签体系列表失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理搜索
|
|
|
+ handleSearch(keyword) {
|
|
|
+ console.log('搜索标签:', keyword);
|
|
|
+ // 这里可以添加搜索标签的逻辑
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理标签勾选
|
|
|
+ handleTagCheck(data, checkedInfo) {
|
|
|
+ console.log('勾选标签:', data, checkedInfo);
|
|
|
+
|
|
|
+ // 查找当前选中的标签体系对应的id
|
|
|
+ const selectedSystem = this.tagSystemsData.find(system => system.categoryNm === this.currentSystem);
|
|
|
+ if (!selectedSystem || !selectedSystem.id) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤掉当前体系的标签,保留其他体系的标签
|
|
|
+ const otherSystemTags = this.selectedTags.filter(tag => tag.category_id !== selectedSystem.id);
|
|
|
+
|
|
|
+ // 添加当前选择的标签,按照要求的数据结构
|
|
|
+ const newSelectedTags = [...otherSystemTags, {
|
|
|
+ id: data.id || '',
|
|
|
+ desc: '',
|
|
|
+ passr: true,
|
|
|
+ tag_code: data.tagCode || '',
|
|
|
+ tag_name: data.tagNm || '',
|
|
|
+ tag_path: data.tagPath || '',
|
|
|
+ category_id: selectedSystem.id
|
|
|
+ }];
|
|
|
+
|
|
|
+ // 更新已选标签
|
|
|
+ this.selectedTags = newSelectedTags;
|
|
|
+
|
|
|
+ // 更新智能推荐的选中状态
|
|
|
+ this.updateIntelligentSelectedState();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 删除已选标签
|
|
|
+ handleTagRemove(index) {
|
|
|
+ // 从已选标签列表中移除指定索引的标签
|
|
|
+ this.selectedTags.splice(index, 1);
|
|
|
+
|
|
|
+ // 更新主体内容的选中状态
|
|
|
+ this.updateIntelligentSelectedState();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取标签类型
|
|
|
+ getTagType(index) {
|
|
|
+ const types = ['', 'success', 'warning', 'danger', 'info'];
|
|
|
+ return types[index % types.length];
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理打标执行中状态
|
|
|
+ handleTaggingInProgress() {
|
|
|
+ // 清空推荐数据
|
|
|
+ this.originalRecommendations = [];
|
|
|
+ this.tagRecommendations = [];
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理打标完成状态
|
|
|
+ handleTaggingCompleted(responseData) {
|
|
|
+ if (responseData.result) {
|
|
|
+ const result = responseData.result;
|
|
|
+ // 更新原始推荐数据,使用passr字段设置选中状态
|
|
|
+ this.originalRecommendations = result.map(item => ({
|
|
|
+ ...item,
|
|
|
+ feedback: '',
|
|
|
+ selected: item.passr === true
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 根据passr字段更新已选标签,使用新的数据结构
|
|
|
+ const selectedTags = result
|
|
|
+ .filter(item => item.passr === true)
|
|
|
+ .map(item => ({
|
|
|
+ id: item.id || '',
|
|
|
+ desc: '',
|
|
|
+ passr: true,
|
|
|
+ tag_code: item.tag_code || '',
|
|
|
+ tag_name: item.tag_name || '',
|
|
|
+ tag_path: item.tag_path || '',
|
|
|
+ category_id: item.category_id || ''
|
|
|
+ }));
|
|
|
+ this.selectedTags = selectedTags;
|
|
|
+
|
|
|
+ // 切换到智能推荐模式
|
|
|
+ this.currentMode = 'intelligent';
|
|
|
+ // 根据当前选中的标签体系过滤推荐数据
|
|
|
+ this.filterRecommendationsBySystem();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理已确认或已推送状态
|
|
|
+ handleTaggingConfirmed(responseData) {
|
|
|
+ // 获取feedback_result作为已选择标签数据
|
|
|
+ let feedbackResult = [];
|
|
|
+ if (responseData.feedback_result) {
|
|
|
+ if (typeof responseData.feedback_result === 'string') {
|
|
|
+ try {
|
|
|
+ feedbackResult = JSON.parse(responseData.feedback_result);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('解析feedback_result失败:', error);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ feedbackResult = responseData.feedback_result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置已选标签,只包含feedback_result中passr为true的数据
|
|
|
+ this.selectedTags = feedbackResult
|
|
|
+ .filter(item => item.passr === true)
|
|
|
+ .map(item => ({
|
|
|
+ id: item.id || '',
|
|
|
+ desc: '',
|
|
|
+ passr: true,
|
|
|
+ tag_code: item.tag_code || '',
|
|
|
+ tag_name: item.tag_name || '',
|
|
|
+ tag_path: item.tag_path || '',
|
|
|
+ category_id: item.category_id || ''
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 处理智能推荐数据,根据feedback_result匹配passr字段
|
|
|
+ if (responseData.result) {
|
|
|
+ const result = responseData.result;
|
|
|
+
|
|
|
+ // 创建feedback_result的映射,用于快速查找
|
|
|
+ const feedbackMap = new Map(feedbackResult.map(item => [item.tag_code, item]));
|
|
|
+
|
|
|
+ // 更新原始推荐数据,根据feedback_result设置passr、selected和feedback字段
|
|
|
+ this.originalRecommendations = result.map(item => {
|
|
|
+ const feedbackItem = feedbackMap.get(item.tag_code);
|
|
|
+ const isInFeedback = feedbackItem !== undefined;
|
|
|
+ const isPassrTrue = isInFeedback && feedbackItem.passr === true;
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ passr: isPassrTrue,
|
|
|
+ selected: isPassrTrue,
|
|
|
+ feedback: isPassrTrue ? '' : (feedbackItem ? feedbackItem.desc : '')
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 切换到智能推荐模式
|
|
|
+ this.currentMode = 'intelligent';
|
|
|
+ // 根据当前选中的标签体系过滤推荐数据
|
|
|
+ this.filterRecommendationsBySystem();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 刷新打标结果
|
|
|
+ refreshTaggingResult() {
|
|
|
+ this.$emit('refresh');
|
|
|
+ },
|
|
|
+
|
|
|
+ // 设置推荐数据
|
|
|
+ setRecommendations(data) {
|
|
|
+ this.originalResponseData = data;
|
|
|
+
|
|
|
+ if (data && data.data) {
|
|
|
+ const responseData = data.data;
|
|
|
+
|
|
|
+ // 获取state状态
|
|
|
+ this.taggingState = responseData.state;
|
|
|
+
|
|
|
+ // 根据state状态处理不同的逻辑
|
|
|
+ switch(this.taggingState) {
|
|
|
+ case 0:
|
|
|
+ // 打标执行中,显示loading效果
|
|
|
+ this.handleTaggingInProgress();
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ // 打标完成,正常处理推荐数据
|
|
|
+ this.handleTaggingCompleted(responseData);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ case 3:
|
|
|
+ // 客户经理已经确认或结果已推送,处理feedback_result
|
|
|
+ this.handleTaggingConfirmed(responseData);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ // 默认处理
|
|
|
+ this.handleTaggingCompleted(responseData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.intelligent-tagging {
|
|
|
+ padding: 0;
|
|
|
+ background-color: transparent !important;
|
|
|
+ height: 100% !important;
|
|
|
+ box-shadow: none !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 顶部通知栏 */
|
|
|
+.top-notification {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 20px;
|
|
|
+ background-color: #FFF9E6;
|
|
|
+ border-bottom: 1px solid #FFE7BA;
|
|
|
+}
|
|
|
+
|
|
|
+.top-notification i {
|
|
|
+ color: #E6A23C;
|
|
|
+ margin-right: 12px;
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.top-notification span {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.button-group {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.cancel-btn {
|
|
|
+ margin-right: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-btn {
|
|
|
+ margin-left: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 已选标签 */
|
|
|
+.selected-tags {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 16px 20px;
|
|
|
+ background-color: #F9FAFC;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+}
|
|
|
+
|
|
|
+.tags-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ margin-right: 12px;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.tags-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-tag {
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 主体内容 */
|
|
|
+.main-content {
|
|
|
+ display: flex;
|
|
|
+ min-height: 600px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 左侧标签体系导航 */
|
|
|
+.tag-system-nav {
|
|
|
+ width: 180px;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ border-right: 1px solid #EBEEF5;
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.nav-title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ margin: 0 0 16px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.nav-list {
|
|
|
+ list-style: none;
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.nav-item {
|
|
|
+ padding: 8px 12px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.nav-item:hover {
|
|
|
+ background-color: #ECF5FF;
|
|
|
+ color: #409EFF;
|
|
|
+}
|
|
|
+
|
|
|
+.nav-item.active {
|
|
|
+ background-color: #ECF5FF;
|
|
|
+ color: #409EFF;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+/* 右侧内容区域 */
|
|
|
+.content-area {
|
|
|
+ flex: 1;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式布局 */
|
|
|
+@media screen and (max-width: 768px) {
|
|
|
+ .main-content {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tag-system-nav {
|
|
|
+ width: 100%;
|
|
|
+ border-right: none;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-item {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .top-notification {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .button-group {
|
|
|
+ align-self: flex-end;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cancel-btn {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .confirm-btn {
|
|
|
+ margin-left: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .selected-tags {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|