7.31更新

This commit is contained in:
hrx 2026-07-31 15:07:23 +08:00
parent 1de17afa1c
commit 56f2300ba3
8 changed files with 695 additions and 89 deletions

View File

@ -18,7 +18,7 @@ export default {
switchEnSuccess: 'Switched to English'
},
home: {
heroTitle: 'One Platform · Intelligent Leap · Across All Industries.',
heroTitle: 'Make AI Everywhere, Make AI Easy',
heroSubtitle: '',
heroSlogan: 'Make AI Everywhere, Make AI Easy',
solutionsBtn: 'Solutions',

View File

@ -57,6 +57,14 @@
<button v-if="!isNcmatchDomain" type="button" class="nav-item" @click.stop="goHomeAnchor('news')">
{{ $t('topbar.news') }}
</button>
<button
type="button"
class="nav-item"
:class="{ active: $route.path.includes('/homePage/about') }"
@click.stop="navigateTo('/homePage/about')"
>
{{ aboutUsText }}
</button>
</nav>
<div class="user-actions">
@ -327,6 +335,9 @@ export default Vue.extend({
langToggleTitle() {
return this.activeLocale === 'en-US' ? 'Switch to Chinese' : '切换到英文'
},
aboutUsText() {
return this.activeLocale === 'en-US' ? 'About Us' : '关于我们'
},
localizedProductMenuItems() {
const isEn = this.activeLocale === 'en-US'
const labels = {

View File

@ -11,7 +11,7 @@
<h1>{{ $t('home.heroTitle') }}</h1>
</div>
<h2 v-if="$t('home.heroSubtitle')">{{ $t('home.heroSubtitle') }}</h2>
<p>{{ $t('home.heroSlogan') }}</p>
<!-- <p>{{ $t('home.heroSlogan') }}</p> -->
<div class="hero-actions">
<button type="button" class="use-btn" @click="goSolution">{{ $t('home.solutionsBtn') }}</button>
<div class="outline-btn" @click="contactSales">{{ $t('home.contactSalesBtn') }}</div>
@ -37,6 +37,14 @@
@mouseleave="startSolutionCarousel"
@click="setSolutionIndex(item.index)"
>
<button
v-if="item.card.scenarioPath"
type="button"
class="solution-card__scenario-link"
@click.stop="goSolutionScenario(item.card.scenarioPath)"
>
{{ $i18n && $i18n.locale === 'en-US' ? 'Scenarios→' : item.card.scenarioLabel }}
</button>
<div class="solution-card__front">
<div class="solution-card__icon" v-html="item.card.icon"></div>
<h3>{{ item.card.title }}</h3>
@ -129,7 +137,7 @@
<div class="news-list">
<article
v-for="(item, index) in localizedNewsList"
:key="item.title"
:key="item.id"
class="news-card"
:class="{ 'news-card-active': index === activeNewsIndex }"
@mouseenter="activeNewsIndex = index"
@ -213,6 +221,8 @@ export default {
],
bg: 'linear-gradient(145deg, rgba(208, 236, 249, 0.72) 0%, rgba(168, 216, 244, 0.64) 44%, rgba(124, 196, 238, 0.58) 100%)',
shadow: '0 18px 54px rgba(80, 150, 220, 0.2), 0 4px 16px rgba(80, 150, 220, 0.08)',
scenarioLabel: '投策智能体→',
scenarioPath: '/homePage/agentStore/decisionCase',
icon: '<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="24" cy="18" r="6"/><circle cx="10" cy="34" r="5"/><circle cx="38" cy="34" r="5"/><line x1="20" y1="23" x2="13" y2="30"/><line x1="28" y1="23" x2="35" y2="30"/><circle cx="36" cy="14" r="3.5"/><circle cx="12" cy="14" r="3.5"/></svg>'
},
{
@ -303,6 +313,8 @@ export default {
],
bg: 'linear-gradient(145deg, rgba(200, 214, 242, 0.72) 0%, rgba(158, 180, 230, 0.64) 44%, rgba(116, 146, 216, 0.58) 100%)',
shadow: '0 18px 54px rgba(60, 80, 160, 0.18), 0 4px 16px rgba(60, 80, 160, 0.08)',
scenarioLabel: '合同智能审查→',
scenarioPath: '/homePage/agentStore/contractCase',
icon: '<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 6h16l10 10v26a4 4 0 0 1-4 4H12a4 4 0 0 1-4-4V10a4 4 0 0 1 4-4z"/><polyline points="28,6 28,16 38,16"/><line x1="14" y1="24" x2="34" y2="24"/><line x1="14" y1="31" x2="30" y2="31"/></svg>'
},
{
@ -378,7 +390,29 @@ export default {
})
},
localizedNewsList() {
return this.newsList
const isEnglish = this.$i18n && this.$i18n.locale === 'en-US'
return this.newsList.map((item) => {
const tag = isEnglish
? (item.tagEn || item.tagZh || this.$t('home.news.tag'))
: (item.tagZh || item.tagEn || this.$t('home.news.tag'))
const title = isEnglish
? (item.titleEn || item.titleZh || '')
: (item.titleZh || item.titleEn || '')
const desc = isEnglish
? (item.descEn || item.descZh || '')
: (item.descZh || item.descEn || '')
const date = isEnglish
? (item.dateEn || item.dateZh || '')
: (item.dateZh || item.dateEn || '')
return {
...item,
tag,
title,
desc,
date
}
})
},
visibleSolutionCards() {
const slots = [-3, -2, -1, 0, 1, 2, 3]
@ -430,6 +464,9 @@ export default {
block: 'start'
})
},
goSolutionScenario(path) {
this.navigateTo(path)
},
contactSales() {
this.$store.commit('setShowTalk', true)
},
@ -455,11 +492,15 @@ export default {
normalizeHomeNewsItem(row, index) {
return {
id: row.id,
tag: row.article_type || this.$t('home.news.tag'),
tagClass: this.getNewsTagClass(index),
date: row.publish_time || row.publishTime || '',
title: row.title || '',
desc: row.summary || row.desc || row.description || ''
tagZh: row.article_type_zh || row.article_type || '',
tagEn: row.article_type_en || '',
dateZh: row.publish_time_zh || row.publish_time || row.publishTime || '',
dateEn: row.publish_time_en || '',
titleZh: row.title_zh || row.title || '',
titleEn: row.title_en || '',
descZh: row.summary_zh || row.summary || row.desc || row.description || '',
descEn: row.summary_en || ''
}
},
getResponseList(res) {
@ -482,7 +523,6 @@ export default {
}
},
nextSolution() {
this.switchSolution(1)
},
@ -690,7 +730,6 @@ body.dark-theme .bg-orb {
align-items: center;
justify-content: center;
&:hover {
background: #fff;
transform: translateY(-2px);
@ -824,6 +863,39 @@ body.dark-theme .bg-orb {
transition: all 0.28s ease;
}
.solution-card__scenario-link {
position: absolute;
top: 16px;
right: 16px;
z-index: 3;
padding: 5px 9px;
color: #1d4ed8;
font-size: 12px;
line-height: 1.2;
font-weight: 700;
white-space: nowrap;
background: rgba(255, 255, 255, 0.58);
border: 1px solid rgba(255, 255, 255, 0.72);
border-radius: 999px;
opacity: 0;
cursor: pointer;
pointer-events: none;
transform: translateY(-4px);
transition: background 0.2s ease, color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
}
.solution-card:hover .solution-card__scenario-link {
opacity: 1;
pointer-events: auto;
transform: translateY(0);
}
.solution-card__scenario-link:hover {
color: #1e40af;
background: rgba(255, 255, 255, 0.9);
transform: translateY(-1px);
}
.solution-card__icon {
position: relative;
z-index: 1;
@ -865,15 +937,12 @@ body.dark-theme .bg-orb {
transition: all 0.25s ease;
overflow-x: hidden;
overflow-y: auto;
-ms-overflow-style: none;
scrollbar-width: none;
box-sizing: border-box;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: rgba(37, 99, 235, 0.18);
border-radius: 999px;
display: none;
}
strong {
@ -1546,8 +1615,6 @@ body.dark-theme .bg-orb {
}
}
@keyframes heroFadeIn {
from {
opacity: 0;

View File

@ -18,7 +18,7 @@
</div>
<div class="article-editor" :class="{ 'is-editor-fullscreen': editorFullscreen }">
<div class="article-editor__left">
<div class="article-editor__left" :class="{ 'has-language-form': showEnglishForm }">
<div class="article-editor__form">
<el-form :model="form" label-width="76px" size="small">
<el-form-item>
@ -71,11 +71,27 @@
</div>
</el-form-item>
</el-form>
<div class="language-trigger">
<div class="language-trigger__title">
<span class="language-trigger__badge">EN</span>
<div>
<strong>多语言输入</strong>
<small>添加英文版文章内容</small>
</div>
</div>
<button
type="button"
class="language-trigger__button"
:aria-expanded="showEnglishForm.toString()"
@click="showEnglishForm = !showEnglishForm"
>
{{ showEnglishForm ? '收起英文版' : '添加英文版' }}
<i :class="showEnglishForm ? 'el-icon-arrow-up' : 'el-icon-arrow-down'" />
</button>
</div>
</div>
<div v-if="dialogVisible" class="wang-editor-wrap">
<Toolbar
class="wang-toolbar"
:editor="editor"
@ -90,6 +106,92 @@
@onCreated="handleEditorCreated"
/>
</div>
<section v-if="showEnglishForm" class="article-editor__language-section">
<div class="language-section-head">
<div>
<span class="language-section-head__eyebrow">ENGLISH VERSION</span>
<h3>英文版文章</h3>
<p>英文内容会与中文内容一并保存或发布</p>
</div>
<span class="language-section-head__tag">English</span>
</div>
<div class="language-form-grid">
<div class="language-field language-field--wide">
<label>Article Title</label>
<el-input v-model.trim="english.title" placeholder="Enter article title" />
</div>
<div class="language-field language-field--wide">
<label>English Summary</label>
<el-input
v-model.trim="english.summary"
type="textarea"
:rows="2"
maxlength="120"
show-word-limit
placeholder="Enter article summary"
/>
</div>
<div class="language-field">
<label>Category</label>
<el-select v-model="english.category" placeholder="Select category">
<el-option label="Corporate News" value="Corporate News" />
<el-option label="Product News" value="Product News" />
<el-option label="Industry Insights" value="Industry Insights" />
<el-option label="Event News" value="Event News" />
</el-select>
</div>
<div class="language-field">
<label>Date</label>
<el-date-picker
v-model="english.publishTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="Select date"
/>
</div>
<div class="language-field language-field--wide">
<label>Cover</label>
<div class="language-cover">
<button type="button" class="language-cover__upload" @click="$refs.englishCoverInput.click()">
<i class="el-icon-upload2" />
Upload cover
</button>
<el-input
v-model.trim="english.coverUrl"
class="language-cover__input"
placeholder="Upload an image or paste its URL"
/>
<span v-if="english.coverName" class="language-cover__name">{{ english.coverName }}</span>
<input ref="englishCoverInput" type="file" accept="image/*" class="hidden-input" @change="handleEnglishCoverUpload">
</div>
</div>
</div>
<div class="language-richtext">
<div class="language-richtext__head">
<span>English Content</span>
<small>Rich text editor</small>
</div>
<div v-if="dialogVisible" class="wang-editor-wrap wang-editor-wrap--english">
<Toolbar
class="wang-toolbar"
:editor="englishEditor"
:default-config="toolbarConfig"
:mode="editorMode"
/>
<Editor
v-model="english.content"
class="wang-editor"
:default-config="englishEditorConfig"
:mode="editorMode"
@onCreated="handleEnglishEditorCreated"
@onDestroyed="handleEnglishEditorDestroyed"
/>
</div>
</div>
</section>
</div>
<div
@ -157,6 +259,7 @@ export default {
dirty: false,
// wangEditor
editor: null,
englishEditor: null,
// wangEditor
editorMode: 'default',
// wangEditor
@ -178,13 +281,33 @@ export default {
}
}
},
englishEditorConfig: {
placeholder: 'Start writing the English version of your article...',
MENU_CONF: {
uploadImage: {
customUpload: async(file, insertFn) => {
try {
const url = await this.uploadNewsImage(file)
insertFn(normalizeImageUrl(url), file.name, normalizeImageUrl(url))
} catch (error) {
this.$message.error('英文正文图片上传失败')
}
}
}
}
},
//
coverPreview: '',
imageUploading: false,
englishImageUploading: false,
editorFullscreen: false,
editorFullscreenObserver: null,
//
previewWidth: 400,
//
showEnglishForm: false,
//
english: this.createEmptyEnglishForm(),
//
resizing: false,
//
@ -230,6 +353,12 @@ export default {
//
this.dirty = true
}
},
english: {
deep: true,
handler() {
this.dirty = true
}
}
},
beforeDestroy() {
@ -238,6 +367,10 @@ export default {
this.editor.destroy()
this.editor = null
}
if (this.englishEditor) {
this.englishEditor.destroy()
this.englishEditor = null
}
//
this.removeResizeListeners()
this.stopObserveEditorFullscreen()
@ -259,17 +392,58 @@ export default {
coverName: ''
}
},
createEmptyEnglishForm() {
return {
title: '',
summary: '',
category: '',
publishTime: '',
coverUrl: '',
coverName: '',
content: ''
}
},
handleOpen() {
//
const article = this.article || {}
const english = article.english || {}
this.form = {
...this.createEmptyForm(),
...(this.article || {})
...article,
title: article.title || article.title_zh || '',
summary: article.summary || article.summary_zh || '',
type: article.type || article.article_type_zh || '企业动态',
publishTime: article.publishTime || article.publish_time_zh || article.publish_time || '',
content: article.content || article.content_zh || '',
coverUrl: article.coverUrl || article.cover_img_zh || article.cover_img || '',
coverName: article.coverName || article.cover_name_zh || article.cover_name || ''
}
// 使
if (!this.form.publishTime) this.form.publishTime = this.today
//
this.coverPreview = this.form.coverUrl || ''
this.editorFullscreen = false
this.imageUploading = false
this.englishImageUploading = false
this.english = {
...this.createEmptyEnglishForm(),
...english,
title: english.title || article.title_en || '',
summary: english.summary || article.summary_en || '',
category: english.category || article.article_type_en || '',
publishTime: english.publishTime || article.publish_time_en || '',
content: english.content || article.content_en || '',
coverUrl: english.coverUrl || article.cover_img_en || '',
coverName: english.coverName || article.cover_name_en || ''
}
this.showEnglishForm = Boolean(
this.english.title ||
this.english.summary ||
this.english.category ||
this.english.publishTime ||
this.english.coverUrl ||
this.english.content
)
this.$nextTick(() => {
//
this.dirty = false
@ -280,6 +454,12 @@ export default {
// 使
this.editor = Object.seal(editor)
},
handleEnglishEditorCreated(editor) {
this.englishEditor = Object.seal(editor)
},
handleEnglishEditorDestroyed() {
this.englishEditor = null
},
handleDialogClose() {
this.stopObserveEditorFullscreen()
this.editorFullscreen = false
@ -398,6 +578,23 @@ export default {
event.target.value = ''
}
},
async handleEnglishCoverUpload(event) {
const file = event.target.files && event.target.files[0]
if (!file) return
this.english.coverName = file.name
this.englishImageUploading = true
try {
this.english.coverUrl = await this.uploadNewsImage(file)
this.$message.success('英文封面图片上传成功')
} catch (error) {
this.english.coverName = ''
this.$message.error('英文封面图片上传失败')
} finally {
this.englishImageUploading = false
event.target.value = ''
}
},
handleCoverUrlInput() {
//
this.coverPreview = ''
@ -469,13 +666,16 @@ export default {
this.$message.warning('请输入文章正文')
return
}
if (this.imageUploading) {
if (this.imageUploading || this.englishImageUploading) {
this.$message.warning('图片上传中,请稍后保存')
return
}
// status 稿
const payload = {
...this.form,
english: {
...this.english
},
publish_time: this.form.publishTime,
status
}
@ -572,6 +772,21 @@ export default {
flex-direction: column;
}
.article-editor__left.has-language-form {
overflow-y: auto;
scrollbar-color: #cbd5e1 transparent;
scrollbar-width: thin;
}
.article-editor__left.has-language-form .article-editor__form {
flex-shrink: 0;
}
.article-editor__left.has-language-form .wang-editor-wrap {
flex: 0 0 420px;
min-height: 420px;
}
.resize-handle {
position: relative;
flex: 0 0 10px;
@ -614,6 +829,70 @@ export default {
border-bottom: 1px solid #edf0f5;
}
.language-trigger {
min-height: 48px;
margin: 2px 0 12px 88px;
padding: 9px 12px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
background: linear-gradient(90deg, #f8fbff 0%, #f7f5ff 100%);
border: 1px dashed #bfdbfe;
border-radius: 8px;
}
.language-trigger__title {
display: flex;
align-items: center;
gap: 9px;
}
.language-trigger__badge {
width: 26px;
height: 26px;
display: inline-flex;
align-items: center;
justify-content: center;
color: #4f46e5;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.04em;
background: #ede9fe;
border-radius: 7px;
}
.language-trigger__title strong,
.language-trigger__title small {
display: block;
}
.language-trigger__title strong {
color: #334155;
font-size: 13px;
}
.language-trigger__title small {
margin-top: 2px;
color: #94a3b8;
font-size: 11px;
}
.language-trigger__button {
padding: 5px 8px;
color: #4f46e5;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
background: transparent;
border: 0;
cursor: pointer;
}
.language-trigger__button i {
margin-left: 4px;
}
.article-editor__inline {
display: flex;
gap: 16px;
@ -671,6 +950,219 @@ export default {
overflow-y: auto;
}
.article-editor__language-section {
flex-shrink: 0;
margin-top: 22px;
padding: 24px 18px 40px 0;
border-top: 1px solid #dbeafe;
}
.language-section-head {
margin-bottom: 18px;
padding: 16px 18px;
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
background: linear-gradient(135deg, #f5f9ff 0%, #f7f5ff 100%);
border: 1px solid #dbeafe;
border-radius: 12px;
}
.language-section-head__eyebrow {
display: block;
margin-bottom: 5px;
color: #6366f1;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.12em;
}
.language-section-head h3 {
margin: 0;
color: #1e293b;
font-size: 16px;
line-height: 1.4;
}
.language-section-head p {
margin: 5px 0 0;
color: #94a3b8;
font-size: 12px;
}
.language-section-head__tag {
padding: 4px 9px;
color: #4f46e5;
font-size: 12px;
font-weight: 600;
background: #ede9fe;
border-radius: 999px;
}
.language-form-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}
.language-field--wide {
grid-column: 1 / -1;
}
.language-field label {
display: block;
margin-bottom: 7px;
color: #475569;
font-size: 12px;
font-weight: 600;
}
.language-field .el-select,
.language-field .el-date-editor {
width: 100%;
}
.language-cover {
min-height: 32px;
padding: 5px 10px;
display: flex;
align-items: center;
gap: 10px;
color: #94a3b8;
font-size: 12px;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
}
.language-cover__upload {
padding: 5px 9px;
color: #fff;
font-size: 12px;
background: #409eff;
border: 0;
border-radius: 3px;
cursor: pointer;
}
.language-cover__upload i {
margin-right: 3px;
}
.language-cover__input {
flex: 1;
min-width: 0;
}
.language-cover__name {
max-width: 120px;
overflow: hidden;
color: #16a34a;
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
}
.language-richtext {
margin-top: 20px;
}
.language-richtext .wang-editor-wrap {
height: 420px;
min-height: 420px;
padding-right: 0;
}
.language-richtext .wang-toolbar {
border-radius: 0;
}
.language-richtext__head {
padding: 12px 14px 8px;
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
border: 1px solid #edf0f5;
border-bottom: 0;
border-radius: 10px 10px 0 0;
}
.language-richtext__head span {
color: #334155;
font-size: 13px;
font-weight: 600;
}
.language-richtext__head small {
color: #94a3b8;
font-size: 11px;
}
.language-richtext__toolbar {
min-height: 38px;
padding: 0 10px;
display: flex;
align-items: center;
gap: 5px;
color: #64748b;
background: #f8fafc;
border-top: 1px solid #edf2f7;
border-bottom: 1px solid #edf2f7;
}
.language-richtext__toolbar > span {
min-width: 24px;
height: 24px;
padding: 0 5px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 12px;
border-radius: 4px;
}
.language-richtext__toolbar > span:not(.language-richtext__divider):hover {
color: #2563eb;
background: #eff6ff;
}
.language-richtext__strong {
font-weight: 700;
}
.language-richtext__italic {
font-family: Georgia, serif;
font-style: italic;
font-weight: 700;
}
.language-richtext__toolbar .language-richtext__divider {
min-width: 1px;
width: 1px;
height: 18px;
padding: 0;
margin: 0 4px;
background: #dbe2ea;
}
.language-richtext__canvas {
min-height: 230px;
padding: 16px;
color: #c0c7d1;
font-size: 13px;
line-height: 1.8;
cursor: text;
outline: none;
}
.language-richtext__canvas:empty::before {
content: attr(data-placeholder);
color: #c0c7d1;
pointer-events: none;
}
.article-editor__preview {
flex: 0 0 auto;
display: flex;

View File

@ -53,6 +53,16 @@ export default {
}
}
},
computed: {
isEnglish() {
return this.$i18n && this.$i18n.locale === 'en-US'
}
},
watch: {
isEnglish() {
this.getNewsDetail()
}
},
created() {
this.getNewsDetail()
},
@ -84,6 +94,10 @@ export default {
if (/^(https?:|blob:|data:|\/\/)/.test(url)) return url
return `${window.location.origin}/idfile?path=${url}`
},
getLocalizedField(row, zhField, enField, legacyField) {
if (this.isEnglish && row[enField]) return row[enField]
return row[zhField] || row[legacyField] || row[enField] || ''
},
getResponseDetail(res) {
if (res.data && res.data.data && !Array.isArray(res.data.data)) return res.data.data
if (res.data && !Array.isArray(res.data)) return res.data
@ -94,12 +108,12 @@ export default {
normalizeArticle(row) {
return {
id: row.id || this.$route.params.id,
title: row.title || '未命名文章',
summary: row.summary || '',
articleType: row.article_type || row.type || '企业动态',
publishTime: row.publish_time || row.publishTime || '',
coverImg: this.normalizeImageUrl(row.cover_img || row.coverImg || ''),
content: row.content || ''
title: this.getLocalizedField(row, 'title_zh', 'title_en', 'title') || '未命名文章',
summary: this.getLocalizedField(row, 'summary_zh', 'summary_en', 'summary'),
articleType: this.getLocalizedField(row, 'article_type_zh', 'article_type_en', 'article_type') || row.type || '企业动态',
publishTime: this.getLocalizedField(row, 'publish_time_zh', 'publish_time_en', 'publish_time') || row.publishTime || '',
coverImg: this.normalizeImageUrl(this.getLocalizedField(row, 'cover_img_zh', 'cover_img_en', 'cover_img') || row.coverImg || ''),
content: this.getLocalizedField(row, 'content_zh', 'content_en', 'content')
}
},
async getNewsDetail() {

View File

@ -291,16 +291,25 @@ export default {
// 使
return {
id: row.id,
title: row.title || '',
summary: row.summary || '',
type: row.article_type || row.type || '企业动态',
title: row.title_zh || row.title || '',
summary: row.summary_zh || row.summary || '',
type: row.article_type_zh || row.article_type || row.type || '企业动态',
status: this.getViewStatus(row.status),
publishTime: row.publish_time || row.publishTime || '',
publishTime: row.publish_time_zh || row.publish_time || row.publishTime || '',
updateTime: row.update_time || row.updateTime || '',
views: row.read_count || row.views || 0,
content: row.content || '',
coverUrl: row.cover_img || row.coverUrl || '',
coverName: row.cover_name || row.coverName || ''
content: row.content_zh || row.content || '',
coverUrl: row.cover_img_zh || row.cover_img || row.coverUrl || '',
coverName: row.cover_name_zh || row.cover_name || row.coverName || '',
english: {
title: row.title_en || '',
summary: row.summary_en || '',
category: row.article_type_en || '',
publishTime: row.publish_time_en || '',
content: row.content_en || '',
coverUrl: row.cover_img_en || '',
coverName: row.cover_name_en || ''
}
}
},
getResponseList(res) {
@ -325,17 +334,24 @@ export default {
)
},
buildArticlePayload(article) {
// /
// /
const english = article.english || {}
return {
...(article.id ? { id: article.id } : {}),
url_link: window.location.href,
title: article.title,
article_type: article.type,
summary: article.summary,
title_zh: article.title,
title_en: english.title || '',
article_type_zh: article.type,
article_type_en: english.category || '',
summary_zh: article.summary,
summary_en: english.summary || '',
update_time: article.update_time || article.updateTime,
publish_time: article.publish_time || article.publishTime,
cover_img: article.coverUrl,
content: article.content,
publish_time_zh: article.publish_time_zh || article.publishTime,
publish_time_en: english.publishTime || '',
cover_img_zh: article.coverUrl,
cover_img_en: english.coverUrl || '',
content_zh: article.content,
content_en: english.content || '',
status: this.getApiStatus(article.status)
}
},

View File

@ -11,10 +11,9 @@
<div class="hero-content">
<span class="hero-badge">COMPANY NEWS</span>
<div class="hero-title-row">
<h1>企业动态</h1>
<button type="button" class="about-link" @click="goAbout">关于我们 </button>
<h1>{{ isEnglish ? 'Company News' : '企业动态' }}</h1>
</div>
<p>了解开元云最新动态把握AI行业前沿资讯与我们一起见证智能跃迁</p>
<p>{{ isEnglish ? 'Stay up to date with Open Computing AI, explore the latest AI industry insights, and witness the intelligent leap with us.' : '了解开元云最新动态把握AI行业前沿资讯与我们一起见证智能跃迁' }}</p>
</div>
</div>
</section>
@ -115,7 +114,6 @@ export default {
fallbackNewsImage: require('@/assets/image/news.jpg'),
activeCategory: 'all',
page: 1,
pageSize: 10,
total: 0,
filterTabs: [
@ -129,6 +127,9 @@ export default {
}
},
computed: {
isEnglish() {
return this.$i18n && this.$i18n.locale === 'en-US'
},
featuredNews() {
return this.newsList[0]
},
@ -142,6 +143,11 @@ export default {
return Array.from({ length: Math.min(this.totalPages, 3) }, (_, index) => index + 1)
}
},
watch: {
isEnglish() {
this.getNewsList()
}
},
created() {
this.getNewsList()
},
@ -187,26 +193,34 @@ export default {
企业动态: 'rgba(16,185,129,0.85)',
产品动态: 'rgba(99,102,241,0.85)',
行业洞察: 'rgba(13,148,136,0.85)',
活动资讯: 'rgba(245,158,11,0.85)'
活动资讯: 'rgba(245,158,11,0.85)',
'Corporate News': 'rgba(16,185,129,0.85)',
'Product News': 'rgba(99,102,241,0.85)',
'Industry Insights': 'rgba(13,148,136,0.85)',
'Event News': 'rgba(245,158,11,0.85)'
}
return map[type] || 'rgba(99,102,241,0.85)'
},
getLocalizedField(row, zhField, enField, legacyField) {
if (this.isEnglish && row[enField]) return row[enField]
return row[zhField] || row[legacyField] || row[enField] || ''
},
normalizeImageUrl(url) {
if (!url) return ''
if (/^(https?:|blob:|data:|\/\/)/.test(url)) return url
return `${window.location.origin}/idfile?path=${url}`
},
normalizeNewsItem(row) {
const type = row.article_type || '企业动态'
const type = this.getLocalizedField(row, 'article_type_zh', 'article_type_en', 'article_type') || '企业动态'
return {
id: row.id,
category: type,
tag: type,
tagColor: this.getTagColor(type),
date: row.publish_time || '',
title: row.title || '未命名文章',
desc: row.summary || '',
img: this.normalizeImageUrl(row.cover_img || ''),
date: this.getLocalizedField(row, 'publish_time_zh', 'publish_time_en', 'publish_time'),
title: this.getLocalizedField(row, 'title_zh', 'title_en', 'title') || '未命名文章',
desc: this.getLocalizedField(row, 'summary_zh', 'summary_en', 'summary'),
img: this.normalizeImageUrl(this.getLocalizedField(row, 'cover_img_zh', 'cover_img_en', 'cover_img')),
views: row.read_count || 0
}
},

View File

@ -1,14 +1,6 @@
<template>
<el-dialog
custom-class="forgot-password-dialog"
:visible="visible"
width="540px"
:close-on-click-modal="false"
destroy-on-close
append-to-body
@open="handleOpen"
@close="handleClose"
>
<el-dialog custom-class="forgot-password-dialog" :visible="visible" width="540px" :close-on-click-modal="false"
destroy-on-close append-to-body @open="handleOpen" @close="handleClose">
<div slot="title" class="forgot-dialog-title">
<div class="title-icon">
<i class="el-icon-lock"></i>
@ -25,18 +17,15 @@
</el-form-item>
<el-form-item label="新密码" prop="password">
<el-input v-model="form.password" clearable show-password autocomplete="new-password" placeholder="请输入新密码"></el-input>
<el-input v-model="form.password" clearable show-password autocomplete="new-password"
placeholder="请输入新密码"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="vcode">
<div class="code-row">
<el-input v-model="form.vcode" clearable autocomplete="off" placeholder="请输入验证码"></el-input>
<el-button
class="code-btn"
:disabled="isDisabled || isGettingCode"
:loading="isGettingCode"
@click="debouncedGetCode"
>
<el-button class="code-btn" :disabled="isDisabled || isGettingCode" :loading="isGettingCode"
@click="debouncedGetCode">
{{ sendCodeText }}
</el-button>
</div>
@ -288,18 +277,21 @@ export default {
}
.code-btn {
width: 118px;
height: 48px;
color: #2f6bff;
background: #eef4ff;
border-color: #cfe0ff;
padding: 0 18px;
color: #1d4ed8;
font-size: 14px;
font-weight: 600;
white-space: nowrap;
cursor: pointer;
border: 1px solid rgba(37, 99, 235, 0.35);
border-radius: 14px;
background: rgba(255, 255, 255, 0.94);
transition: all 0.2s ease;
&:hover,
&:focus {
color: #ffffff;
background: #2f6bff;
border-color: #2f6bff;
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}