自动化详情页 任务显示
This commit is contained in:
@@ -19,8 +19,8 @@ const service = axios.create({
|
|||||||
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
||||||
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
||||||
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
||||||
// baseURL: '/api', //本地
|
baseURL: '/api', //本地
|
||||||
baseURL: '/', //正式
|
// baseURL: '/', //正式
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1243,6 +1243,7 @@ colTitle: 'Template title',
|
|||||||
,
|
,
|
||||||
autoPromotionLogs: {
|
autoPromotionLogs: {
|
||||||
detail: 'Auto Promotion Details',
|
detail: 'Auto Promotion Details',
|
||||||
|
pipelineHistory: 'PIPELINE HISTORY',
|
||||||
factoryTaskSelectPlaceholder: 'Select promotion task',
|
factoryTaskSelectPlaceholder: 'Select promotion task',
|
||||||
configured: 'Configured',
|
configured: 'Configured',
|
||||||
editConfig: 'Edit auto promotion configuration',
|
editConfig: 'Edit auto promotion configuration',
|
||||||
@@ -1310,6 +1311,7 @@ colTitle: 'Template title',
|
|||||||
taskLogState2: 'Failed',
|
taskLogState2: 'Failed',
|
||||||
taskLogState3: 'Bounced',
|
taskLogState3: 'Bounced',
|
||||||
taskLogState4: 'Cancelled',
|
taskLogState4: 'Cancelled',
|
||||||
|
logColIndex: 'No.',
|
||||||
logColExpert: 'Expert',
|
logColExpert: 'Expert',
|
||||||
logColSendTime: 'Sent at',
|
logColSendTime: 'Sent at',
|
||||||
logColPreparedAt: 'Prepared at',
|
logColPreparedAt: 'Prepared at',
|
||||||
|
|||||||
@@ -1228,6 +1228,7 @@ const zh = {
|
|||||||
,
|
,
|
||||||
autoPromotionLogs: {
|
autoPromotionLogs: {
|
||||||
detail: '自动推广详情',
|
detail: '自动推广详情',
|
||||||
|
pipelineHistory: '流水线历史',
|
||||||
factoryTaskSelectPlaceholder: '选择推广任务',
|
factoryTaskSelectPlaceholder: '选择推广任务',
|
||||||
configured: '已配置',
|
configured: '已配置',
|
||||||
editConfig: '修改期刊自动推广配置',
|
editConfig: '修改期刊自动推广配置',
|
||||||
@@ -1295,6 +1296,7 @@ const zh = {
|
|||||||
taskLogState2: '失败',
|
taskLogState2: '失败',
|
||||||
taskLogState3: '退信',
|
taskLogState3: '退信',
|
||||||
taskLogState4: '取消',
|
taskLogState4: '取消',
|
||||||
|
logColIndex: '序号',
|
||||||
logColExpert: '专家信息',
|
logColExpert: '专家信息',
|
||||||
logColSendTime: '发送时间',
|
logColSendTime: '发送时间',
|
||||||
logColPreparedAt: '预处理完成时间',
|
logColPreparedAt: '预处理完成时间',
|
||||||
|
|||||||
@@ -19,19 +19,46 @@
|
|||||||
<el-select
|
<el-select
|
||||||
v-if="config.initialized && selectedJournalId"
|
v-if="config.initialized && selectedJournalId"
|
||||||
v-model="headerPromotionFactoryId"
|
v-model="headerPromotionFactoryId"
|
||||||
class="header-factory-task-select"
|
class="header-factory-task-select custom-pipeline-select"
|
||||||
size="small"
|
size="small"
|
||||||
filterable
|
filterable
|
||||||
:loading="factoryTasksHeaderLoading"
|
:loading="factoryTasksHeaderLoading"
|
||||||
:placeholder="$t('autoPromotionLogs.factoryTaskSelectPlaceholder')"
|
:placeholder="$t('autoPromotionLogs.factoryTaskSelectPlaceholder')"
|
||||||
@change="onHeaderFactoryTaskChange"
|
@change="onHeaderFactoryTaskChange"
|
||||||
|
popper-class="pipeline-popper"
|
||||||
>
|
>
|
||||||
<el-option
|
|
||||||
v-for="opt in factoryTaskOptions"
|
|
||||||
:key="opt.value"
|
<el-option-group >
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
<el-option
|
||||||
/>
|
v-for="opt in factoryTaskOptions"
|
||||||
|
:key="opt.value"
|
||||||
|
:label="opt.label"
|
||||||
|
:value="opt.value"
|
||||||
|
class="pipeline-option"
|
||||||
|
>
|
||||||
|
<div class="option-content">
|
||||||
|
<div class="row-top">
|
||||||
|
<span class="task-title">{{ mapFactoryTaskTypeLabel(opt.task.type) }}</span>
|
||||||
|
<el-tag :type="getStatusType(opt.task.start_promotion)" size="mini" effect="plain" class="status-tag">
|
||||||
|
{{ opt.task.start_promotion==1 ? $t('autoPromotion.running') : $t('autoPromotion.stopped') }}
|
||||||
|
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="row-bottom">
|
||||||
|
<span class="meta-item database">{{ mapFactoryExpertTypeLabel(opt.task.expert_type) }}</span>
|
||||||
|
<template v-if="opt.task.expert_type==5">
|
||||||
|
<span class="separator">•</span>
|
||||||
|
<span class="meta-item region">{{ opt.task.country_scope_label }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<span class="separator">•</span>
|
||||||
|
<span class="meta-item time">{{ opt.task.ctime_text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
|
</el-option-group>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-tag
|
<el-tag
|
||||||
v-if="config.initialized && selectedJournalId && headerFactoryTaskRunning !== null"
|
v-if="config.initialized && selectedJournalId && headerFactoryTaskRunning !== null"
|
||||||
@@ -45,19 +72,10 @@
|
|||||||
{{ headerFactoryTaskRunning ? $t('autoPromotion.running') : $t('autoPromotion.stopped') }}
|
{{ headerFactoryTaskRunning ? $t('autoPromotion.running') : $t('autoPromotion.stopped') }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
|
||||||
<!-- <template v-if="config.initialized"> -->
|
<el-button type="text" size="small" style="margin-left: 10px" @click="openFactoryTaskDialogFromLogs">
|
||||||
<!-- <el-tag type="success" size="small" effect="plain" style="margin-left: 10px">
|
<i class="el-icon-edit"></i>
|
||||||
<i class="el-icon-circle-check"></i> {{ $t('autoPromotionLogs.configured') }}
|
{{ config.initialized ? $t('autoPromotionLogs.editConfig') : $t('autoPromotionLogs.startConfig') }}
|
||||||
</el-tag> -->
|
</el-button>
|
||||||
<el-button type="text" size="small" style="margin-left: 10px" @click="openFactoryTaskDialogFromLogs">
|
|
||||||
<i class="el-icon-edit"></i>
|
|
||||||
{{ config.initialized ? $t('autoPromotionLogs.editConfig') : $t('autoPromotionLogs.startConfig') }}
|
|
||||||
</el-button>
|
|
||||||
<!-- </template> -->
|
|
||||||
|
|
||||||
<!-- <el-tag v-else type="info" size="small" effect="plain" style="margin-left: 10px">
|
|
||||||
<i class="el-icon-info"></i> {{ $t('autoPromotionLogs.notConfigured') }}
|
|
||||||
</el-tag> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="config.initialized && selectedJournalId && headerPromotionFactoryId" class="right">
|
<div v-if="config.initialized && selectedJournalId && headerPromotionFactoryId" class="right">
|
||||||
<el-button
|
<el-button
|
||||||
@@ -100,8 +118,6 @@
|
|||||||
|
|
||||||
<div v-else class="manage-mode">
|
<div v-else class="manage-mode">
|
||||||
<el-card shadow="never" class="list-card">
|
<el-card shadow="never" class="list-card">
|
||||||
|
|
||||||
|
|
||||||
<div class="filter-header-row">
|
<div class="filter-header-row">
|
||||||
<div class="tmr-capsule-group">
|
<div class="tmr-capsule-group">
|
||||||
<el-tabs v-model="query.state" type="card" @tab-click="handleTabClick">
|
<el-tabs v-model="query.state" type="card" @tab-click="handleTabClick">
|
||||||
@@ -135,7 +151,9 @@
|
|||||||
<div class="task-column">
|
<div class="task-column">
|
||||||
<div class="task-name">{{ scope.row.task_name || '-' }}</div>
|
<div class="task-name">{{ scope.row.task_name || '-' }}</div>
|
||||||
<div class="task-id-tags">
|
<div class="task-id-tags">
|
||||||
<span class="id-tag">{{ $t('autoPromotionLogs.templateIdLabel') }}: {{ scope.row.template_id }}</span>
|
<span class="id-tag"
|
||||||
|
>{{ $t('autoPromotionLogs.templateIdLabel') }}: {{ scope.row.template_id }}</span
|
||||||
|
>
|
||||||
<span class="id-tag">{{ $t('autoPromotionLogs.styleIdLabel') }}: {{ scope.row.style_id }}</span>
|
<span class="id-tag">{{ $t('autoPromotionLogs.styleIdLabel') }}: {{ scope.row.style_id }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -224,7 +242,11 @@
|
|||||||
:icon="String(scope.row.state) === '5' ? 'el-icon-edit-outline' : 'el-icon-view'"
|
:icon="String(scope.row.state) === '5' ? 'el-icon-edit-outline' : 'el-icon-view'"
|
||||||
@click="previewRow(scope.row)"
|
@click="previewRow(scope.row)"
|
||||||
>
|
>
|
||||||
{{ String(scope.row.state) === '5' ? $t('autoPromotionLogs.editAction') : $t('autoPromotionLogs.previewAction') }}
|
{{
|
||||||
|
String(scope.row.state) === '5'
|
||||||
|
? $t('autoPromotionLogs.editAction')
|
||||||
|
: $t('autoPromotionLogs.previewAction')
|
||||||
|
}}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -427,6 +449,36 @@ export default {
|
|||||||
const opt = this.factoryTaskOptions.find((o) => String(o.value) === id);
|
const opt = this.factoryTaskOptions.find((o) => String(o.value) === id);
|
||||||
if (opt && typeof opt.running === 'boolean') return opt.running;
|
if (opt && typeof opt.running === 'boolean') return opt.running;
|
||||||
return null;
|
return null;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 顶部 select 前缀展示用:与 headerPromotionFactoryId 对应的 option(含 task)。
|
||||||
|
* URL 回退插入的占位项可能没有 task,这里统一成可安全渲染的对象。
|
||||||
|
*/
|
||||||
|
currentSelectedTask() {
|
||||||
|
const emptyTask = { type: '', ctime_text: '' };
|
||||||
|
const id = String(this.headerPromotionFactoryId || '').trim();
|
||||||
|
if (!id || !Array.isArray(this.factoryTaskOptions) || !this.factoryTaskOptions.length) {
|
||||||
|
return { value: '', label: '', running: false, task: { ...emptyTask } };
|
||||||
|
}
|
||||||
|
const opt = this.factoryTaskOptions.find((o) => String(o.value) === id);
|
||||||
|
if (!opt) {
|
||||||
|
return { value: id, label: id, running: false, task: { ...emptyTask } };
|
||||||
|
}
|
||||||
|
const raw = opt.task && typeof opt.task === 'object' ? opt.task : {};
|
||||||
|
const ctimeText =
|
||||||
|
raw.ctime_text != null && String(raw.ctime_text).trim() !== ''
|
||||||
|
? String(raw.ctime_text).trim()
|
||||||
|
: this.formatFactoryHeaderTaskCreateTime(raw);
|
||||||
|
return {
|
||||||
|
value: opt.value,
|
||||||
|
label: opt.label,
|
||||||
|
running: typeof opt.running === 'boolean' ? opt.running : this.isFactoryHeaderTaskRunning(raw),
|
||||||
|
task: {
|
||||||
|
...raw,
|
||||||
|
type: raw.type != null ? String(raw.type) : '',
|
||||||
|
ctime_text: ctimeText || ''
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -445,12 +497,33 @@ export default {
|
|||||||
this.initPage();
|
this.initPage();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
mapFactoryTaskTypeLabel(type) {
|
||||||
|
const t = String(type || '');
|
||||||
|
if (t === '1') return this.$t('autoPromotion.factoryScenarioSolicit');
|
||||||
|
if (t === '2') return this.$t('autoPromotion.factoryScenarioPromoteCitation');
|
||||||
|
if (t === '3') return this.$t('autoPromotion.factoryScenarioGeneralThanks');
|
||||||
|
if (t === '4') return this.$t('autoPromotion.autoSolicit');
|
||||||
|
return this.$t('autoPromotion.autoSolicit');
|
||||||
|
},
|
||||||
|
mapFactoryExpertTypeLabel(expertType) {
|
||||||
|
const t = String(expertType || '').trim();
|
||||||
|
if (t === '1') return this.$t('autoPromotion.factoryExpertChief');
|
||||||
|
if (t === '2') return this.$t('autoPromotion.factoryExpertBoard');
|
||||||
|
if (t === '3') return this.$t('autoPromotion.factoryExpertYoungBoard');
|
||||||
|
if (t === '4') return this.$t('autoPromotion.factoryExpertAuthor');
|
||||||
|
if (t === '5') return this.$t('autoPromotion.factoryExpertDb');
|
||||||
|
return '-';
|
||||||
|
},
|
||||||
|
getStatusType(status) {
|
||||||
|
|
||||||
|
return status==1?'success':'info';
|
||||||
|
},
|
||||||
handleTabClick(tab) {
|
handleTabClick(tab) {
|
||||||
// tab.name 对应的就是原来的 value ("0", "1" 等)
|
// tab.name 对应的就是原来的 value ("0", "1" 等)
|
||||||
// 注意:el-tabs 的 v-model 绑定的是字符串
|
// 注意:el-tabs 的 v-model 绑定的是字符串
|
||||||
this.query.state = tab.name;
|
this.query.state = tab.name;
|
||||||
this.handleStateChange(); // 触发你原有的搜索逻辑
|
this.handleStateChange(); // 触发你原有的搜索逻辑
|
||||||
},
|
},
|
||||||
getPercent(row) {
|
getPercent(row) {
|
||||||
if (!row.total_count || row.total_count === 0) return 0;
|
if (!row.total_count || row.total_count === 0) return 0;
|
||||||
// 计算已发送占比
|
// 计算已发送占比
|
||||||
@@ -554,9 +627,7 @@ export default {
|
|||||||
this.hidePage = false;
|
this.hidePage = false;
|
||||||
var journal_id = (this.$route.query && this.$route.query.journal_id) || '';
|
var journal_id = (this.$route.query && this.$route.query.journal_id) || '';
|
||||||
var pfid =
|
var pfid =
|
||||||
(this.$route.query && this.$route.query.promotion_factory_id) ||
|
(this.$route.query && this.$route.query.promotion_factory_id) || (this.$route.query && this.$route.query.taskId) || '';
|
||||||
(this.$route.query && this.$route.query.taskId) ||
|
|
||||||
'';
|
|
||||||
this.routePromotionFactoryId = String(pfid || '');
|
this.routePromotionFactoryId = String(pfid || '');
|
||||||
this.headerPromotionFactoryId = this.routePromotionFactoryId;
|
this.headerPromotionFactoryId = this.routePromotionFactoryId;
|
||||||
this.selectedJournalId = String(journal_id);
|
this.selectedJournalId = String(journal_id);
|
||||||
@@ -662,7 +733,7 @@ export default {
|
|||||||
}
|
}
|
||||||
if (!dt || isNaN(dt.getTime())) return String(raw).trim();
|
if (!dt || isNaN(dt.getTime())) return String(raw).trim();
|
||||||
const pad = (v) => String(v).padStart(2, '0');
|
const pad = (v) => String(v).padStart(2, '0');
|
||||||
return `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())} ${pad(dt.getHours())}:${pad(dt.getMinutes())}:${pad(dt.getSeconds())}`;
|
return `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())}`;
|
||||||
},
|
},
|
||||||
isFactoryHeaderTaskRunning(task) {
|
isFactoryHeaderTaskRunning(task) {
|
||||||
if (!task || typeof task !== 'object') return false;
|
if (!task || typeof task !== 'object') return false;
|
||||||
@@ -676,9 +747,12 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 下拉仅展示「类型 - 创建日期」,运行状态单独用 el-tag */
|
/** 下拉仅展示「类型 - 创建日期」,运行状态单独用 el-tag */
|
||||||
buildFactoryHeaderOptionMainLabel(task, pidFallback) {
|
buildFactoryHeaderOptionMainLabel(task, pidFallback) {
|
||||||
|
console.log("🚀 ~ buildFactoryHeaderOptionMainLabel ~ task:", task);
|
||||||
|
|
||||||
const typePart = this.getFactoryHeaderTaskTypeLabel(task) || String(pidFallback || '').trim() || '—';
|
const typePart = this.getFactoryHeaderTaskTypeLabel(task) || String(pidFallback || '').trim() || '—';
|
||||||
|
const expertTypePart = this.mapFactoryExpertTypeLabel(task.expert_type);
|
||||||
const datePart = this.formatFactoryHeaderTaskCreateTime(task);
|
const datePart = this.formatFactoryHeaderTaskCreateTime(task);
|
||||||
return datePart ? `${typePart} - ${datePart}` : typePart;
|
return datePart ? `${typePart} | ${expertTypePart}${task.expert_type==5 ? ` | ${task.country_scope_label} ` :''} | ${datePart}` : typePart;
|
||||||
},
|
},
|
||||||
replacePromotionFactoryIdInUrl(promotionFactoryId) {
|
replacePromotionFactoryIdInUrl(promotionFactoryId) {
|
||||||
try {
|
try {
|
||||||
@@ -704,18 +778,20 @@ export default {
|
|||||||
});
|
});
|
||||||
const payload = (res && res.data) || {};
|
const payload = (res && res.data) || {};
|
||||||
const list = this.findArray(payload) || this.findArray(res) || [];
|
const list = this.findArray(payload) || this.findArray(res) || [];
|
||||||
let opts = (Array.isArray(list) ? list : []).map((task, idx) => {
|
let opts = (Array.isArray(list) ? list : [])
|
||||||
const pid =
|
.map((task, idx) => {
|
||||||
task && task.promotion_factory_id != null
|
const pid =
|
||||||
? String(task.promotion_factory_id)
|
task && task.promotion_factory_id != null
|
||||||
: task && task.id != null
|
? String(task.promotion_factory_id)
|
||||||
? String(task.id)
|
: task && task.id != null
|
||||||
: '';
|
? String(task.id)
|
||||||
if (!pid) return null;
|
: '';
|
||||||
const label = this.buildFactoryHeaderOptionMainLabel(task, pid);
|
if (!pid) return null;
|
||||||
const running = this.isFactoryHeaderTaskRunning(task);
|
const label = this.buildFactoryHeaderOptionMainLabel(task, pid);
|
||||||
return { value: pid, label, running };
|
const running = this.isFactoryHeaderTaskRunning(task);
|
||||||
}).filter(Boolean);
|
return { value: pid, label, running,task:task }
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
let cur = String(this.routePromotionFactoryId || this.headerPromotionFactoryId || '').trim();
|
let cur = String(this.routePromotionFactoryId || this.headerPromotionFactoryId || '').trim();
|
||||||
const ids = new Set(opts.map((o) => o.value));
|
const ids = new Set(opts.map((o) => o.value));
|
||||||
@@ -799,10 +875,14 @@ export default {
|
|||||||
selectedPayload.country_fetch_ids != null
|
selectedPayload.country_fetch_ids != null
|
||||||
? selectedPayload.country_fetch_ids
|
? selectedPayload.country_fetch_ids
|
||||||
: selectedPayload.country_ids != null
|
: selectedPayload.country_ids != null
|
||||||
? selectedPayload.country_ids
|
? selectedPayload.country_ids
|
||||||
: '';
|
: '';
|
||||||
if (typeof raw === 'string' && raw.trim()) {
|
if (typeof raw === 'string' && raw.trim()) {
|
||||||
return raw.split(',').map((s) => s.trim()).filter(Boolean).map(String);
|
return raw
|
||||||
|
.split(',')
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(String);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@@ -825,7 +905,7 @@ export default {
|
|||||||
let availableArr = this.findArray(availablePayload);
|
let availableArr = this.findArray(availablePayload);
|
||||||
if (!availableArr) availableArr = Array.isArray(availablePayload) ? availablePayload : [];
|
if (!availableArr) availableArr = Array.isArray(availablePayload) ? availablePayload : [];
|
||||||
this.availableFields = availableArr.map((item, idx) => {
|
this.availableFields = availableArr.map((item, idx) => {
|
||||||
const id = item.expert_fetch_id || item.fetch_id || item.id || item.field_id || (idx + 1);
|
const id = item.expert_fetch_id || item.fetch_id || item.id || item.field_id || idx + 1;
|
||||||
const label = item.field || item.title || item.name || item.label || String(id);
|
const label = item.field || item.title || item.name || item.label || String(id);
|
||||||
return { id: String(id), label };
|
return { id: String(id), label };
|
||||||
});
|
});
|
||||||
@@ -898,10 +978,10 @@ export default {
|
|||||||
matched.promotion_factory_id != null
|
matched.promotion_factory_id != null
|
||||||
? String(matched.promotion_factory_id)
|
? String(matched.promotion_factory_id)
|
||||||
: matched.id != null
|
: matched.id != null
|
||||||
? String(matched.id)
|
? String(matched.id)
|
||||||
: matched.task_id != null
|
: matched.task_id != null
|
||||||
? String(matched.task_id)
|
? String(matched.task_id)
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// promotion_factory/getDetail 必须使用地址栏 promotion_factory_id,避免列表首行 id 与路由不一致
|
// promotion_factory/getDetail 必须使用地址栏 promotion_factory_id,避免列表首行 id 与路由不一致
|
||||||
@@ -1048,11 +1128,7 @@ export default {
|
|||||||
const runAt = item.run_at || item.run_time || item.plan_time || item.execute_time || item.send_date || '';
|
const runAt = item.run_at || item.run_time || item.plan_time || item.execute_time || item.send_date || '';
|
||||||
const state = String(item.state != null ? item.state : '');
|
const state = String(item.state != null ? item.state : '');
|
||||||
const promotionFactoryId =
|
const promotionFactoryId =
|
||||||
item.promotion_factory_id != null
|
item.promotion_factory_id != null ? item.promotion_factory_id : item.id != null ? item.id : item.task_id;
|
||||||
? item.promotion_factory_id
|
|
||||||
: item.id != null
|
|
||||||
? item.id
|
|
||||||
: item.task_id;
|
|
||||||
return {
|
return {
|
||||||
id: item.id || item.task_id || `task_${idx + 1}`,
|
id: item.id || item.task_id || `task_${idx + 1}`,
|
||||||
promotion_factory_id: promotionFactoryId != null ? String(promotionFactoryId) : '',
|
promotion_factory_id: promotionFactoryId != null ? String(promotionFactoryId) : '',
|
||||||
@@ -1206,16 +1282,16 @@ export default {
|
|||||||
return Object.prototype.hasOwnProperty.call(stateTextMap, key) ? stateTextMap[key] : '-';
|
return Object.prototype.hasOwnProperty.call(stateTextMap, key) ? stateTextMap[key] : '-';
|
||||||
},
|
},
|
||||||
getTaskStatusClass(state) {
|
getTaskStatusClass(state) {
|
||||||
const stateClassMap = {
|
const stateClassMap = {
|
||||||
0: 'status-draft', // Draft - 浅灰色
|
0: 'status-draft', // Draft - 浅灰色
|
||||||
5: 'status-preparing', // Preparing - 橘色
|
5: 'status-preparing', // Preparing - 橘色
|
||||||
1: 'status-running', // Running - 深蓝色
|
1: 'status-running', // Running - 深蓝色
|
||||||
2: 'status-paused', // Paused - 深灰色
|
2: 'status-paused', // Paused - 深灰色
|
||||||
3: 'status-completed', // Completed - 绿色
|
3: 'status-completed', // Completed - 绿色
|
||||||
4: 'status-cancelled' // Cancelled - 浅红色
|
4: 'status-cancelled' // Cancelled - 浅红色
|
||||||
};
|
};
|
||||||
return stateClassMap[Number(state)] || '';
|
return stateClassMap[Number(state)] || '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -1229,11 +1305,13 @@ export default {
|
|||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
.config-bar {
|
.config-bar {
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.config-bar .left {
|
.config-bar .left {
|
||||||
|
width: calc(100% - 100px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1758,96 +1836,96 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-header-row {
|
.filter-header-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center; /* 垂直居中对齐 */
|
align-items: center; /* 垂直居中对齐 */
|
||||||
gap: 16px; /* 胶囊和Search按钮之间的间距 */
|
gap: 16px; /* 胶囊和Search按钮之间的间距 */
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
background-color: transparent; /* 容器透明,不厚重 */
|
background-color: transparent; /* 容器透明,不厚重 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. 彻底重置 el-tabs 的原生样式 (最丑的地方) */
|
/* 2. 彻底重置 el-tabs 的原生样式 (最丑的地方) */
|
||||||
.tmr-capsule-group {
|
.tmr-capsule-group {
|
||||||
flex: 1; /* 占据左侧空间 */
|
flex: 1; /* 占据左侧空间 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 强制隐藏默认灰色横线和卡片灰边 */
|
/* 强制隐藏默认灰色横线和卡片灰边 */
|
||||||
.tmr-capsule-group .el-tabs__header {
|
.tmr-capsule-group .el-tabs__header {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
border-bottom: none !important;
|
border-bottom: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tmr-capsule-group .el-tabs__nav {
|
.tmr-capsule-group .el-tabs__nav {
|
||||||
border: none !important;
|
border: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. 重新定义每个 Tab 的样式 (让其变成按钮) */
|
/* 3. 重新定义每个 Tab 的样式 (让其变成按钮) */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item {
|
||||||
height: 32px !important; /* 紧凑高度 */
|
height: 32px !important; /* 紧凑高度 */
|
||||||
line-height: 32px !important;
|
line-height: 32px !important;
|
||||||
font-size: 13px; /* 紧凑字体 */
|
font-size: 13px; /* 紧凑字体 */
|
||||||
border: none !important; /* 彻底隐藏原生卡片边框 */
|
border: none !important; /* 彻底隐藏原生卡片边框 */
|
||||||
background-color: transparent; /* 默认状态下透明背景 */
|
background-color: transparent; /* 默认状态下透明背景 */
|
||||||
color: #515a6e; /* 默认状态深灰文字,更专业 */
|
color: #515a6e; /* 默认状态深灰文字,更专业 */
|
||||||
transition: all 0.2s ease-in-out;
|
transition: all 0.2s ease-in-out;
|
||||||
padding: 0 16px !important; /* 适当内边距 */
|
padding: 0 16px !important; /* 适当内边距 */
|
||||||
margin-right: 8px; /* 每个 Tab 之间的间距 */
|
margin-right: 8px; /* 每个 Tab 之间的间距 */
|
||||||
border-radius: 6px !important; /* 先统一圆角 */
|
border-radius: 6px !important; /* 先统一圆角 */
|
||||||
overflow: visible; /* 确保选中的阴影显示完全 */
|
overflow: visible; /* 确保选中的阴影显示完全 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 首尾 Tab 的圆角处理 (形成整体感) */
|
/* 首尾 Tab 的圆角处理 (形成整体感) */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:first-child {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:first-child {
|
||||||
border-top-left-radius: 6px;
|
border-top-left-radius: 6px;
|
||||||
border-bottom-left-radius: 6px;
|
border-bottom-left-radius: 6px;
|
||||||
}
|
}
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:last-child {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:last-child {
|
||||||
border-top-right-radius: 6px;
|
border-top-right-radius: 6px;
|
||||||
border-bottom-right-radius: 6px;
|
border-bottom-right-radius: 6px;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 中间 Tab 的处理 (去掉左右圆角,紧凑对齐) */
|
/* 中间 Tab 的处理 (去掉左右圆角,紧凑对齐) */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:not(:first-child):not(:last-child) {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:not(:first-child):not(:last-child) {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. **选中效果 (Active) - 胶囊浮动核心** */
|
/* 4. **选中效果 (Active) - 胶囊浮动核心** */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
|
||||||
background-color: #ffffff !important; /* 白色底色 */
|
background-color: #ffffff !important; /* 白色底色 */
|
||||||
color: #409eff !important; /* 主题蓝色文字 */
|
color: #409eff !important; /* 主题蓝色文字 */
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important; /* **关键:增加轻微阴影,浮动感** */
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important; /* **关键:增加轻微阴影,浮动感** */
|
||||||
border-radius: 6px; /* 选中时恢复圆角 */
|
border-radius: 6px; /* 选中时恢复圆角 */
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2; /* 确保选中态在最前面,不被覆盖线破坏 */
|
z-index: 2; /* 确保选中态在最前面,不被覆盖线破坏 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 5. 处理 Tab 之间的断层 (像素级微调) */
|
/* 5. 处理 Tab 之间的断层 (像素级微调) */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 首尾 Tab 之间的像素级处理 */
|
/* 首尾 Tab 之间的像素级处理 */
|
||||||
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:not(:last-child)::after {
|
.tmr-capsule-group .el-tabs--card > .el-tabs__header .el-tabs__item:not(:last-child)::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -5px; /* 让 Tab 之间紧密无缝 */
|
right: -5px; /* 让 Tab 之间紧密无缝 */
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
background: transparent; /* 移除灰线,不丑 */
|
background: transparent; /* 移除灰线,不丑 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 6. 搜索按钮对齐微调 */
|
/* 6. 搜索按钮对齐微调 */
|
||||||
.filter-actions .el-button {
|
.filter-actions .el-button {
|
||||||
height: 32px; /* 与 Tab 高度一致 */
|
height: 32px; /* 与 Tab 高度一致 */
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-actions {
|
.filter-actions {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
/* 基础 Badge 样式 */
|
/* 基础 Badge 样式 */
|
||||||
.status-badge {
|
.status-badge {
|
||||||
@@ -1894,14 +1972,18 @@ export default {
|
|||||||
background-color: #f1f5f9;
|
background-color: #f1f5f9;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
.status-draft::before { background-color: #94a3b8; }
|
.status-draft::before {
|
||||||
|
background-color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
/* 5: Preparing - 橘色 */
|
/* 5: Preparing - 橘色 */
|
||||||
.status-preparing {
|
.status-preparing {
|
||||||
background-color: #fff7ed;
|
background-color: #fff7ed;
|
||||||
color: #c2410c;
|
color: #c2410c;
|
||||||
}
|
}
|
||||||
.status-preparing::before { background-color: #f97316; }
|
.status-preparing::before {
|
||||||
|
background-color: #f97316;
|
||||||
|
}
|
||||||
|
|
||||||
/* 1: Running - 深蓝色 */
|
/* 1: Running - 深蓝色 */
|
||||||
.status-running {
|
.status-running {
|
||||||
@@ -1919,19 +2001,104 @@ export default {
|
|||||||
color: #334155;
|
color: #334155;
|
||||||
border: 1px solid #e2e8f0; /* 停用状态加个微边框增加分量感 */
|
border: 1px solid #e2e8f0; /* 停用状态加个微边框增加分量感 */
|
||||||
}
|
}
|
||||||
.status-paused::before { background-color: #475569; }
|
.status-paused::before {
|
||||||
|
background-color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
/* 3: Completed - 绿色 */
|
/* 3: Completed - 绿色 */
|
||||||
.status-completed {
|
.status-completed {
|
||||||
background-color: #f0fdf4;
|
background-color: #f0fdf4;
|
||||||
color: #15803d;
|
color: #15803d;
|
||||||
}
|
}
|
||||||
.status-completed::before { background-color: #22c55e; }
|
.status-completed::before {
|
||||||
|
background-color: #22c55e;
|
||||||
|
}
|
||||||
|
|
||||||
/* 4: Cancelled - 浅红色 */
|
/* 4: Cancelled - 浅红色 */
|
||||||
.status-cancelled {
|
.status-cancelled {
|
||||||
background-color: #fef2f2;
|
background-color: #fef2f2;
|
||||||
color: #b91c1c;
|
color: #b91c1c;
|
||||||
}
|
}
|
||||||
.status-cancelled::before { background-color: #ef4444; }
|
.status-cancelled::before {
|
||||||
|
background-color: #ef4444;
|
||||||
|
}
|
||||||
|
/* 基础 Select 宽度 */
|
||||||
|
.custom-pipeline-select {
|
||||||
|
width: 580px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分组标题(el-option-group,避免在 ul 内放 div) */
|
||||||
|
.pipeline-popper .el-select-group__title {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #909399;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
border-bottom: 1px solid #f0f2f5;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 单个选项容器 */
|
||||||
|
.pipeline-popper .el-select-dropdown__item {
|
||||||
|
height: auto; /* 允许高度自适应 */
|
||||||
|
padding: 12px 20px;
|
||||||
|
line-height: normal;
|
||||||
|
border-left: 3px solid transparent; /* 预留边框位置防止抖动 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中状态 */
|
||||||
|
.pipeline-popper .el-select-dropdown__item.selected {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-left: 3px solid #409eff; /* 选中时的左侧蓝条 */
|
||||||
|
color: #606266; /* 覆盖 Element 默认高亮色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选项内容布局 */
|
||||||
|
.pipeline-popper .option-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 第一行:标题 + 状态标签 */
|
||||||
|
.pipeline-popper .option-content .row-top {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pipeline-popper .option-content .row-top .task-title {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pipeline-popper .option-content .row-top .status-tag {
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 0 8px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 第二行:元数据信息 */
|
||||||
|
.pipeline-popper .option-content .row-bottom {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pipeline-popper .option-content .row-bottom .meta-item.database {
|
||||||
|
color: #5856d6;
|
||||||
|
font-weight: bold;
|
||||||
|
/* text-transform: uppercase; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pipeline-popper .option-content .row-bottom .separator {
|
||||||
|
margin: 0 6px;
|
||||||
|
color: #dcdfe6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -59,20 +59,22 @@
|
|||||||
|
|
||||||
<div class="drawer-body" v-loading="loading">
|
<div class="drawer-body" v-loading="loading">
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
|
<div class="col-index">{{ $t('autoPromotionLogs.logColIndex') }}</div>
|
||||||
<div class="col-info">{{ $t('autoPromotionLogs.logColExpert') }}</div>
|
<div class="col-info">{{ $t('autoPromotionLogs.logColExpert') }}</div>
|
||||||
<div class="col-send" style="font-size: 12px;">{{ $t('autoPromotionLogs.logColSendTime') }}</div>
|
<div class="col-send" style="font-size: 12px;">{{ $t('autoPromotionLogs.logColSendTime') }}</div>
|
||||||
<div class="col-prepared" style="font-size: 12px;">{{ $t('autoPromotionLogs.logColPreparedAt') }}</div>
|
<div class="col-prepared" style="font-size: 12px;">{{ $t('autoPromotionLogs.logColPreparedAt') }}</div>
|
||||||
<div class="col-status">{{ $t('autoPromotionLogs.logColStatus') }}</div>
|
<div class="col-status">{{ $t('autoPromotionLogs.logColStatus') }}</div>
|
||||||
<div class="col-action">{{ $t('autoPromotionLogs.logColAction') }}</div>
|
<div class="col-action"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-wrapper">
|
<div class="list-wrapper">
|
||||||
<div
|
<div
|
||||||
v-for="item in fullData"
|
v-for="(item, rowIndex) in fullData"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="log-row"
|
class="log-row"
|
||||||
:class="{ 'row-error': item.isErrorRow }"
|
:class="{ 'row-error': item.isErrorRow }"
|
||||||
>
|
>
|
||||||
|
<div class="col-index">{{ (currentPage - 1) * pageSize + rowIndex + 1 }}</div>
|
||||||
<div class="col-info">
|
<div class="col-info">
|
||||||
<div class="expert-main">
|
<div class="expert-main">
|
||||||
<span class="name">{{ item.expertName }}</span>
|
<span class="name">{{ item.expertName }}</span>
|
||||||
@@ -782,6 +784,14 @@ export default {
|
|||||||
color: #475569;
|
color: #475569;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.col-index {
|
||||||
|
flex: 0 0 52px;
|
||||||
|
width: 52px;
|
||||||
|
text-align: center;
|
||||||
|
color: #64748b;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
.col-info {
|
.col-info {
|
||||||
flex: 1.8;
|
flex: 1.8;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user