@@ -158,6 +184,7 @@ export default {
total: 0,
loading: false,
exportLoading: false,
+ switchingExpertId: '',
fieldDetailVisible: false,
fieldDetailExpert: null,
fieldDetailRows: []
@@ -223,8 +250,12 @@ export default {
this.list = rawList.map((item) => {
const fieldArray = item.fields || [];
const fieldNames = fieldArray.map((f) => f.field).join(', ');
+ const unsubscribed = this.normalizeUnsubscribeValue(item);
return {
...item,
+ // 以 unsubscribed 作为页面主判断字段
+ unsubscribed,
+ unsubscribe: unsubscribed,
fieldDisplay: fieldNames
};
});
@@ -240,6 +271,57 @@ export default {
this.loading = false;
}
},
+ getExpertId(row) {
+ if (!row) return '';
+ return String(row.expert_id || row.id || row.user_id || row.uid || '').trim();
+ },
+ normalizeUnsubscribeValue(row) {
+ const raw =
+ row && row.unsubscribed != null
+ ? row.unsubscribed
+ : row && row.unsubscribe != null
+ ? row.unsubscribe
+ : row && row.is_unsubscribe != null
+ ? row.is_unsubscribe
+ : 0;
+ return Number(raw) === 1 ? 1 : 0;
+ },
+ getUnsubscribeValue(row) {
+ return this.normalizeUnsubscribeValue(row);
+ },
+ async handleUnsubscribeSwitch(row, checked) {
+ const expertId = this.getExpertId(row);
+ if (!expertId) {
+ this.$message.warning(this.$t('expertDatabase.unsubscribeMissingId'));
+ return;
+ }
+ const oldValue = this.getUnsubscribeValue(row);
+ // switch: ON(checked)=正常(0), OFF=退订(1)
+ const nextValue = checked ? 0 : 1;
+ if (oldValue === nextValue) return;
+ row.unsubscribed = nextValue;
+ row.unsubscribe = nextValue;
+ this.switchingExpertId = expertId;
+ try {
+ const apiUrl = nextValue === 1 ? 'api/expert_manage/unsubscribe' : 'api/expert_manage/resubscribe';
+ const res = await this.$api.post(apiUrl, {
+ expert_ids: String(expertId)
+ });
+ if (res && Number(res.code) === 0) {
+ this.$message.success(this.$t('expertDatabase.unsubscribeUpdateSuccess'));
+ } else {
+ row.unsubscribed = oldValue;
+ row.unsubscribe = oldValue;
+ this.$message.error((res && res.msg) || this.$t('expertDatabase.unsubscribeUpdateFailed'));
+ }
+ } catch (e) {
+ row.unsubscribed = oldValue;
+ row.unsubscribe = oldValue;
+ this.$message.error(this.$t('expertDatabase.unsubscribeUpdateFailed'));
+ } finally {
+ this.switchingExpertId = '';
+ }
+ },
handleSearch() {
this.query.pageIndex = 1;
this.fetchList();
@@ -390,5 +472,24 @@ export default {
color: #909399;
font-size: 13px;
}
+.unsubscribe-cell {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 10px;
+ padding: 0 4px;
+}
+.unsubscribe-tag {
+ min-width: 56px;
+ height: 22px;
+ line-height: 20px;
+ text-align: center;
+ border-radius: 12px;
+ font-size: 12px;
+}
+.unsubscribe-switch {
+ flex-shrink: 0;
+}
From 56cda2c232398ee6c07c25952594e83081ca85a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com>
Date: Tue, 28 Apr 2026 13:27:09 +0800
Subject: [PATCH 2/8] =?UTF-8?q?=E6=A8=A1=E7=89=88=E5=88=97=E8=A1=A8?=
=?UTF-8?q?=E8=AE=B0=E5=BF=86=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/index.js | 4 ++--
src/components/page/mailboxMould.vue | 24 +++++++++++++++++++++++-
2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/api/index.js b/src/api/index.js
index 525753d..487fb66 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -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: '/', //正式
});
diff --git a/src/components/page/mailboxMould.vue b/src/components/page/mailboxMould.vue
index 4189eaa..6fa837f 100644
--- a/src/components/page/mailboxMould.vue
+++ b/src/components/page/mailboxMould.vue
@@ -147,6 +147,12 @@ const API = {
deleteTemplate: 'api/mail_template/deleteTemplate',
deleteStyle: 'api/mail_template/deleteStyle'
};
+// 仅在当前 SPA 会话内记忆筛选(刷新页面即重置)
+const mailboxMouldSessionMemory = {
+ journalId: '',
+ scene: '',
+ language: ''
+};
export default {
data() {
@@ -203,8 +209,15 @@ export default {
}));
this.journalList = mapped;
if (mapped.length > 0) {
- this.tplFilters.journalId = String(mapped[0].journal_id);
+ const rememberedJournalId = String(mailboxMouldSessionMemory.journalId || '').trim();
+ const hasRemembered = rememberedJournalId && mapped.some(j => String(j.journal_id) === rememberedJournalId);
+ this.tplFilters.journalId = hasRemembered
+ ? rememberedJournalId
+ : String(mapped[0].journal_id);
}
+ this.tplFilters.scene = String(mailboxMouldSessionMemory.scene || '');
+ this.tplFilters.language = String(mailboxMouldSessionMemory.language || '');
+ this.syncTplFilterMemory();
if (this.activeTab === 'styles') {
this.fetchStyles();
} else {
@@ -226,6 +239,11 @@ export default {
},
// ========== Templates ==========
+ syncTplFilterMemory() {
+ mailboxMouldSessionMemory.journalId = String((this.tplFilters && this.tplFilters.journalId) || '');
+ mailboxMouldSessionMemory.scene = String((this.tplFilters && this.tplFilters.scene) || '');
+ mailboxMouldSessionMemory.language = String((this.tplFilters && this.tplFilters.language) || '');
+ },
fetchTemplates() {
this.tplLoading = true;
const params = {
@@ -233,6 +251,7 @@ export default {
scene: this.tplFilters.scene || '',
language: this.tplFilters.language || ''
};
+ this.syncTplFilterMemory();
this.$api
.post(API.listTemplates, params)
.then(res => {
@@ -257,11 +276,13 @@ export default {
});
},
handleCreateTemplate() {
+ this.syncTplFilterMemory();
// 传入当前模板列表选中的期刊,详情页用于默认回填
const journalId = this.tplFilters && this.tplFilters.journalId ? String(this.tplFilters.journalId) : '';
this.$router.push({ path: '/mailboxMouldDetail', query: journalId ? { journal_id: journalId } : {} });
},
handleEditTemplate(row) {
+ this.syncTplFilterMemory();
const templateId = row && (row.template_id || row.id);
const journalId = this.tplFilters && this.tplFilters.journalId ? String(this.tplFilters.journalId) : '';
const query = templateId ? { template_id: String(templateId) } : {};
@@ -274,6 +295,7 @@ export default {
this.previewVisible = true;
},
handleDeleteTemplate(row) {
+ this.syncTplFilterMemory();
const templateId = row && (row.template_id || row.id);
if (!templateId) return;
this.$confirm(this.$t('mailboxMould.deleteConfirm'), this.$t('mailboxMould.colActions'), {
From a4cbce2db7e3190904cf5972a67db45c2fc14832 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com>
Date: Wed, 29 Apr 2026 09:20:47 +0800
Subject: [PATCH 3/8] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E6=A0=B7?=
=?UTF-8?q?=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/common/Header.vue | 1 +
src/components/common/Header2.vue | 1 +
src/components/common/langs/en.js | 2 +
src/components/common/langs/zh.js | 2 +
src/components/page/Login.vue | 4 +
src/components/page/autoPromotion.vue | 21 +-
.../PromotionFactoryTaskDialog.vue | 807 +++++++++++++++---
src/components/page/editorBorder.vue | 61 +-
src/components/page/partyListCorr.vue | 46 +-
src/components/page/reviewerList.vue | 45 +-
src/components/page/youthList.vue | 43 +-
11 files changed, 917 insertions(+), 116 deletions(-)
diff --git a/src/components/common/Header.vue b/src/components/common/Header.vue
index 07fbaac..dfb8064 100644
--- a/src/components/common/Header.vue
+++ b/src/components/common/Header.vue
@@ -176,6 +176,7 @@ export default {
localStorage.removeItem('U_role');
localStorage.removeItem('U_id');
localStorage.removeItem('U_name');
+ localStorage.removeItem('U_email');
localStorage.removeItem('U_status');
localStorage.removeItem('ms_journal_alias');
localStorage.removeItem('journalTypeData');
diff --git a/src/components/common/Header2.vue b/src/components/common/Header2.vue
index e9dcd42..6102e0b 100644
--- a/src/components/common/Header2.vue
+++ b/src/components/common/Header2.vue
@@ -174,6 +174,7 @@ export default {
localStorage.removeItem('U_role');
localStorage.removeItem('U_id');
localStorage.removeItem('U_name');
+ localStorage.removeItem('U_email');
localStorage.removeItem('U_status');
localStorage.removeItem('ms_journal_alias');
localStorage.removeItem('journalTypeData');
diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js
index 1496380..8de3fff 100644
--- a/src/components/common/langs/en.js
+++ b/src/components/common/langs/en.js
@@ -1217,6 +1217,8 @@ colTitle: 'Template title',
factoryExpertYoungBoard: 'Young editorial board',
factoryExpertAuthor: 'Author',
factoryExpertDb: 'Expert database',
+ factoryExpertJump: 'View',
+ factoryOfficialEmailTip: 'For this type, the system uses the official sender email by default. No account selection is required.',
factoryScenario: 'Scenario',
factoryScenarioPlaceholder: 'Select scenario',
factoryScenarioSolicit: 'Invite Submission',
diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js
index 08dc441..91bd8a5 100644
--- a/src/components/common/langs/zh.js
+++ b/src/components/common/langs/zh.js
@@ -1202,6 +1202,8 @@ const zh = {
factoryExpertYoungBoard: '青年编委',
factoryExpertAuthor: '作者',
factoryExpertDb: 'expert库',
+ factoryExpertJump: '查看',
+ factoryOfficialEmailTip: '此类型默认使用系统官方邮箱发送,无需选择邮箱账号。',
factoryScenario: '场景',
factoryScenarioPlaceholder: '请选择场景',
factoryScenarioSolicit: '约稿',
diff --git a/src/components/page/Login.vue b/src/components/page/Login.vue
index bb61d01..e50785d 100644
--- a/src/components/page/Login.vue
+++ b/src/components/page/Login.vue
@@ -215,6 +215,8 @@
localStorage.setItem('U_role', 'superadmin');
localStorage.setItem('U_name', res.userinfo.account);
localStorage.setItem('U_id', res.userinfo.user_id);
+ localStorage.setItem('U_email', '');
+
this.$router.push('/');
} else if (res.data.roles.includes('editor')) {
@@ -222,6 +224,7 @@
localStorage.setItem('U_role', res.data.roles);
localStorage.setItem('U_name', res.data.userinfo.account);
localStorage.setItem('U_id', res.data.userinfo.user_id);
+ localStorage.setItem('U_email', res.data.userinfo.email);
this.$router.push('/');
} else {
localStorage.setItem('U_status', '2'); //其余的身份
@@ -229,6 +232,7 @@
localStorage.setItem('U_name', res.data.userinfo.account);
localStorage.setItem('U_id', res.data.userinfo.user_id);
localStorage.setItem('U_relname', res.data.userinfo.realname);
+ localStorage.setItem('U_email', res.data.userinfo.email);
this.$router.push('/');
// this.roleVisible = true;
// this.user_cap = res.data.roles;
diff --git a/src/components/page/autoPromotion.vue b/src/components/page/autoPromotion.vue
index 77c0a8c..aebbe41 100644
--- a/src/components/page/autoPromotion.vue
+++ b/src/components/page/autoPromotion.vue
@@ -82,6 +82,12 @@
>
{{ taskCard.templateName || 'No Template Configured' }}
+
+ Type :
+ {{ taskCard.expertTypeLabel || '-' }}
+
-
+
-
-
{{ $t('autoPromotion.factoryExpertType') }}*
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {{ $t('autoPromotion.countryQuickZone1') }}
+ {{ $t('autoPromotion.countryQuickZone2') }}
+ {{ $t('autoPromotion.countryQuickZone3') }}
+ {{ $t('autoPromotion.countryQuickChina') }}
+ {{ $t('autoPromotion.countryQuickIndia') }}
+
+
-
@@ -327,6 +350,16 @@
sendLimitFromApi: false,
factoryType: '1',
expertType: '5',
+ expertTypeCounts: {
+ chief: null,
+ board: null,
+ young: null,
+ author: null,
+ reviewer: null,
+ expertDb: null
+ },
+ expertTypeCountsLoading: false,
+ expertTypeCountsReqSeq: 0,
factoryStartPromotion: true,
factoryConfig: { defaultTemplateId: '', defaultStyleId: '' },
factoryTemplateName: '',
@@ -355,13 +388,72 @@
}
},
factorySteps() {
- return [
+ const steps = [
{ title: this.$t('autoPromotion.factoryStepNav1Title'), desc: this.$t('autoPromotion.factoryStepNav1Desc') },
{ title: this.$t('autoPromotion.factoryStepNav2Title'), desc: this.$t('autoPromotion.factoryStepNav2Desc') },
- { title: this.$t('autoPromotion.factoryStepNav3Title'), desc: this.$t('autoPromotion.factoryStepNav3Desc') },
- { title: this.$t('autoPromotion.factoryStepNav4Title'), desc: this.$t('autoPromotion.factoryStepNav4Desc') },
- { title: this.$t('autoPromotion.factoryStepNav5Title'), desc: this.$t('autoPromotion.factoryStepNav5Desc') }
+ // { title: this.$t('autoPromotion.factoryExpertType'), desc: this.$t('autoPromotion.factoryExpertTypePlaceholder') },
+ { title: this.$t('autoPromotion.factoryStepNav3Title'), desc: this.$t('autoPromotion.factoryStepNav3Desc') }
];
+ if (this.isExpertDatabaseType) {
+ steps.push(
+ { title: this.$t('autoPromotion.factoryStepNav4Title'), desc: this.$t('autoPromotion.factoryStepNav4Desc') },
+ { title: this.$t('autoPromotion.factoryStepNav5Title'), desc: this.$t('autoPromotion.factoryStepNav5Desc') }
+ );
+ }
+ return steps;
+ },
+ isExpertDatabaseType() {
+ return String(this.expertType || '') === '5';
+ },
+ expertOptions() {
+ const counts = this.expertTypeCounts || {};
+ return [
+ {
+ value: '1',
+ label: this.$t('autoPromotion.factoryExpertChief'),
+ desc: this.$t('autoPromotion.factoryExpertChief'),
+ icon: 'el-icon-s-custom',
+ count: counts.chief,
+ jump: { path: '/editorBorder', queryKey: 'journal_id' }
+ },
+ {
+ value: '2',
+ label: this.$t('autoPromotion.factoryExpertBoard'),
+ desc: this.$t('autoPromotion.factoryExpertBoard'),
+ icon: 'el-icon-user-solid',
+ count: counts.board,
+ jump: { path: '/editorBorder', queryKey: 'journal_id' }
+ },
+ {
+ value: '3',
+ label: this.$t('autoPromotion.factoryExpertYoungBoard'),
+ desc: this.$t('autoPromotion.factoryExpertYoungBoard'),
+ icon: 'el-icon-user',
+ count: counts.young,
+ jump: { path: '/youthList', queryKey: 'journal_id' }
+ },
+ {
+ value: '4',
+ label: this.$t('autoPromotion.factoryExpertAuthor'),
+ desc: this.$t('autoPromotion.factoryExpertAuthor'),
+ icon: 'el-icon-edit',
+ count: counts.author,
+ jump: { path: '/partyListCorr', queryKey: 'journal_id' }
+ },
+ {
+ value: '5',
+ label: this.$t('autoPromotion.factoryExpertDb'),
+ desc: this.$t('autoPromotion.factoryExpertDb'),
+ icon: 'el-icon-collection',
+ count: counts.expertDb,
+ jump: { path: '/expertDatabase', queryKey: 'journal_id' }
+ }
+ ];
+ },
+ visibleExpertOptions() {
+ if (!this.isEditMode) return this.expertOptions;
+ const current = String(this.expertType || '').trim();
+ return this.expertOptions.filter((opt) => String(opt.value) === current);
},
isEditMode() {
const task = this.initialTask;
@@ -440,6 +532,10 @@
}
},
methods: {
+ handleExpertTypeClick(v) {
+ if (this.isEditMode) return;
+ this.expertType = v;
+ },
handleDialogOpen() {
this.initDialogState();
},
@@ -472,7 +568,11 @@
await this.loadAccounts(this.selectedJournalId);
const initialSeed = await this.loadInitialTaskSeed();
await this.applyInitialTaskSeed(initialSeed);
- await Promise.all([this.loadAvailableFields(this.selectedJournalId), this.refreshSendCountMax()]);
+ await Promise.all([
+ this.loadAvailableFields(this.selectedJournalId),
+ this.isExpertDatabaseType ? this.refreshSendCountMax() : Promise.resolve()
+ ]);
+ this.fetchExpertTypeCounts();
this.syncActiveStep();
} else {
await this.onJournalChange(this.selectedJournalId);
@@ -697,22 +797,23 @@
s = 1;
}
if (
- this.selectedEmailIds &&
- this.selectedEmailIds.length > 0 &&
String(this.factoryType || '').trim() !== '' &&
String(this.expertType || '').trim() !== '' &&
this.sendCount != null &&
- this.sendCount >= 1
+ this.sendCount >= 1 &&
+ this.selectedEmailIds &&
+ this.selectedEmailIds.length > 0
) {
s = 2;
}
- if (this.factoryFieldIds && this.factoryFieldIds.length > 0) {
+ if (this.isExpertDatabaseType && this.factoryZoneCountryIds && this.factoryZoneCountryIds.length > 0) {
s = 3;
}
- if (this.factoryZoneCountryIds && this.factoryZoneCountryIds.length > 0) {
+ if (this.isExpertDatabaseType && this.factoryFieldIds && this.factoryFieldIds.length > 0) {
s = 4;
}
- if (s >= 4) s = 4;
+ var maxIdx = (this.factorySteps && this.factorySteps.length ? this.factorySteps.length : 1) - 1;
+ if (s > maxIdx) s = maxIdx;
this.activeStep = s;
},
async loadJournalList() {
@@ -721,7 +822,9 @@
this.journalList = externalList.map(function (item) {
return {
journal_id: item.journal_id != null ? item.journal_id : item.id,
- title: item.title || item.journal_title || item.name || ''
+ title: item.title || item.journal_title || item.name || '',
+ journal_icon: item.journal_icon || '',
+ abbr: item.abbr || ''
};
});
return;
@@ -737,9 +840,12 @@
list = res;
}
this.journalList = list.map(function (item) {
+
return {
journal_id: item.journal_id != null ? item.journal_id : item.id,
- title: item.title || item.name || ''
+ title: item.title || item.name || '',
+ journal_icon: item.journal_icon || '',
+ abbr: item.abbr || ''
};
});
} catch (e) {
@@ -749,19 +855,151 @@
this.journalLoading = false;
}
},
+ async handleSelect(id) {
+ if (this.isEditMode) return;
+
+ // 如果点击的是当前已选中的,则置空(实现取消选中功能)
+ const newValue = this.selectedJournalId === id ? null : id;
+
+ // 更新 v-model 绑定的变量
+ this.selectedJournalId = newValue;
+
+ // 调用你原有的业务逻辑方法
+ await this.onJournalChange(newValue);
+ },
async onJournalChange(val) {
if (!val) {
this.accountList = [];
this.availableFields = [];
this.factoryFieldIds = [];
this.selectedEmailIds = [];
+ this.expertTypeCounts = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
this.syncActiveStep();
return;
}
+ // 切换期刊时:先清空旧人数并立即触发 loading
+ this.expertTypeCounts = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
+ this.fetchExpertTypeCounts();
await this.loadAccounts(val);
- await Promise.all([this.loadAvailableFields(val), this.refreshSendCountMax()]);
+ await Promise.all([
+ this.loadAvailableFields(val),
+ this.refreshSendCountMax()
+ ]);
this.syncActiveStep();
},
+ openExpertTypeJump(opt) {
+ const jump = opt && opt.jump;
+ if (!jump || !jump.path) return;
+ const journalId = this.selectedJournalId;
+ // 不使用 query(会污染地址栏 + Tags fullPath);改用 sessionStorage 传参,目标页读取一次后即销毁
+ try {
+ const payload = {
+ from: 'promotionFactory',
+ journal_id: journalId != null && journalId !== '' ? String(journalId) : '',
+ ts: Date.now(),
+ targetPath: String(jump.path || '')
+ };
+ sessionStorage.setItem('promotionFactoryJump', JSON.stringify(payload));
+ } catch (e) {}
+ // 跳转前先关闭并销毁弹窗(destroy-on-close),避免“中间态”残留
+ this.innerVisible = false;
+ this.$nextTick(() => {
+ this.$router.push({ path: jump.path });
+ });
+ },
+ async fetchExpertTypeCounts() {
+ const journalId = this.selectedJournalId;
+ if (!journalId) return;
+ const reqId = ++this.expertTypeCountsReqSeq;
+ this.expertTypeCountsLoading = true;
+ try {
+ const safeCount = (v) => (v == null || isNaN(Number(v)) ? 0 : Number(v));
+ const countBoardMembers = (member) => {
+ if (!member) return 0;
+ if (Array.isArray(member)) return member.length;
+ let sum = 0;
+ Object.keys(member).forEach((k) => {
+ const v = member[k];
+ if (Array.isArray(v)) sum += v.length;
+ else if (v && typeof v === 'object' && Array.isArray(v.list)) sum += v.list.length;
+ else if (v && typeof v === 'object' && Array.isArray(v.data)) sum += v.data.length;
+ else if (v && typeof v === 'object') sum += 1;
+ });
+ return sum;
+ };
+
+ const [boardRes, youngRes, authorRes, reviewerRes, expertDbRes] = await Promise.all([
+ this.$api.post('api/Board/getBoards', { journal_id: journalId }).catch(() => null),
+ this.$api
+ .post('api/User/getYboardlist', {
+ journal_id: journalId,
+ type: 1,
+ year: 0,
+ pageIndex: 1,
+ pageSize: 1,
+ keywords: '',
+ fieldkey: '',
+ order_remark: 0
+ })
+ .catch(() => null),
+ this.$api
+ .post('api/User/authorDatabase', {
+ journal_id: journalId,
+ keywords: '',
+ page: 1,
+ limit: 1
+ })
+ .catch(() => null),
+ this.$api
+ .post('api/Reviewer/getReviewerListByJournal', {
+ username: localStorage.getItem('U_name'),
+ journalId: journalId,
+ class: 0,
+ pageIndex: 1,
+ pageSize: 1
+ })
+ .catch(() => null),
+ this.$api
+ .post('api/expert_manage/getList', {
+ pageIndex: 1,
+ pageSize: 1
+ })
+ .catch(() => null)
+ ]);
+
+ const next = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
+
+ if (boardRes && boardRes.code === 0 && boardRes.data && boardRes.data.boards) {
+ const b = boardRes.data.boards || {};
+ const chief = Array.isArray(b.main) ? b.main.length : 0;
+ const remain = Array.isArray(b.remain) ? b.remain.length : 0;
+ const member = countBoardMembers(b.member);
+ next.chief = safeCount(chief);
+ next.board = safeCount(remain + member);
+ }
+ if (youngRes && youngRes.code === 0) {
+ next.young = safeCount(youngRes.data && youngRes.data.count);
+ }
+ if (authorRes && authorRes.code === 0) {
+ next.author = safeCount(authorRes.data && authorRes.data.count);
+ }
+ if (reviewerRes && reviewerRes.code === 0) {
+ next.reviewer = safeCount(reviewerRes.total);
+ }
+ if (expertDbRes && expertDbRes.code === 0) {
+ const total = (expertDbRes.data && (expertDbRes.data.total || expertDbRes.data.count)) || expertDbRes.total;
+ next.expertDb = safeCount(total);
+ }
+
+ // 防止快速切换期刊导致旧请求覆盖新请求
+ if (reqId !== this.expertTypeCountsReqSeq) return;
+ this.expertTypeCounts = next;
+ } finally {
+ if (reqId === this.expertTypeCountsReqSeq) {
+ this.expertTypeCountsLoading = false;
+ }
+ }
+ },
async loadAccounts(id) {
this.accountsLoading = true;
try {
@@ -879,18 +1117,18 @@
let fromApi = false;
try {
if (this.selectedEmailIds && this.selectedEmailIds.length > 0) {
+ // 优先走后端限制接口:api/promotion_factory/getCountForPromotionEmailIds
const emailCap = await this.loadSendCountMaxFromEmailIds();
if (emailCap.max > 0) {
max = emailCap.max;
fromApi = emailCap.fromApi;
}
}
+ // 没有选账号或接口不可用时:回退为邮箱额度合计(或默认上限)
if (!max || max < 1) {
const fallbackCap = this.loadSendCountMaxFallback();
max = fallbackCap.max;
- if (!fromApi && fallbackCap.fromApi) {
- fromApi = true;
- }
+ fromApi = false;
}
} catch (e) {
console.error(e);
@@ -994,11 +1232,19 @@
this.$message.warning(this.$t('autoPromotion.factoryNeedExpertType'));
return;
}
- if (!this.factoryFieldIds || !this.factoryFieldIds.length) {
+ if (!String(this.factoryType || '').trim()) {
+ this.$message.warning(this.$t('autoPromotion.factoryNeedExpertType'));
+ return;
+ }
+ if (this.sendCount == null || Number(this.sendCount) < 1) {
+ this.$message.warning(this.$t('autoPromotion.factoryFillRequired'));
+ return;
+ }
+ if (this.isExpertDatabaseType && (!this.factoryFieldIds || !this.factoryFieldIds.length)) {
this.$message.warning(this.$t('autoPromotion.factoryNeedPromotionFields'));
return;
}
- if (!this.factoryZoneCountryIds || !this.factoryZoneCountryIds.length) {
+ if (this.isExpertDatabaseType && (!this.factoryZoneCountryIds || !this.factoryZoneCountryIds.length)) {
this.$message.warning(this.$t('autoPromotion.factoryNeedPromotionCountry'));
return;
}
@@ -1011,9 +1257,9 @@
send_count: String(this.sendCount),
template_id: String(this.factoryConfig.defaultTemplateId),
style_id: String(this.factoryConfig.defaultStyleId),
- fetch_ids: (this.factoryFieldIds || []).join(','),
- target_partitions: pc.target_partitions,
- target_country_ids: pc.target_country_ids,
+ fetch_ids: this.isExpertDatabaseType ? (this.factoryFieldIds || []).join(',') : '',
+ target_partitions: this.isExpertDatabaseType ? pc.target_partitions : '',
+ target_country_ids: this.isExpertDatabaseType ? pc.target_country_ids : '',
start_promotion: '0'
};
const endpoint = this.isEditMode ? API_FACTORY_EDIT : API_FACTORY_ADD;
@@ -1098,10 +1344,10 @@
/* 左侧步骤条样式 (模仿图一) */
.step-navigation {
- width: 240px;
+ width: 230px;
background: #fafbfc;
border-right: 1px solid #edf0f5;
- padding: 10px 20px 30px 10px;
+ padding: 10px 20px 30px 0px;
}
.step-item {
@@ -1300,10 +1546,10 @@
.click-card {
border: 1px dashed #dcdfe6;
border-radius: 6px;
- padding: 15px;
+ padding: 4px 20px;
cursor: pointer;
transition: all 0.2s;
- min-height: 50px;
+ min-height: 30px;
display: flex;
align-items: center;
}
@@ -1325,21 +1571,69 @@
}
.account-grid-layout {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
- gap: 8px;
- }
-
- .acc-box {
- background: #fff;
- border: 1px solid #e4e7ed;
- padding: 4px 10px;
- border-radius: 4px;
- }
-
- .acc-info { display: flex; flex-direction: column; margin-left: 5px; }
- .acc-info .u { font-size: 12px; font-weight: 500; color: #333; }
- .acc-info .m { font-size: 11px; color: #999; }
+ display: grid;
+ /* 如果希望固定 3 个一行:repeat(3, 1fr);如果自适应:repeat(auto-fill, minmax(280px, 1fr)) */
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ gap: 8px;
+}
+
+/* 账号外框:大幅缩小内边距和高度 */
+.acc-box {
+ border: 1px solid #e4e7ed;
+ border-radius: 4px;
+ padding: 4px 10px; /* 极窄内边距 */
+ background: #fff;
+ transition: all 0.2s;
+ display: flex;
+ align-items: center;
+ height: 32px; /* 强制固定一行的高度 */
+}
+
+.acc-box:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+}
+
+/* 内部信息:改为横向 Flex */
+.acc-info-inline {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ font-size: 12px;
+}
+
+.acc-info-inline .u {
+ color: #333;
+ font-weight: 500;
+ max-width: 180px; /* 防止邮箱过长撑破布局 */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.acc-info-inline .m {
+ color: #909399;
+ font-size: 11px;
+}
+
+.divider {
+ color: #dcdfe6;
+ margin: 0 4px;
+}
+
+/* 深度选择器:去除 Element 默认的间距 */
+.acc-box /deep/ .el-checkbox {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ margin-right: 0;
+}
+
+.acc-box /deep/ .el-checkbox__label {
+ padding-left: 8px;
+ line-height: 1;
+ display: flex;
+}
/* 底部参数栏:白底 + 左侧蓝边;标签与控件同一行横向排布 */
.parameter-bar {
@@ -1483,4 +1777,301 @@
padding-top:15px !important;
padding-bottom:15px !important;
}
-
\ No newline at end of file
+ .journal-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ padding: 10px 0;
+}
+
+.journal-card {
+ width: 80px; /* 根据实际需求调整宽度 */
+ cursor: pointer;
+ position: relative;
+ transition: all 0.3s;
+ border: 2px solid transparent;
+ border-radius: 4px;
+ padding: 4px;
+ text-align: center;
+ background: #f8f9fa;
+
+ &:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
+ }
+
+ &.is-active {
+ border-color: #409eff; /* ElementUI 主题色 */
+ background: #ecf5ff;
+ .journal-abbreviation {
+ color: #409eff;
+ font-weight: bold;
+ }
+ }
+
+ &.is-disabled {
+ pointer-events: none;
+ opacity: 0.6;
+ filter: grayscale(1);
+ }
+}
+
+.journal-cover {
+ width: 100%;
+ height: 110px; /* 保持期刊封面比例 */
+ margin-bottom: 8px;
+ border-radius: 4px;
+ overflow: hidden;
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
+
+ .el-image {
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.journal-abbreviation {
+ font-size: 13px;
+ color: #606266;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.active-badge {
+ position: absolute;
+ top: -5px;
+ right: -5px;
+ background: #409eff;
+ color: white;
+ border-radius: 50%;
+ width: 20px;
+ height: 20px;
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+/* 3. 核心美化区块:期刊+专家合并 */
+.combined-selector-container {
+ display: flex;
+ gap: 30px; /* 期刊和专家类型之间的间距 */
+ background: #f8fafc;
+ border-radius: 8px;
+ padding: 16px;
+ border: 1px solid #ebf0f5;
+ align-items: flex-start; /* 顶部对齐 */
+}
+
+/* 左侧期刊区域:由内容撑开,不收缩 */
+.journal-selection-side {
+ flex-shrink: 0;
+ max-width:450px;
+
+ /* 如果你想让左侧也稍微宽点,可以设置 min-width: 300px; */
+}
+
+
+.mini-label {
+ font-size: 12px;
+ color: #909399;
+ font-weight: bold;
+ margin-bottom: 12px;
+
+}
+
+/* 左侧期刊:更紧凑的列表 */
+.journal-selection-side {
+ flex: 1;
+ border-right: 1px solid #e4e7ed;
+ padding-right: 20px;
+}
+
+.journal-grid-compact {
+
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.journal-card-mini {
+ width: 70px;
+ position: relative;
+ cursor: pointer;
+ text-align: center;
+}
+
+.mini-cover {
+ width: 70px;
+ height: 90px;
+ border-radius: 4px;
+ box-shadow: 0 2px 6px rgba(0,0,0,0.1);
+ border: 2px solid transparent;
+ transition: 0.2s;
+}
+
+.journal-card-mini.is-active .mini-cover {
+ border-color: #409eff;
+ transform: scale(1.05);
+}
+
+.mini-abbr {
+ font-size: 11px;
+ margin-top: 5px;
+ color: #606266;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+/* 期刊网格微调 */
+.journal-grid-compact { display: flex; flex-wrap: wrap; gap: 12px; }
+.journal-card-mini { width: 70px; text-align: center; cursor: pointer; }
+.mini-cover-wrapper { position: relative; width: 70px; height: 95px; }
+.mini-cover {
+ width: 100%; height: 100%; border-radius: 4px; border: 2px solid transparent;
+ box-shadow: 0 2px 6px rgba(0,0,0,0.1); transition: 0.3s;
+}
+.journal-card-mini.is-active .mini-cover { border-color: #409eff; transform: translateY(-3px); }
+.mini-badge {
+ position: absolute; top: -6px; right: -6px; background: #67c23a; color: #fff;
+ width: 18px; height: 18px; border-radius: 50%; font-size: 10px;
+ display: flex; align-items: center; justify-content: center; z-index: 2;
+}
+.mini-abbr { font-size: 11px; color: #606266; margin-top: 6px; overflow: hidden; text-overflow: ellipsis; }
+.mini-abbr.is-active {
+ color: #409eff;
+ font-weight: 600;
+}
+
+.expert-type-side {
+ flex: 1; /* 核心代码:占据剩余空间 */
+ min-width: 0; /* 防止 Flex 子项溢出 */
+ display: flex;
+ flex-direction: column;
+
+}
+
+.mini-label {
+ font-size: 12px;
+ color: #909399;
+ margin-bottom: 8px; /* 紧凑间距 */
+ font-weight: 600;
+}
+
+
+.expert-tile-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ width: 100%;
+}
+
+.expert-tile-mini {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 6px 12px;
+ background: #fff;
+ border: 1px solid #e4e7ed;
+ border-radius: 4px;
+ cursor: pointer;
+
+ /* --- 关键修改:不强制占满 --- */
+ flex: 0 0 auto; /* 不放大,不缩小,根据内容定宽度 */
+ min-width: 140px; /* 给一个最小宽度,保证整齐度 */
+ max-width: 300px; /* 限制最大宽度,防止太长 */
+ /* ------------------------ */
+
+ height: 34px;
+ box-sizing: border-box;
+ transition: all 0.2s;
+}
+
+.expert-tile-mini.is-disabled {
+ cursor: not-allowed;
+ opacity: 0.75;
+}
+
+.expert-tile-mini.is-disabled:hover {
+ background: #fff;
+}
+
+.tile-text {
+ font-size: 12px;
+ color: #606266;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-right: 8px;
+}
+
+.tile-count {
+ margin-left: 4px;
+ color: #909399;
+ font-weight: 400;
+}
+.tile-count--loading {
+ opacity: 0.7;
+}
+.tile-link-btn {
+ padding: 0;
+ margin-left: auto;
+ line-height: 1;
+ font-size: 12px;
+}
+
+.tile-spinner {
+ margin-left: 6px;
+ color: #409eff;
+ font-size: 12px;
+}
+
+/* 选中状态 */
+.expert-tile-mini.is-active {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+}
+
+.expert-tile-mini:hover {
+ background-color: #f5f7fa;
+}
+
+
+
+
+
+.expert-tile-mini.is-active .tile-text {
+ color: #409eff;
+ font-weight: 500;
+}
+
+/* 选中图标微型化 */
+.expert-tile-mini i {
+ font-size: 14px;
+ color: #409eff;
+}
+
+/* 隐藏横向滚动条,美化纵向滚动条 */
+.custom-scrollbar::-webkit-scrollbar {
+ width: 4px;
+}
+.custom-scrollbar::-webkit-scrollbar-thumb {
+ background: #e4e7ed;
+ border-radius: 4px;
+}
+
+/* 激活状态左侧的小指示条(可选,增加精致感) */
+.expert-tile-mini.is-active {
+ position: relative;
+}
+.expert-tile-mini.is-active::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 4px;
+ bottom: 4px;
+ width: 2px;
+ background: #409eff;
+}
+
+
\ No newline at end of file
diff --git a/src/components/page/editorBorder.vue b/src/components/page/editorBorder.vue
index 4b5f927..4accd3a 100644
--- a/src/components/page/editorBorder.vue
+++ b/src/components/page/editorBorder.vue
@@ -771,6 +771,7 @@
diff --git a/src/components/common/common.vue b/src/components/common/common.vue
index a1781ec..9bac70a 100644
--- a/src/components/common/common.vue
+++ b/src/components/common/common.vue
@@ -2,14 +2,14 @@
//记得切换
//正式
-// const mediaUrl = '/public/';
-// const baseUrl = '/';
+const mediaUrl = '/public/';
+const baseUrl = '/';
//正式环境
-const mediaUrl = 'https://submission.tmrjournals.com/public/';
-// const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
-const baseUrl = '/api'
+// const mediaUrl = 'https://submission.tmrjournals.com/public/';
+// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
+// const baseUrl = '/api'
//测试环境
diff --git a/src/components/page/JournalManagement/JournalManagement/common.vue b/src/components/page/JournalManagement/JournalManagement/common.vue
index 0ae93f0..9ff0bfb 100644
--- a/src/components/page/JournalManagement/JournalManagement/common.vue
+++ b/src/components/page/JournalManagement/JournalManagement/common.vue
@@ -263,7 +263,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add
-
-
+
+
@@ -657,6 +694,17 @@ export default {
this.$message.error(res.msg);
}
},
+ async handleAvatarSuccessYboard(res, file) {
+ if (res.code == 0) {
+ this.detailForm.wechat_yboard_qrcode = res.upurl;
+ this.$forceUpdate();
+ } else {
+ this.$message.error(res.msg);
+ }
+ },
+ handleAvatarErrorYboard(res, file) {
+ // no-op
+ },
handleAvatarError2(res, file) {
// this.$message.error(res);
},
@@ -883,7 +931,9 @@ export default {
epassword: data.epassword,
kfen: data.kfen,
fee: data.fee,
+ databases: data.databases || data.database_inclusion || '',
editor_qrcode: data.editor_qrcode,
+ wechat_yboard_qrcode: data.wechat_yboard_qrcode || data.yboard_qrcode,
scope: data.scope,
abstract_chinese: data.abstract_chinese,
publish_author: data.publish_author,
@@ -1369,6 +1419,29 @@ export default {
border-radius: 110px;
}
+/* Wechat Name + Apply Youth Board QR:两列对齐到右侧 */
+.wechat-name-split__inner {
+ display: flex;
+ align-items: flex-start;
+ gap: 16px;
+}
+
+.wechat-name-split__left {
+ flex: 1;
+ min-width: 200px;
+}
+
+.wechat-name-split__right {
+ width: 160px;
+}
+
+.yboard-qrcode-side__label {
+ font-size: 12px;
+ color: #666;
+ text-align: center;
+ margin-bottom: 8px;
+}
+
.portrait .ptmark {
position: absolute;
top: 0;
diff --git a/src/components/page/YouthBoardSubmitSuccess.vue b/src/components/page/YouthBoardSubmitSuccess.vue
new file mode 100644
index 0000000..928d110
--- /dev/null
+++ b/src/components/page/YouthBoardSubmitSuccess.vue
@@ -0,0 +1,238 @@
+
+
+
+
✔
+
Application submitted successfully!
+
+ We have a WeChat group for academic discussions. Please feel free to scan the QR code below to join.
+
+
+ Your application is currently under review. We appreciate your patience, and our team will notify you of the final decision via email as soon as possible.
+
+
+
+
Loading...
+
+
+
+
+
+
+
Login to the Submission System Now
+
+
+
+
+
+
+
diff --git a/src/components/page/YouthEditorialBoardRegistration.vue b/src/components/page/YouthEditorialBoardRegistration.vue
new file mode 100644
index 0000000..73b02bd
--- /dev/null
+++ b/src/components/page/YouthEditorialBoardRegistration.vue
@@ -0,0 +1,598 @@
+
+
+
+
Youth Editorial Board Registration
+
+
+
+
+
{{ journalTitle || 'Journal Information' }}
+
+
+
+
+
+
Thank you
+
Your registration has been submitted. We will contact you by email.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/page/youthApplyList.vue b/src/components/page/youthApplyList.vue
index 9b84261..390ac1c 100644
--- a/src/components/page/youthApplyList.vue
+++ b/src/components/page/youthApplyList.vue
@@ -187,6 +187,7 @@