745 行
18 KiB
Plaintext
745 行
18 KiB
Plaintext
<template>
|
||
<view class="articles-page" :class="pageRtlClass" :style="pageTheme">
|
||
<!-- 顶部极光微光晕 -->
|
||
<view class="ambient-aurora-glow"></view>
|
||
|
||
<!-- 顶部标题栏 -->
|
||
<view class="articles-header-bar">
|
||
<view class="articles-title-group">
|
||
<text class="articles-heading">{{ t('title') }}</text>
|
||
<text class="articles-subtitle">{{ t('subtitle') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 骨架屏加载态 -->
|
||
<view v-if="state.loading" class="articles-skeleton">
|
||
<view class="skeleton-card"></view>
|
||
<view class="skeleton-card"></view>
|
||
</view>
|
||
|
||
<!-- 空状态展示 -->
|
||
<view v-else-if="state.empty" class="articles-empty-card">
|
||
<view class="empty-badge">
|
||
<text class="empty-badge-icon">!</text>
|
||
</view>
|
||
<text class="empty-title">{{ t('emptyTitle') }}</text>
|
||
<text class="empty-desc">{{ t('emptyDesc') }}</text>
|
||
</view>
|
||
|
||
<!-- 文章动态列表 -->
|
||
<scroll-view v-else class="articles-scroll" :scroll-y="true">
|
||
<view class="articles-list">
|
||
<view v-for="item in state.list" :key="item.id" class="article-item-card">
|
||
<image
|
||
v-if="item.coverImage != null && item.coverImage !== ''"
|
||
class="article-item-cover"
|
||
:src="item.coverImage!"
|
||
mode="aspectFill"
|
||
/>
|
||
|
||
<view class="article-item-body">
|
||
<view class="article-item-header">
|
||
<text class="article-item-title">{{ item.title }}</text>
|
||
<view
|
||
class="article-status-pill"
|
||
:class="item.isPublished ? 'status-pill-published' : 'status-pill-draft'"
|
||
@click="handleToggleStatus(item)"
|
||
>
|
||
<text class="article-status-text">
|
||
{{ item.isPublished ? t('statusPublished') : t('statusDraft') }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<text v-if="item.summary != null && item.summary !== ''" class="article-item-summary">
|
||
{{ item.summary }}
|
||
</text>
|
||
|
||
<view class="article-item-actions">
|
||
<button class="action-btn action-btn-edit" @click="handleOpenEdit(item)">
|
||
<text class="action-btn-text">{{ t('editBtn') }}</text>
|
||
</button>
|
||
<button class="action-btn action-btn-delete" @click="handleDelete(item)">
|
||
<text class="action-btn-delete-text">{{ t('deleteBtn') }}</text>
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部常驻主 CTA 悬浮栏 -->
|
||
<view class="articles-bottom-bar">
|
||
<button class="primary-cta-btn" @click="handleOpenAdd">
|
||
<text class="primary-cta-btn-text">{{ t('publishBtn') }}</text>
|
||
</button>
|
||
</view>
|
||
|
||
<!-- 底部编辑抽屉 (Bottom Sheet) -->
|
||
<view v-if="state.drawerVisible" class="drawer-mask" @click="handleCloseDrawer">
|
||
<view class="drawer-sheet" @click.stop="">
|
||
<view class="drawer-handle-bar">
|
||
<view class="drawer-handle"></view>
|
||
</view>
|
||
|
||
<view class="drawer-header">
|
||
<text class="drawer-title">{{ isEditing ? t('editBtn') : t('publishBtn') }}</text>
|
||
<text class="drawer-close" @click="handleCloseDrawer">×</text>
|
||
</view>
|
||
|
||
<scroll-view class="drawer-scroll" :scroll-y="true">
|
||
<view class="drawer-form">
|
||
<!-- 标题 -->
|
||
<view class="form-field">
|
||
<text class="form-label">{{ t('fieldTitle') }} *</text>
|
||
<input
|
||
class="form-input"
|
||
type="text"
|
||
v-model="editForm.title"
|
||
placeholder="例如:2026 全球智能硬件合规白皮书"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 摘要导读 -->
|
||
<view class="form-field">
|
||
<text class="form-label">{{ t('fieldSummary') }}</text>
|
||
<input
|
||
class="form-input"
|
||
type="text"
|
||
v-model="editForm.summary"
|
||
placeholder="若不填写将自动从正文中提取摘要..."
|
||
/>
|
||
</view>
|
||
|
||
<!-- 封面图 -->
|
||
<view class="form-field">
|
||
<text class="form-label">{{ t('fieldCover') }}</text>
|
||
<image-uploader
|
||
:max-count="1"
|
||
:model-value="uploadedCover"
|
||
@update:modelValue="handleCoverChange"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 正文内容 -->
|
||
<view class="form-field">
|
||
<text class="form-label">{{ t('fieldContent') }} *</text>
|
||
<textarea
|
||
class="form-textarea"
|
||
v-model="editForm.content"
|
||
placeholder="输入正文内容,支持段落与 Markdown..."
|
||
maxlength="2000"
|
||
></textarea>
|
||
</view>
|
||
|
||
<!-- 公开发布状态 -->
|
||
<view class="form-field-switch">
|
||
<view class="switch-info">
|
||
<text class="switch-title">{{ t('fieldPublish') }}</text>
|
||
<text class="switch-desc">{{ publishDescText }}</text>
|
||
</view>
|
||
<switch
|
||
:checked="editForm.isPublished"
|
||
color="#0088FF"
|
||
@change="handleSwitchChange"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 抽屉底部操作条 -->
|
||
<view class="drawer-action-bar">
|
||
<button class="drawer-btn-cancel" @click="handleCloseDrawer">
|
||
<text class="drawer-btn-cancel-text">{{ t('cancelBtn') }}</text>
|
||
</button>
|
||
<button
|
||
class="primary-cta-btn drawer-btn-save"
|
||
:disabled="state.saving"
|
||
@click="handleSave"
|
||
>
|
||
<text class="primary-cta-btn-text">{{ state.saving ? savingText : t('saveBtn') }}</text>
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { CardArticle } from '../../../common/types.uts';
|
||
import {
|
||
createArticlesState,
|
||
loadArticles,
|
||
saveArticle,
|
||
deleteArticle,
|
||
toggleArticlePublish,
|
||
resolveArticlesText,
|
||
ArticlesCopyKey,
|
||
} from './useCardArticles.uts';
|
||
import ImageUploader from '../../../components/image-uploader/image-uploader.uvue';
|
||
import { getCurrentLocale, isRtl } from '../../../common/locale.uts';
|
||
import { utsLightColors, utsRadius, utsSpacing, utsTypography } from '../../../common/tokens.uts';
|
||
|
||
const currentCardId = ref<string>('1001');
|
||
const state = reactive(createArticlesState('1001'));
|
||
|
||
const editForm = reactive<Partial<CardArticle>>({
|
||
title: '',
|
||
summary: '',
|
||
coverImage: '',
|
||
content: '',
|
||
isPublished: true,
|
||
});
|
||
|
||
const uploadedCover = ref<string[]>([]);
|
||
|
||
const isEditing = computed<boolean>(() => {
|
||
return editForm.id != null;
|
||
});
|
||
|
||
const pageRtlClass = computed<string>(() => {
|
||
return isRtl(getCurrentLocale()) ? 'page-rtl' : '';
|
||
});
|
||
|
||
const publishDescText = computed<string>(() => {
|
||
return getCurrentLocale() === 'zh-CN'
|
||
? '开启后,全球访客可在您的名片微官网中直接浏览'
|
||
: 'When enabled, visitors can view this insight on your micro-site';
|
||
});
|
||
|
||
const savingText = computed<string>(() => {
|
||
return getCurrentLocale() === 'zh-CN' ? '保存中...' : 'Saving...';
|
||
});
|
||
|
||
const pageTheme: Record<string, string> = {
|
||
'--oc-primary': utsLightColors.primary,
|
||
'--oc-primary-gradient': utsLightColors.primaryGradient,
|
||
'--oc-primary-soft': utsLightColors.primarySoft,
|
||
'--oc-aurora': utsLightColors.aurora,
|
||
'--oc-bg': utsLightColors.bg,
|
||
'--oc-surface': utsLightColors.surface,
|
||
'--oc-border': utsLightColors.border,
|
||
'--oc-text': utsLightColors.text,
|
||
'--oc-text-2': utsLightColors.text2,
|
||
'--oc-success': utsLightColors.success,
|
||
'--oc-warning': utsLightColors.warning,
|
||
'--oc-error': utsLightColors.error,
|
||
'--oc-radius-btn': utsRadius.btn,
|
||
'--oc-radius-card': utsRadius.card,
|
||
'--oc-radius-sheet': utsRadius.sheet,
|
||
'--oc-space-16': utsSpacing.s16,
|
||
'--oc-space-24': utsSpacing.s24,
|
||
'--oc-font-title': utsTypography.title,
|
||
'--oc-font-body': utsTypography.body,
|
||
'--oc-font-caption': utsTypography.caption,
|
||
};
|
||
|
||
function t(key: ArticlesCopyKey): string {
|
||
return resolveArticlesText(key);
|
||
}
|
||
|
||
function handleOpenAdd(): void {
|
||
editForm.id = undefined;
|
||
editForm.title = '';
|
||
editForm.summary = '';
|
||
editForm.coverImage = '';
|
||
editForm.content = '';
|
||
editForm.isPublished = true;
|
||
uploadedCover.value = [];
|
||
state.drawerVisible = true;
|
||
}
|
||
|
||
function handleOpenEdit(item: CardArticle): void {
|
||
editForm.id = item.id;
|
||
editForm.title = item.title;
|
||
editForm.summary = item.summary || '';
|
||
editForm.coverImage = item.coverImage || '';
|
||
editForm.content = item.content || '';
|
||
editForm.isPublished = item.isPublished;
|
||
uploadedCover.value = item.coverImage ? [item.coverImage] : [];
|
||
state.drawerVisible = true;
|
||
}
|
||
|
||
function handleCloseDrawer(): void {
|
||
state.drawerVisible = false;
|
||
}
|
||
|
||
function handleCoverChange(imgs: string[]): void {
|
||
uploadedCover.value = imgs;
|
||
if (imgs.length > 0) {
|
||
editForm.coverImage = imgs[0];
|
||
} else {
|
||
editForm.coverImage = '';
|
||
}
|
||
}
|
||
|
||
function handleSwitchChange(e: any): void {
|
||
editForm.isPublished = Boolean(e.detail.value);
|
||
}
|
||
|
||
async function handleToggleStatus(item: CardArticle): Promise<void> {
|
||
const ok = await toggleArticlePublish(state, item);
|
||
if (ok) {
|
||
uni.showToast({
|
||
title: getCurrentLocale() === 'zh-CN' ? '状态已切换' : 'Status Updated',
|
||
icon: 'none',
|
||
});
|
||
}
|
||
}
|
||
|
||
async function handleSave(): Promise<void> {
|
||
const success = await saveArticle(state, editForm);
|
||
if (success) {
|
||
uni.showToast({
|
||
title: getCurrentLocale() === 'zh-CN' ? '动态已保存' : 'Article Saved',
|
||
icon: 'none',
|
||
});
|
||
} else if (state.errorMessage !== '') {
|
||
uni.showToast({
|
||
title: state.errorMessage,
|
||
icon: 'none',
|
||
});
|
||
}
|
||
}
|
||
|
||
async function handleDelete(item: CardArticle): void {
|
||
if (item.id == null) return;
|
||
const zh = getCurrentLocale() === 'zh-CN';
|
||
uni.showModal({
|
||
title: zh ? '确认删除' : 'Confirm Delete',
|
||
content: zh ? '确定要删除该文章动态吗?' : 'Are you sure you want to delete this article?',
|
||
confirmText: zh ? '删除' : 'Delete',
|
||
cancelText: zh ? '取消' : 'Cancel',
|
||
success: async (res: any) => {
|
||
if (res.confirm) {
|
||
const ok = await deleteArticle(state, item.id!);
|
||
if (ok) {
|
||
uni.showToast({
|
||
title: zh ? '已删除' : 'Deleted',
|
||
icon: 'none',
|
||
});
|
||
}
|
||
}
|
||
},
|
||
});
|
||
}
|
||
|
||
onLoad((options: any) => {
|
||
const id = options && (options.cardId || options.id) ? String(options.cardId || options.id) : '1001';
|
||
currentCardId.value = id;
|
||
state.cardId = id;
|
||
loadArticles(state);
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.articles-page {
|
||
position: relative;
|
||
min-height: 100vh;
|
||
background-color: var(--oc-bg);
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.ambient-aurora-glow {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 160px;
|
||
background: var(--oc-aurora);
|
||
opacity: 0.08;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.articles-header-bar {
|
||
padding: 20px 16px 12px 16px;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.articles-heading {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
color: var(--oc-text);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.articles-subtitle {
|
||
font-size: 13px;
|
||
color: var(--oc-text-2);
|
||
margin-top: 6px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.articles-scroll {
|
||
flex: 1;
|
||
padding: 0 16px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.articles-list {
|
||
padding-bottom: 96px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 14px;
|
||
}
|
||
|
||
.article-item-card {
|
||
background-color: var(--oc-surface);
|
||
border-radius: var(--oc-radius-card);
|
||
overflow: hidden;
|
||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.04), 0 2px 8px rgba(11, 99, 229, 0.03);
|
||
border: 1px solid var(--oc-border);
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.article-item-cover {
|
||
width: 100%;
|
||
height: 150px;
|
||
background-color: #EBF1F7;
|
||
}
|
||
|
||
.article-item-body {
|
||
padding: 16px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.article-item-header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
gap: 8px;
|
||
}
|
||
|
||
.article-item-title {
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
color: var(--oc-text);
|
||
flex: 1;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.article-status-pill {
|
||
padding: 4px 10px;
|
||
border-radius: 9999px;
|
||
}
|
||
|
||
.status-pill-published {
|
||
background-color: #ECFDF3;
|
||
}
|
||
|
||
.status-pill-draft {
|
||
background-color: #F2F4F7;
|
||
}
|
||
|
||
.article-status-text {
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: var(--oc-text);
|
||
}
|
||
|
||
.article-item-summary {
|
||
font-size: 13px;
|
||
color: var(--oc-text-2);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.article-item-actions {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: flex-end;
|
||
gap: 10px;
|
||
margin-top: 8px;
|
||
border-top: 1px solid var(--oc-border);
|
||
padding-top: 10px;
|
||
}
|
||
|
||
.action-btn {
|
||
height: 44px;
|
||
min-height: 44px;
|
||
padding: 0 16px;
|
||
border-radius: var(--oc-radius-btn);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: none;
|
||
}
|
||
|
||
.action-btn-edit {
|
||
background-color: var(--oc-primary-soft);
|
||
}
|
||
|
||
.action-btn-text {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: var(--oc-primary);
|
||
}
|
||
|
||
.action-btn-delete {
|
||
background-color: #FFF1F0;
|
||
}
|
||
|
||
.action-btn-delete-text {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: var(--oc-error);
|
||
}
|
||
|
||
.articles-empty-card {
|
||
margin: 40px 16px;
|
||
padding: 32px 20px;
|
||
background-color: var(--oc-surface);
|
||
border-radius: var(--oc-radius-card);
|
||
text-align: center;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.empty-badge {
|
||
width: 48px;
|
||
height: 48px;
|
||
border-radius: 24px;
|
||
background-color: var(--oc-primary-soft);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.empty-badge-icon {
|
||
font-size: 20px;
|
||
font-weight: 700;
|
||
color: var(--oc-primary);
|
||
}
|
||
|
||
.empty-title {
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
color: var(--oc-text);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.empty-desc {
|
||
font-size: 13px;
|
||
color: var(--oc-text-2);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.articles-bottom-bar {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
padding: 12px 16px;
|
||
padding-bottom: calc(12px + env(safe-area-inset-bottom));
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(12px);
|
||
border-top: 1px solid var(--oc-border);
|
||
z-index: 10;
|
||
}
|
||
|
||
.primary-cta-btn {
|
||
width: 100%;
|
||
height: 48px;
|
||
min-height: 44px;
|
||
background: var(--oc-primary-gradient);
|
||
border-radius: 9999px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: none;
|
||
box-shadow: 0 8px 20px rgba(0, 136, 255, 0.22);
|
||
}
|
||
|
||
.primary-cta-btn-text {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
/* 抽屉样式 */
|
||
.drawer-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.45);
|
||
z-index: 100;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.drawer-sheet {
|
||
background-color: var(--oc-surface);
|
||
border-top-left-radius: var(--oc-radius-sheet);
|
||
border-top-right-radius: var(--oc-radius-sheet);
|
||
max-height: 85vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
}
|
||
|
||
.drawer-handle-bar {
|
||
padding-top: 10px;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.drawer-handle {
|
||
width: 36px;
|
||
height: 4px;
|
||
background-color: #D0D5DD;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.drawer-header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px 20px 16px 20px;
|
||
border-bottom: 1px solid var(--oc-border);
|
||
}
|
||
|
||
.drawer-title {
|
||
font-size: 17px;
|
||
font-weight: 700;
|
||
color: var(--oc-text);
|
||
}
|
||
|
||
.drawer-close {
|
||
font-size: 24px;
|
||
color: var(--oc-text-2);
|
||
line-height: 1;
|
||
padding: 4px 8px;
|
||
}
|
||
|
||
.drawer-scroll {
|
||
max-height: 60vh;
|
||
padding: 16px 20px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.drawer-form {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
padding-bottom: 20px;
|
||
}
|
||
|
||
.form-field {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.form-field-switch {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px 0;
|
||
border-top: 1px solid var(--oc-border);
|
||
}
|
||
|
||
.switch-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.switch-title {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--oc-text);
|
||
}
|
||
|
||
.switch-desc {
|
||
font-size: 12px;
|
||
color: var(--oc-text-2);
|
||
}
|
||
|
||
.form-label {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--oc-text);
|
||
}
|
||
|
||
.form-input {
|
||
height: 44px;
|
||
min-height: 44px;
|
||
font-size: 16px;
|
||
border: 1px solid var(--oc-border);
|
||
border-radius: var(--oc-radius-btn);
|
||
padding: 0 14px;
|
||
background-color: #FAFAFA;
|
||
color: var(--oc-text);
|
||
}
|
||
|
||
.form-textarea {
|
||
font-size: 16px;
|
||
border: 1px solid var(--oc-border);
|
||
border-radius: var(--oc-radius-btn);
|
||
padding: 12px 14px;
|
||
background-color: #FAFAFA;
|
||
color: var(--oc-text);
|
||
height: 120px;
|
||
}
|
||
|
||
.drawer-action-bar {
|
||
display: flex;
|
||
flex-direction: row;
|
||
gap: 12px;
|
||
padding: 12px 20px;
|
||
border-top: 1px solid var(--oc-border);
|
||
}
|
||
|
||
.drawer-btn-cancel {
|
||
flex: 1;
|
||
height: 46px;
|
||
min-height: 44px;
|
||
background-color: #F2F4F7;
|
||
border-radius: 9999px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: none;
|
||
}
|
||
|
||
.drawer-btn-cancel-text {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: var(--oc-text-2);
|
||
}
|
||
|
||
.drawer-btn-save {
|
||
flex: 2;
|
||
height: 46px;
|
||
min-height: 44px;
|
||
}
|
||
|
||
.skeleton-card {
|
||
height: 120px;
|
||
background: #EAECF0;
|
||
border-radius: var(--oc-radius-card);
|
||
margin: 16px;
|
||
animation: pulse 1.5s infinite ease-in-out;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { opacity: 0.6; }
|
||
50% { opacity: 1; }
|
||
100% { opacity: 0.6; }
|
||
}
|
||
</style>
|