283 lines
6.9 KiB
JavaScript
283 lines
6.9 KiB
JavaScript
import { htmlToPlainText } from '@/utils/exportTableWord';
|
||
|
||
const STOP_WORDS = new Set([
|
||
'a', 'an', 'the', 'of', 'and', 'for', 'in', 'on', 'at', 'to', 'from', 'with', 'by',
|
||
'de', 'du', 'des', 'la', 'le', 'les', 'et', 'und', 'der', 'die', 'das'
|
||
]);
|
||
|
||
const KNOWN_WORD_ABBREVIATIONS = {
|
||
journal: 'J',
|
||
international: 'Int',
|
||
american: 'Am',
|
||
european: 'Eur',
|
||
british: 'Br',
|
||
medicine: 'Med',
|
||
medical: 'Med',
|
||
nursing: 'Nurs',
|
||
inquiry: 'Inq',
|
||
science: 'Sci',
|
||
sciences: 'Sci',
|
||
research: 'Res',
|
||
review: 'Rev',
|
||
reports: 'Rep',
|
||
health: 'Health',
|
||
healthcare: 'Health',
|
||
clinical: 'Clin',
|
||
surgery: 'Surg',
|
||
pediatric: 'Pediatr',
|
||
paediatric: 'Paediatr',
|
||
oncology: 'Oncol',
|
||
psychiatry: 'Psychiatry',
|
||
psychology: 'Psychol',
|
||
education: 'Educ',
|
||
technology: 'Technol',
|
||
engineering: 'Eng',
|
||
management: 'Manage',
|
||
studies: 'Stud',
|
||
practice: 'Pract',
|
||
traditional: 'Tradit',
|
||
tradit: 'Tradit',
|
||
clinical: 'Clin',
|
||
complementary: 'Complement',
|
||
alternative: 'Altern',
|
||
integrative: 'Integr',
|
||
pharmacology: 'Pharmacol',
|
||
biochemistry: 'Biochem',
|
||
physiology: 'Physiol',
|
||
pathology: 'Pathol',
|
||
radiology: 'Radiol',
|
||
cardiology: 'Cardiol',
|
||
neurology: 'Neurol',
|
||
dermatology: 'Dermatol',
|
||
obstetrics: 'Obstet',
|
||
gynecology: 'Gynecol',
|
||
gynaecology: 'Gynaecol',
|
||
anesthesiology: 'Anesthesiol',
|
||
anaesthesiology: 'Anaesthesiol',
|
||
epidemiology: 'Epidemiol',
|
||
immunology: 'Immunol',
|
||
microbiology: 'Microbiol',
|
||
nutrition: 'Nutr',
|
||
public: 'Public',
|
||
environmental: 'Environ',
|
||
occupational: 'Occup',
|
||
behavioral: 'Behav',
|
||
behavioural: 'Behav',
|
||
biological: 'Biol',
|
||
molecular: 'Mol',
|
||
cellular: 'Cell',
|
||
applied: 'Appl',
|
||
advanced: 'Adv',
|
||
general: 'Gen',
|
||
internal: 'Intern',
|
||
family: 'Fam',
|
||
community: 'Community',
|
||
global: 'Glob',
|
||
world: 'World',
|
||
asian: 'Asian',
|
||
chinese: 'Chin',
|
||
japanese: 'Jpn',
|
||
korean: 'Korean',
|
||
indian: 'Indian',
|
||
african: 'Afr',
|
||
australian: 'Aust',
|
||
canadian: 'Can',
|
||
quarterly: 'Q',
|
||
monthly: 'Mon',
|
||
weekly: 'Wkly',
|
||
annual: 'Annu',
|
||
proceedings: 'Proc',
|
||
transactions: 'Trans',
|
||
bulletin: 'Bull',
|
||
letters: 'Lett',
|
||
communications: 'Commun',
|
||
perspectives: 'Perspect',
|
||
insights: 'Insights',
|
||
trends: 'Trends',
|
||
systems: 'Syst',
|
||
informatics: 'Inform',
|
||
bioinformatics: 'Bioinform',
|
||
therapeutics: 'Ther',
|
||
diagnostics: 'Diagn',
|
||
imaging: 'Imaging',
|
||
rehabilitation: 'Rehabil',
|
||
emergency: 'Emerg',
|
||
critical: 'Crit',
|
||
care: 'Care',
|
||
patient: 'Patient',
|
||
patients: 'Patient',
|
||
hospital: 'Hosp',
|
||
hospitals: 'Hosp',
|
||
university: 'Univ',
|
||
academy: 'Acad',
|
||
society: 'Soc',
|
||
association: 'Assoc',
|
||
federation: 'Fed',
|
||
institute: 'Inst',
|
||
college: 'Coll',
|
||
school: 'Sch',
|
||
department: 'Dep',
|
||
division: 'Div',
|
||
section: 'Sect',
|
||
series: 'Ser',
|
||
supplement: 'Suppl',
|
||
edition: 'Ed',
|
||
online: 'Online',
|
||
open: 'Open',
|
||
access: 'Access'
|
||
};
|
||
|
||
function splitJournalWords(journalText) {
|
||
return String(journalText || '')
|
||
.replace(/\./g, ' ')
|
||
.split(/[\s/&]+/)
|
||
.map(function (part) {
|
||
return part.trim();
|
||
})
|
||
.filter(Boolean);
|
||
}
|
||
|
||
function abbreviateJournalWord(word) {
|
||
const cleaned = String(word || '').replace(/[^\p{L}\-]/gu, '');
|
||
if (!cleaned) {
|
||
return '';
|
||
}
|
||
|
||
const lower = cleaned.toLowerCase();
|
||
if (KNOWN_WORD_ABBREVIATIONS[lower]) {
|
||
return KNOWN_WORD_ABBREVIATIONS[lower];
|
||
}
|
||
|
||
if (cleaned.length <= 4) {
|
||
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
|
||
}
|
||
|
||
const vowels = 'aeiouy';
|
||
let result = cleaned.charAt(0).toUpperCase();
|
||
const rest = cleaned.slice(1).toLowerCase();
|
||
let index = 0;
|
||
|
||
while (result.length < 4 && index < rest.length) {
|
||
const ch = rest.charAt(index);
|
||
index += 1;
|
||
if (!vowels.includes(ch)) {
|
||
result += ch;
|
||
} else if (result.length === 1) {
|
||
result += ch;
|
||
}
|
||
}
|
||
|
||
if (result.length < 3) {
|
||
const fallback = cleaned.slice(0, Math.min(4, cleaned.length));
|
||
result = fallback.charAt(0).toUpperCase() + fallback.slice(1).toLowerCase();
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function normalizeJournalText(text) {
|
||
return String(text || '')
|
||
.replace(/\./g, ' ')
|
||
.replace(/\s+/g, ' ')
|
||
.trim();
|
||
}
|
||
|
||
/** 是否已是期刊缩写形式(如 Nurs Inq、Tradit Med Res) */
|
||
export function isAbbreviatedJournalName(journalText) {
|
||
const plain = normalizeJournalText(htmlToPlainText(journalText));
|
||
if (!plain) {
|
||
return true;
|
||
}
|
||
|
||
const words = splitJournalWords(plain);
|
||
if (!words.length) {
|
||
return true;
|
||
}
|
||
|
||
return !words.some(function (word) {
|
||
if (STOP_WORDS.has(word.toLowerCase())) {
|
||
return false;
|
||
}
|
||
return word.length >= 7;
|
||
});
|
||
}
|
||
|
||
/** 将期刊全称转为无句点缩写(如 Nursing Inquiry -> Nurs Inq) */
|
||
export function buildJournalAbbreviation(journalText) {
|
||
const plain = normalizeJournalText(htmlToPlainText(journalText));
|
||
if (!plain) {
|
||
return '';
|
||
}
|
||
|
||
const abbreviated = splitJournalWords(plain)
|
||
.map(function (word) {
|
||
if (STOP_WORDS.has(word.toLowerCase())) {
|
||
return '';
|
||
}
|
||
return abbreviateJournalWord(word);
|
||
})
|
||
.filter(Boolean);
|
||
|
||
return abbreviated.join(' ');
|
||
}
|
||
|
||
/** journal 参考文献期刊名是否需要缩写建议 */
|
||
export function needsJournalAbbreviation(journalText) {
|
||
const plain = normalizeJournalText(htmlToPlainText(journalText));
|
||
if (!plain || isAbbreviatedJournalName(plain)) {
|
||
return false;
|
||
}
|
||
|
||
const abbreviated = buildJournalAbbreviation(plain);
|
||
if (!abbreviated) {
|
||
return false;
|
||
}
|
||
|
||
return plain.toLowerCase() !== abbreviated.toLowerCase();
|
||
}
|
||
|
||
function isJournalReference(ref) {
|
||
return String(ref && ref.refer_type || '').toLowerCase() === 'journal';
|
||
}
|
||
|
||
export function extractJournalSource(ref) {
|
||
if (!isJournalReference(ref)) {
|
||
return '';
|
||
}
|
||
|
||
const jouraPlain = htmlToPlainText(ref.joura).trim();
|
||
if (jouraPlain) {
|
||
return jouraPlain;
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
export function buildJournalAbbrevComment(ref) {
|
||
const revision = buildJournalAbbrevRevision(ref);
|
||
if (!revision) {
|
||
return '';
|
||
}
|
||
|
||
return '期刊名称缩写:' + revision.suggested;
|
||
}
|
||
|
||
export function buildJournalAbbrevRevision(ref) {
|
||
const journalSource = extractJournalSource(ref);
|
||
if (!journalSource || !needsJournalAbbreviation(journalSource)) {
|
||
return null;
|
||
}
|
||
|
||
const suggested = buildJournalAbbreviation(journalSource);
|
||
if (!suggested || journalSource.toLowerCase() === suggested.toLowerCase()) {
|
||
return null;
|
||
}
|
||
|
||
return {
|
||
original: journalSource,
|
||
suggested: suggested,
|
||
suffix: '. ',
|
||
italics: true
|
||
};
|
||
}
|