任务工厂列表版
This commit is contained in:
@@ -19,8 +19,8 @@ const service = axios.create({
|
||||
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
||||
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
||||
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
||||
// baseURL: '/api', //本地
|
||||
baseURL: '/', //正式
|
||||
baseURL: '/api', //本地
|
||||
// baseURL: '/', //正式
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1107,6 +1107,11 @@ colTitle: 'Template title',
|
||||
selectPromotionCountryTip: 'Multiple selection supported; leave empty for no country restriction. Uses the same API as fields until a dedicated country list is available.',
|
||||
fieldSearchPlaceholder: 'Search promotion fields',
|
||||
countrySearchPlaceholder: 'Search countries',
|
||||
countryQuickZone1: 'Partition 1',
|
||||
countryQuickZone2: 'Partition 2',
|
||||
countryQuickZone3: 'Partition 3',
|
||||
countryQuickChina: 'China',
|
||||
countryQuickIndia: 'India',
|
||||
noFieldMatch: 'No matching fields',
|
||||
noCountryMatch: 'No matching countries',
|
||||
confirm: 'Confirm',
|
||||
@@ -1114,7 +1119,68 @@ colTitle: 'Template title',
|
||||
countriesSaved: 'Promotion countries saved',
|
||||
confirmAndEnable: 'Confirm and Enable',
|
||||
onlySaveConfig: 'Save configuration only',
|
||||
enableNowNextDay: 'Enable auto promotion now (starts next day)'
|
||||
enableNowNextDay: 'Enable auto promotion now (starts next day)',
|
||||
factoryCreateBtn: 'Create automated promotion task',
|
||||
factoryDialogTitle: 'Create task',
|
||||
factoryJournal: 'Journal',
|
||||
factoryJournalPlaceholder: 'Select a journal',
|
||||
factorySendSettings: 'Sending & scenario',
|
||||
factoryEmails: 'Sender accounts',
|
||||
factoryEmailsPlaceholder: 'Select one or more sender accounts',
|
||||
factorySendCount: 'Send count',
|
||||
factoryType: 'Scenario',
|
||||
factoryTypeEditor: 'Editor',
|
||||
factoryTypeArticle: 'Promote article',
|
||||
factoryExpertType: 'Expert type',
|
||||
factoryExpertTypePlaceholder: 'Optional; follow backend rules',
|
||||
factorySubmit: 'Submit task',
|
||||
factorySubmitSuccess: 'Factory task created',
|
||||
factorySubmitFailed: 'Create failed, please try again later',
|
||||
factoryNeedJournal: 'Please select a journal first',
|
||||
factoryNeedTemplate: 'Please select email template and style',
|
||||
factoryNeedEmails: 'Please select at least one sender account',
|
||||
factoryNeedExpertType: 'Please select target person type',
|
||||
factoryEmailsPickJournal: 'Select a journal to load sender accounts',
|
||||
factoryNoAccounts: 'No mailbox accounts for this journal',
|
||||
factoryAccountRemaining: 'Remaining today',
|
||||
factorySendMaxFromApi: 'limit: up to {max} per day',
|
||||
factorySendMaxFallback: 'using mailbox quota sum ~{max} (or default cap)',
|
||||
factoryStepNav1Title: 'Journal',
|
||||
factoryStepNav1Desc: 'Select a journal first.',
|
||||
factoryStepNav2Title: 'Email template and style',
|
||||
factoryStepNav2Desc: 'Choose template and style.',
|
||||
factoryStepNav3Title: 'Sending and scenario',
|
||||
factoryStepNav3Desc: 'Choose accounts, send count, and target type.',
|
||||
factoryStepNav4Title: 'Promotion fields',
|
||||
factoryStepNav4Desc: 'Select at least one promotion field.',
|
||||
factoryStepNav5Title: 'Country',
|
||||
factoryStepNav5Desc: 'Select at least one country or partition.',
|
||||
factoryStepNav6Title: 'Confirm and enable',
|
||||
factoryStepNav6Desc: 'Choose save only or enable next day.',
|
||||
factoryPromotionFieldsBlockTip: 'Open “Choose fields” and tick at least one item; do not submit with none selected.',
|
||||
factoryPromotionCountryBlockTip: 'Tick at least one partition or country; do not submit with none selected.',
|
||||
factoryNeedPromotionFields: 'Select at least one promotion field before submitting.',
|
||||
factoryNeedPromotionCountry: 'Select at least one partition or country before submitting.',
|
||||
factoryQuotaLabel: 'Quota',
|
||||
factoryClickSelectTemplate: 'Click to select email template',
|
||||
factoryClickConfigureFields: 'Click to configure subject fields',
|
||||
factoryBtnModify: 'Edit',
|
||||
factoryBtnReset: 'Reset',
|
||||
factoryBtnCancel: 'Cancel',
|
||||
factoryBtnSubmit: 'Submit task',
|
||||
factoryFillRequired: 'Please complete journal, template, and at least one sender account',
|
||||
factoryExpertChief: 'Editor-in-Chief',
|
||||
factoryExpertBoard: 'Editorial board',
|
||||
factoryExpertYoungBoard: 'Young editorial board',
|
||||
factoryExpertAuthor: 'Author',
|
||||
factoryExpertDb: 'Expert database',
|
||||
factoryScenario: 'Scenario',
|
||||
factoryScenarioPlaceholder: 'Select scenario',
|
||||
factoryScenarioSolicit: 'Invite Submission',
|
||||
factoryScenarioPromoteCitation: 'Promote Citation',
|
||||
factoryScenarioGeneralThanks: 'General Thanks',
|
||||
noFactoryTask: 'No tasks',
|
||||
factoryCreateNow: 'Create now'
|
||||
}
|
||||
,
|
||||
autoPromotionLogs: {
|
||||
|
||||
@@ -1092,6 +1092,11 @@ const zh = {
|
||||
selectPromotionCountryTip: '可多选;未选择则不限制国家。与领域接口一致,后续可对接独立国家数据。',
|
||||
fieldSearchPlaceholder: '搜索推广领域',
|
||||
countrySearchPlaceholder: '搜索国家',
|
||||
countryQuickZone1: '1区',
|
||||
countryQuickZone2: '2区',
|
||||
countryQuickZone3: '3区',
|
||||
countryQuickChina: 'China',
|
||||
countryQuickIndia: 'India',
|
||||
noFieldMatch: '没有匹配的领域',
|
||||
noCountryMatch: '没有匹配的国家',
|
||||
confirm: '确定',
|
||||
@@ -1099,7 +1104,68 @@ const zh = {
|
||||
countriesSaved: '推广国家已保存',
|
||||
confirmAndEnable: '确认并开启',
|
||||
onlySaveConfig: '仅保存配置',
|
||||
enableNowNextDay: '立即激活自动推广(次日开始自动推广)'
|
||||
enableNowNextDay: '立即激活自动推广(次日开始自动推广)',
|
||||
factoryCreateBtn: '创建自动化推广任务',
|
||||
factoryDialogTitle: '创建任务',
|
||||
factoryJournal: '期刊',
|
||||
factoryJournalPlaceholder: '请选择期刊',
|
||||
factorySendSettings: '发送与场景',
|
||||
factoryEmails: '发送邮箱',
|
||||
factoryEmailsPlaceholder: '请选择发送账号(可多选)',
|
||||
factorySendCount: '发送数量',
|
||||
factoryType: '场景类型',
|
||||
factoryTypeEditor: '编辑',
|
||||
factoryTypeArticle: '推广文章',
|
||||
factoryExpertType: '专家类型',
|
||||
factoryExpertTypePlaceholder: '可选,按后端要求填写',
|
||||
factorySubmit: '提交任务',
|
||||
factorySubmitSuccess: '工厂任务已创建',
|
||||
factorySubmitFailed: '创建失败,请稍后重试',
|
||||
factoryNeedJournal: '请先选择期刊',
|
||||
factoryNeedTemplate: '请先选择邮件模板与样式',
|
||||
factoryNeedEmails: '请至少选择一个发送邮箱',
|
||||
factoryNeedExpertType: '请选择目标人类型',
|
||||
factoryEmailsPickJournal: '请先选择期刊以加载邮箱列表',
|
||||
factoryNoAccounts: '该期刊下暂无可用邮箱账号',
|
||||
factoryAccountRemaining: '今日剩余',
|
||||
factorySendMaxFromApi: '接口限制:单日最多 {max} 封',
|
||||
factorySendMaxFallback: '未返回接口上限,当前按邮箱额度合计约 {max} 封(或默认上限)',
|
||||
factoryStepNav1Title: '期刊',
|
||||
factoryStepNav1Desc: '先选期刊,未选不能提交。',
|
||||
factoryStepNav2Title: '邮件模版与样式',
|
||||
factoryStepNav2Desc: '选好邮件模板和样式。',
|
||||
factoryStepNav3Title: '发送与场景',
|
||||
factoryStepNav3Desc: '选账号,填发送数量和目标人类型。',
|
||||
factoryStepNav4Title: '推广领域',
|
||||
factoryStepNav4Desc: '至少选择一个推广领域。',
|
||||
factoryStepNav5Title: '国家',
|
||||
factoryStepNav5Desc: '至少选择一个国家或分区。',
|
||||
factoryStepNav6Title: '确认并开启',
|
||||
factoryStepNav6Desc: '选择仅保存或次日自动开启。',
|
||||
factoryPromotionFieldsBlockTip: '请打开「选择领域」,在列表中至少勾选一项;不得留空提交。',
|
||||
factoryPromotionCountryBlockTip: '请至少勾选一项分区或国家;不得留空提交。',
|
||||
factoryNeedPromotionFields: '请至少选择一项推广领域后再提交。',
|
||||
factoryNeedPromotionCountry: '请至少选择一项分区或国家后再提交。',
|
||||
factoryQuotaLabel: '额度',
|
||||
factoryClickSelectTemplate: '点击选择邮件模板',
|
||||
factoryClickConfigureFields: '点击配置学科字段',
|
||||
factoryBtnModify: '修改',
|
||||
factoryBtnReset: '重置',
|
||||
factoryBtnCancel: '取消',
|
||||
factoryBtnSubmit: '立即提交任务',
|
||||
factoryFillRequired: '请完善必填信息(期刊、模板、账号)',
|
||||
factoryExpertChief: '主编',
|
||||
factoryExpertBoard: '编委',
|
||||
factoryExpertYoungBoard: '青年编委',
|
||||
factoryExpertAuthor: '作者',
|
||||
factoryExpertDb: 'expert库',
|
||||
factoryScenario: '场景',
|
||||
factoryScenarioPlaceholder: '请选择场景',
|
||||
factoryScenarioSolicit: '约稿',
|
||||
factoryScenarioPromoteCitation: '推广引用',
|
||||
factoryScenarioGeneralThanks: '常规感谢',
|
||||
noFactoryTask: '没有任务',
|
||||
factoryCreateNow: '立即创建'
|
||||
}
|
||||
,
|
||||
autoPromotionLogs: {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
<el-tag type="success" size="small" effect="plain" style="margin-left: 10px">
|
||||
<i class="el-icon-circle-check"></i> {{ $t('autoPromotionLogs.configured') }}
|
||||
</el-tag>
|
||||
<el-button type="text" size="small" style="margin-left: 10px" @click="openWizardDialog">
|
||||
<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>
|
||||
@@ -242,6 +242,15 @@
|
||||
@confirm="handleTemplateApply"
|
||||
@close-all-dialogs="closeAllDialogs"
|
||||
/>
|
||||
<promotion-factory-task-dialog
|
||||
:visible.sync="showFactoryTaskDialog"
|
||||
:initial-journal-id="factoryDialogInitialJournalId"
|
||||
:initial-task="factoryDialogInitialTask"
|
||||
@success="
|
||||
fetchList();
|
||||
fetchJournalDetail();
|
||||
"
|
||||
/>
|
||||
<el-dialog :title="$t('autoPromotionLogs.previewEditTitle')" :visible.sync="showPreviewDialog" width="1200px" top="5vh">
|
||||
<div class="mail-edit-wrapper" v-if="previewForm">
|
||||
<el-form label-width="120px" size="small">
|
||||
@@ -287,6 +296,7 @@
|
||||
import CkeditorMail from '@/components/page/components/email/CkeditorMail.vue';
|
||||
import TemplateSelectorDialog from '@/components/page/components/email/TemplateSelectorDialog.vue';
|
||||
import AutoPromotionWizard from '@/components/page/components/autoPromotion/AutoPromotionWizard.vue';
|
||||
import PromotionFactoryTaskDialog from '@/components/page/components/autoPromotion/PromotionFactoryTaskDialog.vue';
|
||||
import PromotionDetailDrawer from '@/components/page/components/autoPromotion/PromotionDetailDrawer.vue';
|
||||
// 这里假设你已经定义了 API 地址
|
||||
const API = {
|
||||
@@ -300,7 +310,7 @@ const API = {
|
||||
|
||||
export default {
|
||||
name: 'autoPromotion',
|
||||
components: { TemplateSelectorDialog, AutoPromotionWizard, CkeditorMail, PromotionDetailDrawer },
|
||||
components: { TemplateSelectorDialog, AutoPromotionWizard, PromotionFactoryTaskDialog, CkeditorMail, PromotionDetailDrawer },
|
||||
data() {
|
||||
return {
|
||||
handleRefreshList: [],
|
||||
@@ -350,6 +360,9 @@ export default {
|
||||
availableCountries: [],
|
||||
fieldsLoading: false,
|
||||
fieldsSaving: false,
|
||||
showFactoryTaskDialog: false,
|
||||
factoryDialogInitialJournalId: '',
|
||||
factoryDialogInitialTask: null,
|
||||
previewForm: {
|
||||
id: '',
|
||||
email: '',
|
||||
@@ -378,6 +391,7 @@ export default {
|
||||
closeAllDialogs() {
|
||||
// 点击“去新增模板”后:关闭当前页面所有可能的弹窗
|
||||
this.showWizardDialog = false;
|
||||
this.showFactoryTaskDialog = false;
|
||||
this.showTemplateDialog = false;
|
||||
this.showPreviewDialog = false;
|
||||
this.currentRow = null;
|
||||
@@ -659,6 +673,11 @@ export default {
|
||||
}
|
||||
this.showWizardDialog = true;
|
||||
},
|
||||
openFactoryTaskDialogFromLogs() {
|
||||
this.factoryDialogInitialJournalId = this.selectedJournalId ? String(this.selectedJournalId) : '';
|
||||
this.factoryDialogInitialTask = this.list && this.list.length ? { ...this.list[0] } : null;
|
||||
this.showFactoryTaskDialog = true;
|
||||
},
|
||||
|
||||
// 切换期刊逻辑
|
||||
async handleJournalChange() {
|
||||
|
||||
@@ -101,13 +101,13 @@
|
||||
|
||||
<el-divider></el-divider>
|
||||
|
||||
<!-- <section class="form-section">
|
||||
<section class="form-section">
|
||||
<h4 class="section-title">
|
||||
<i class="el-icon-location-outline"></i> 3. {{ $t('autoPromotion.selectPromotionCountry') }}
|
||||
<span class="selected-count">
|
||||
<!-- <span class="selected-count">
|
||||
{{ $t('autoPromotion.selectedCount', { count: selectedCountryIdsProxy.length }) }}
|
||||
</span>
|
||||
<el-button
|
||||
</span> -->
|
||||
<!-- <el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
plain
|
||||
@@ -116,21 +116,31 @@
|
||||
@click="countryDialogVisible = true"
|
||||
>
|
||||
{{ $t('autoPromotion.choosePromotionCountry') }}
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</h4>
|
||||
<div class="status-confirm-box">
|
||||
<div v-if="selectedCountryTagRows.length" class="selected-tags">
|
||||
<el-tag v-for="row in selectedCountryTagRows" :key="'c-' + row.id" size="mini" type="info" effect="plain">{{ row.text }}</el-tag>
|
||||
<div class="country-quick-checks">
|
||||
<div class="field-tip" style="margin-bottom: 10px;">{{ $t('autoPromotion.selectPromotionCountryTip') }}</div>
|
||||
<el-checkbox-group v-model="selectedCountryIdsProxy" size="small">
|
||||
<el-checkbox label="Partition1">{{ $t('autoPromotion.countryQuickZone1') }}</el-checkbox>
|
||||
<el-checkbox label="Partition2">{{ $t('autoPromotion.countryQuickZone2') }}</el-checkbox>
|
||||
<el-checkbox label="Partition3">{{ $t('autoPromotion.countryQuickZone3') }}</el-checkbox>
|
||||
<el-checkbox label="country_china" value="239">{{ $t('autoPromotion.countryQuickChina') }}</el-checkbox>
|
||||
<el-checkbox label="country_india" value="228">{{ $t('autoPromotion.countryQuickIndia') }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="field-tip">{{ $t('autoPromotion.selectPromotionCountryTip') }}</div>
|
||||
<!-- <div v-if="selectedCountryTagRows.length" class="selected-tags">
|
||||
<el-tag v-for="row in selectedCountryTagRows" :key="'c-' + row.id" size="mini" type="info" effect="plain">{{ row.text }}</el-tag>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-divider></el-divider> -->
|
||||
<el-divider></el-divider>
|
||||
|
||||
<section class="form-section">
|
||||
<h4 class="section-title">
|
||||
<i class="el-icon-finished"></i> 3. {{ $t('autoPromotion.confirmAndEnable') }}
|
||||
<i class="el-icon-finished"></i> 4. {{ $t('autoPromotion.confirmAndEnable') }}
|
||||
</h4>
|
||||
|
||||
<div class="status-confirm-box">
|
||||
@@ -317,10 +327,24 @@ export default {
|
||||
(this.availableCountries || []).forEach((i) => {
|
||||
map[String(i.id)] = i.label;
|
||||
});
|
||||
return (this.selectedCountryIdsProxy || []).map((id) => ({
|
||||
id: String(id),
|
||||
text: map[String(id)] != null && map[String(id)] !== '' ? map[String(id)] : String(id)
|
||||
}));
|
||||
const quick = {
|
||||
zone_1: this.$t('autoPromotion.countryQuickZone1'),
|
||||
zone_2: this.$t('autoPromotion.countryQuickZone2'),
|
||||
zone_3: this.$t('autoPromotion.countryQuickZone3'),
|
||||
country_china: this.$t('autoPromotion.countryQuickChina'),
|
||||
country_india: this.$t('autoPromotion.countryQuickIndia')
|
||||
};
|
||||
return (this.selectedCountryIdsProxy || []).map((id) => {
|
||||
const sid = String(id);
|
||||
const fromList = map[sid];
|
||||
const text =
|
||||
fromList != null && fromList !== ''
|
||||
? fromList
|
||||
: quick[sid] != null
|
||||
? quick[sid]
|
||||
: sid;
|
||||
return { id: sid, text };
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -694,5 +718,17 @@ export default {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
.country-quick-checks {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.country-quick-checks >>> .el-checkbox-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 12px 20px;
|
||||
}
|
||||
.country-quick-checks >>> .el-checkbox {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
:close-on-click-modal="false"
|
||||
width="90%"
|
||||
top="5vh"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:before-close="handleClose"
|
||||
custom-class="template-modal"
|
||||
|
||||
Reference in New Issue
Block a user