fix: 优化业务表格展示与登录会话体验

This commit is contained in:
Cheng Zhou
2026-03-31 14:37:06 +08:00
parent ceda34fd1d
commit a7bbcaa5dc
30 changed files with 461 additions and 275 deletions
+7 -7
View File
@@ -1,33 +1,33 @@
<template>
<el-table :data="items" v-loading="loading" style="width: 100%" class="faq-table" @row-click="onRowClick">
<el-table-column prop="question" :label="TEXT.common.fields.question" min-width="200">
<el-table :data="items" v-loading="loading" style="width: 100%" class="faq-table" @row-click="onRowClick" table-layout="fixed">
<el-table-column prop="question" :label="TEXT.common.fields.question" show-overflow-tooltip>
<template #default="scope">
<el-link type="primary" :underline="false" class="question-link">
{{ scope.row.question }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="category_id" :label="TEXT.common.labels.category" width="140">
<el-table-column prop="category_id" :label="TEXT.common.labels.category" show-overflow-tooltip>
<template #default="scope">
{{ categoryMap[scope.row.category_id] || scope.row.category_id }}
</template>
</el-table-column>
<el-table-column prop="is_active" :label="TEXT.common.fields.enabled" width="80">
<el-table-column prop="is_active" :label="TEXT.common.fields.enabled">
<template #default="scope">
<el-tag :type="scope.row.is_active ? 'success' : 'info'">
{{ scope.row.is_active ? TEXT.common.boolean.yes : TEXT.common.boolean.no }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" width="180">
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" show-overflow-tooltip>
<template #default="scope">{{ displayDateTime(scope.row.updated_at) }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" width="120">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="statusTagType(scope.row.status)" size="small">{{ statusLabel(scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="180">
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<el-button v-if="canDelete(scope.row)" type="text" size="small" class="danger" @click="remove(scope.row)">
{{ TEXT.common.actions.delete }}
@@ -10,22 +10,22 @@
@uploaded="load"
/>
</div>
<el-table :data="attachments" v-loading="loading" style="width: 100%" class="attachment-table">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="200" />
<el-table-column :label="TEXT.common.labels.size" width="120">
<el-table :data="attachments" v-loading="loading" style="width: 100%" class="attachment-table" table-layout="fixed">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.size">
<template #default="scope">{{ formatFileSize(scope.row.file_size ?? scope.row.size) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.uploader" width="180">
<el-table-column :label="TEXT.common.labels.uploader" show-overflow-tooltip>
<template #default="scope">
{{ uploaderLabel(scope.row) }}
</template>
</el-table-column>
<el-table-column prop="uploaded_at" :label="TEXT.common.labels.uploadedAt" width="180">
<el-table-column prop="uploaded_at" :label="TEXT.common.labels.uploadedAt" show-overflow-tooltip>
<template #default="scope">
{{ displayDateTime(scope.row.uploaded_at) }}
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="220">
<el-table-column :label="TEXT.common.labels.actions" width="160">
<template #default="scope">
<el-button link type="primary" size="small" @click="preview(scope.row)">
{{ TEXT.common.labels.preview }}
@@ -28,12 +28,12 @@
<div v-if="(grouped[group.key] || []).length === 0" class="group-empty">
<StateEmpty :description="group.emptyText" />
</div>
<el-table v-else :data="grouped[group.key]" style="width: 100%" class="group-table">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" min-width="160" />
<el-table-column :label="TEXT.common.labels.size" width="110">
<el-table v-else :data="grouped[group.key]" style="width: 100%" class="group-table" table-layout="fixed">
<el-table-column prop="filename" :label="TEXT.common.labels.filename" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.size">
<template #default="scope">{{ formatFileSize(scope.row.size || scope.row.file_size) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.uploader" width="140">
<el-table-column :label="TEXT.common.labels.uploader" show-overflow-tooltip>
<template #default="scope">
{{ uploaderLabel(scope.row) }}
</template>
+28
View File
@@ -0,0 +1,28 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createPinia, setActivePinia } from "pinia";
describe("session store", () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-03-31T12:00:00.000Z"));
setActivePinia(createPinia());
});
it("resets activity timestamps when unlocking a previously stale session", async () => {
const { useSessionStore } = await import("./session");
const session = useSessionStore();
const staleTs = Date.now() - 2 * 60 * 60 * 1000 - 1_000;
session.recordUserActivity(staleTs);
session.recordNetworkActivity(staleTs);
session.setLastExtendAt(staleTs);
session.lock("token_invalid", "user@example.com", staleTs + 10_000);
session.unlock();
expect(session.locked).toBe(false);
expect(session.lastUserActiveAt).toBe(Date.now());
expect(session.lastNetworkActiveAt).toBe(Date.now());
expect(session.lastExtendAt).toBe(0);
});
});
+4
View File
@@ -29,11 +29,15 @@ export const useSessionStore = defineStore("session", () => {
};
const unlock = () => {
const now = Date.now();
locked.value = false;
lockReason.value = null;
lockEmail.value = "";
lockAutoLogoutDeadlineAt.value = 0;
unlockAttempts.value = 0;
lastUserActiveAt.value = now;
lastNetworkActiveAt.value = now;
lastExtendAt.value = 0;
};
const incrementUnlockAttempt = () => {
@@ -14,22 +14,22 @@
</div>
</div>
<div class="unified-section approval-table-section">
<el-table :data="users" v-loading="loading" class="approval-table" style="width: 100%">
<el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" />
<el-table-column prop="role" :label="TEXT.common.labels.role" width="120">
<el-table :data="users" v-loading="loading" class="approval-table" style="width: 100%" table-layout="fixed">
<el-table-column prop="email" :label="TEXT.common.fields.email" show-overflow-tooltip />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" show-overflow-tooltip />
<el-table-column prop="role" :label="TEXT.common.labels.role">
<template #default="scope">{{ displayEnum(TEXT.enums.userRole, scope.row.role) }}</template>
</el-table-column>
<el-table-column prop="department" :label="TEXT.common.fields.department" min-width="160" />
<el-table-column prop="created_at" :label="TEXT.modules.adminUserApproval.createdAt" width="200">
<el-table-column prop="department" :label="TEXT.common.fields.department" show-overflow-tooltip />
<el-table-column prop="created_at" :label="TEXT.modules.adminUserApproval.createdAt" show-overflow-tooltip>
<template #default="scope">{{ displayDateTime(scope.row.created_at) }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" width="120">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="statusType(scope.row.status)">{{ displayEnum(TEXT.enums.userStatus, scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="220" align="center">
<el-table-column :label="TEXT.common.labels.actions" width="140" align="center">
<template #default="scope">
<el-button
v-if="scope.row.status === 'PENDING'"
+8 -8
View File
@@ -60,20 +60,20 @@
</el-form>
</div>
<div class="unified-section table-section">
<el-table :data="logs" v-loading="loading" class="audit-table" style="width: 100%" stripe>
<el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" width="180" align="center">
<el-table :data="logs" v-loading="loading" class="audit-table" style="width: 100%" stripe table-layout="fixed">
<el-table-column prop="timestamp" :label="TEXT.modules.adminAuditLogs.columns.time" align="center" show-overflow-tooltip>
<template #default="scope">
<span class="text-gray-500">{{ displayDateTime(scope.row.timestamp) }}</span>
</template>
</el-table-column>
<el-table-column prop="actorName" :label="TEXT.modules.adminAuditLogs.columns.actor" width="140" />
<el-table-column prop="eventLabel" :label="TEXT.modules.adminAuditLogs.columns.event" width="160">
<el-table-column prop="actorName" :label="TEXT.modules.adminAuditLogs.columns.actor" show-overflow-tooltip />
<el-table-column prop="eventLabel" :label="TEXT.modules.adminAuditLogs.columns.event" show-overflow-tooltip>
<template #default="scope">
<el-tag effect="plain">{{ scope.row.eventLabel }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="actionText" :label="TEXT.modules.adminAuditLogs.columns.action" min-width="180" />
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.target" min-width="180">
<el-table-column prop="actionText" :label="TEXT.modules.adminAuditLogs.columns.action" show-overflow-tooltip />
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.target" show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.targetTypeLabel">
<strong>{{ scope.row.targetTypeLabel }}</strong>
@@ -82,7 +82,7 @@
<span v-else>{{ TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.diff" min-width="260">
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.diff" show-overflow-tooltip>
<template #default="scope">
<div v-if="scope.row.diffText?.length" class="diff-container">
<div v-for="(line, idx) in getDiffPreview(scope.row)" :key="idx" class="diff-line">{{ line }}</div>
@@ -94,7 +94,7 @@
<span v-else class="text-gray-400">{{ TEXT.audit.emptyValue }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.result" width="100" align="center">
<el-table-column :label="TEXT.modules.adminAuditLogs.columns.result" width="110" align="center">
<template #default="scope">
<el-tag :type="scope.row.result === 'SUCCESS' ? 'success' : 'danger'" effect="dark" size="small">
{{ scope.row.resultLabel }}
+36 -27
View File
@@ -8,51 +8,53 @@
</el-button>
</div>
<div class="unified-section project-table-section">
<el-table :data="projects" v-loading="loading" stripe class="project-table">
<el-table-column prop="name" :label="TEXT.common.fields.projectName" min-width="300">
<el-table :data="projects" v-loading="loading" stripe class="project-table" table-layout="fixed">
<el-table-column prop="name" :label="TEXT.common.fields.projectName" show-overflow-tooltip>
<template #default="scope">
<el-link type="primary" @click="goDetail(scope.row)" class="font-medium">{{ scope.row.name }}</el-link>
</template>
</el-table-column>
<el-table-column prop="code" :label="TEXT.common.fields.projectCode" min-width="160">
<el-table-column prop="code" :label="TEXT.common.fields.projectCode" show-overflow-tooltip>
<template #default="scope">
<span class="text-gray-500">{{ scope.row.code || "-" }}</span>
</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" min-width="120" align="center">
<el-table-column prop="status" :label="TEXT.common.fields.status" align="center">
<template #default="scope">
<el-tag :type="statusTag(scope.row.status)" effect="plain" round>{{ statusLabel(scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="is_locked" label="锁定状态" min-width="100" align="center">
<el-table-column prop="is_locked" label="锁定状态" align="center">
<template #default="scope">
<el-tag v-if="scope.row.is_locked" type="warning" effect="plain" round>已锁定</el-tag>
<el-tag v-else type="success" effect="plain" round>未锁定</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" min-width="280" align="center">
<el-table-column :label="TEXT.common.labels.actions" width="240" align="center">
<template #default="scope">
<el-tooltip :content="TEXT.modules.adminProjects.members" placement="top">
<el-button link type="primary" :icon="User" class="action-btn" @click="goMembers(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminProjects.sites" placement="top">
<el-button link type="primary" :icon="OfficeBuilding" class="action-btn" @click="goSites(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminProjects.enter" placement="top">
<el-button link type="success" :icon="ArrowRight" class="action-btn enter-btn" @click="enterStudy(scope.row)" />
</el-tooltip>
<el-tooltip v-if="!scope.row.is_locked" content="锁定项目" placement="top">
<el-button
link
type="info"
:icon="Lock"
class="action-btn"
@click="handleLockToggle(scope.row)"
/>
</el-tooltip>
<el-tooltip :content="TEXT.common.actions.delete" placement="top">
<el-button link type="danger" :icon="Delete" class="action-btn" @click="handleDelete(scope.row)" />
</el-tooltip>
<div class="action-row">
<el-tooltip :content="TEXT.modules.adminProjects.members" placement="top">
<el-button link type="primary" :icon="User" class="action-btn" @click="goMembers(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminProjects.sites" placement="top">
<el-button link type="primary" :icon="OfficeBuilding" class="action-btn" @click="goSites(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminProjects.enter" placement="top">
<el-button link type="success" :icon="ArrowRight" class="action-btn enter-btn" @click="enterStudy(scope.row)" />
</el-tooltip>
<el-tooltip v-if="!scope.row.is_locked" content="锁定项目" placement="top">
<el-button
link
type="info"
:icon="Lock"
class="action-btn"
@click="handleLockToggle(scope.row)"
/>
</el-tooltip>
<el-tooltip :content="TEXT.common.actions.delete" placement="top">
<el-button link type="danger" :icon="Delete" class="action-btn" @click="handleDelete(scope.row)" />
</el-tooltip>
</div>
</template>
</el-table-column>
</el-table>
@@ -239,6 +241,13 @@ onMounted(() => {
padding: 0;
}
.action-row {
display: inline-flex;
align-items: center;
gap: 10px;
white-space: nowrap;
}
.actions-only-bar {
display: flex;
justify-content: flex-end;
+40 -31
View File
@@ -28,46 +28,48 @@
</div>
<div class="unified-section user-table-section">
<el-table :data="users" stripe v-loading="loading" class="user-table" style="width: 100%">
<el-table-column prop="email" :label="TEXT.common.fields.email" min-width="200" />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" min-width="140" />
<el-table-column prop="department" :label="TEXT.common.fields.department" min-width="140" />
<el-table-column :label="TEXT.common.fields.status" width="140">
<el-table :data="users" stripe v-loading="loading" class="user-table" style="width: 100%" table-layout="fixed">
<el-table-column prop="email" :label="TEXT.common.fields.email" show-overflow-tooltip />
<el-table-column prop="full_name" :label="TEXT.common.fields.name" show-overflow-tooltip />
<el-table-column prop="department" :label="TEXT.common.fields.department" show-overflow-tooltip />
<el-table-column :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="statusType(scope.row.status)">
{{ statusLabel(scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="created_at" :label="TEXT.modules.adminUsers.createdAt" width="200">
<el-table-column prop="created_at" :label="TEXT.modules.adminUsers.createdAt" show-overflow-tooltip>
<template #default="scope">{{ displayDateTime(scope.row.created_at) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" min-width="200" align="center">
<el-table-column :label="TEXT.common.labels.actions" width="220" align="center">
<template #default="scope">
<el-tooltip :content="TEXT.common.actions.edit" placement="top">
<el-button link type="primary" :icon="Edit" @click="openEdit(scope.row)" />
</el-tooltip>
<el-tooltip :content="scope.row.status === 'ACTIVE' ? TEXT.common.actions.disable : TEXT.common.actions.enable" placement="top">
<el-button
link
:type="scope.row.status === 'ACTIVE' ? 'warning' : 'success'"
:icon="scope.row.status === 'ACTIVE' ? Lock : Unlock"
:disabled="isLastAdmin(scope.row)"
@click="toggleStatus(scope.row)"
/>
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminUsers.resetPassword" placement="top">
<el-button link type="warning" :icon="Key" @click="openReset(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.common.actions.delete" placement="top">
<el-button
link
type="danger"
:icon="Delete"
:disabled="scope.row.id === auth.user?.id"
@click="onDelete(scope.row)"
/>
</el-tooltip>
<div class="action-row">
<el-tooltip :content="TEXT.common.actions.edit" placement="top">
<el-button link type="primary" :icon="Edit" @click="openEdit(scope.row)" />
</el-tooltip>
<el-tooltip :content="scope.row.status === 'ACTIVE' ? TEXT.common.actions.disable : TEXT.common.actions.enable" placement="top">
<el-button
link
:type="scope.row.status === 'ACTIVE' ? 'warning' : 'success'"
:icon="scope.row.status === 'ACTIVE' ? Lock : Unlock"
:disabled="isLastAdmin(scope.row)"
@click="toggleStatus(scope.row)"
/>
</el-tooltip>
<el-tooltip :content="TEXT.modules.adminUsers.resetPassword" placement="top">
<el-button link type="warning" :icon="Key" @click="openReset(scope.row)" />
</el-tooltip>
<el-tooltip :content="TEXT.common.actions.delete" placement="top">
<el-button
link
type="danger"
:icon="Delete"
:disabled="scope.row.id === auth.user?.id"
@click="onDelete(scope.row)"
/>
</el-tooltip>
</div>
</template>
</el-table-column>
</el-table>
@@ -327,6 +329,13 @@ onMounted(() => {
flex: 1;
}
.action-row {
display: inline-flex;
align-items: center;
gap: 10px;
white-space: nowrap;
}
.user-table-section {
padding: 0;
}
+12 -12
View File
@@ -50,34 +50,34 @@
</div>
</div>
<div class="ctms-table-panel">
<el-table :data="detail.version_timeline" v-loading="versionLoading" class="ctms-table">
<el-table-column prop="version_no" :label="TEXT.modules.fileVersionManagement.fields.versionNo" width="120">
<el-table :data="detail.version_timeline" v-loading="versionLoading" class="ctms-table" table-layout="fixed">
<el-table-column prop="version_no" :label="TEXT.modules.fileVersionManagement.fields.versionNo" show-overflow-tooltip>
<template #default="{ row }">
<span class="font-medium">V{{ row.version_no }}</span>
</template>
</el-table-column>
<el-table-column label="版本日期" width="140">
<el-table-column label="版本日期" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-secondary">{{ formatDateOnly(row.effective_at || row.created_at) }}</span>
</template>
</el-table-column>
<el-table-column prop="change_summary" :label="TEXT.modules.fileVersionManagement.fields.changeSummary" min-width="200" show-overflow-tooltip />
<el-table-column :label="TEXT.modules.fileVersionManagement.labels.createdBy" width="160">
<el-table-column prop="change_summary" :label="TEXT.modules.fileVersionManagement.fields.changeSummary" show-overflow-tooltip />
<el-table-column :label="TEXT.modules.fileVersionManagement.labels.createdBy" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ displayCreator(row.created_by) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.parentVersion" width="140">
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.parentVersion" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-secondary">{{ displayParentVersion(row.parent_version_id) }}</span>
</template>
</el-table-column>
<el-table-column prop="effective_at" :label="TEXT.modules.fileVersionManagement.columns.effectiveAt" width="180">
<el-table-column prop="effective_at" :label="TEXT.modules.fileVersionManagement.columns.effectiveAt" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-secondary">{{ formatDate(row.effective_at || row.created_at) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.actions" width="180" align="center">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.actions" width="140" align="center">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="downloadVersion(row)" v-if="canAction('view')">
{{ TEXT.modules.fileVersionManagement.actions.download }}
@@ -108,18 +108,18 @@
</div>
</div>
<div class="ctms-table-panel">
<el-table :data="distributions" v-loading="distributionLoading" class="ctms-table">
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.targetType" width="120">
<el-table :data="distributions" v-loading="distributionLoading" class="ctms-table" table-layout="fixed">
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.targetType">
<template #default="{ row }">
<el-tag effect="plain" type="info">{{ displayEnum(TEXT.enums.distributionTargetType, row.target_type) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.target" min-width="200">
<el-table-column :label="TEXT.modules.fileVersionManagement.fields.target" show-overflow-tooltip>
<template #default="{ row }">
<span class="font-medium">{{ displayTarget(row) }}</span>
</template>
</el-table-column>
<el-table-column label="抄送时间" width="180">
<el-table-column label="抄送时间" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-secondary">{{ formatDate(row.created_at) }}</span>
</template>
@@ -35,13 +35,14 @@
@row-click="handleRowClick"
:row-class-name="documentRowClass"
class="ctms-table"
table-layout="fixed"
>
<el-table-column prop="title" :label="TEXT.modules.fileVersionManagement.columns.title" min-width="200">
<el-table-column prop="title" :label="TEXT.modules.fileVersionManagement.columns.title" show-overflow-tooltip>
<template #default="{ row }">
<span class="font-semibold">{{ row.title }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.scope" width="120">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.scope">
<template #default="{ row }">
<el-tag
effect="plain"
@@ -51,28 +52,28 @@
</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.site" min-width="160">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.site" show-overflow-tooltip>
<template #default="{ row }">
<span>{{ displaySite(row.site_id) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.docType" width="140">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.docType">
<template #default="{ row }">
<el-tag effect="plain" type="info">{{ displayText(row.doc_type, TEXT.enums.documentType) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.currentVersion" width="140">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.currentVersion">
<template #default="{ row }">
<span v-if="row.current_effective_version">{{ row.current_effective_version.version_no }}</span>
<span v-else class="text-secondary">-</span>
</template>
</el-table-column>
<el-table-column prop="updated_at" :label="TEXT.modules.fileVersionManagement.columns.updatedAt" width="180">
<el-table-column prop="updated_at" :label="TEXT.modules.fileVersionManagement.columns.updatedAt" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-secondary">{{ formatDate(row.updated_at) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.actions" width="100" align="center">
<el-table-column :label="TEXT.modules.fileVersionManagement.columns.actions" width="120" align="center">
<template #default="{ row }">
<el-button v-if="isAdmin" link type="danger" :disabled="isInactiveSite(row.site_id)" @click.stop="confirmDelete(row)">
{{ TEXT.common.actions.delete }}
@@ -52,18 +52,18 @@
<span class="header-title">{{ TEXT.modules.feeContracts.paymentTitle }}</span>
</div>
</template>
<el-table :data="detail.payments" style="width: 100%" :header-cell-style="{ background: '#f8f9fb' }">
<el-table-column :label="TEXT.modules.feeContracts.paymentSeq" width="120">
<el-table :data="detail.payments" style="width: 100%" :header-cell-style="{ background: '#f8f9fb' }" table-layout="fixed">
<el-table-column :label="TEXT.modules.feeContracts.paymentSeq">
<template #default="scope">
<span class="seq-tag">{{ TEXT.modules.feeContracts.paymentSeq }}{{ scope.row.seq }}{{ TEXT.modules.feeContracts.paymentSeqUnit }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.amount" width="160" align="right">
<el-table-column :label="TEXT.common.fields.amount" align="right">
<template #default="scope">
<span class="amount-text">{{ formatAmountWan(scope.row.amount) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.paidFlag" width="200">
<el-table-column :label="TEXT.modules.feeContracts.paidFlag">
<template #default="scope">
<div v-if="scope.row.is_paid" class="status-cell">
<el-tag type="success" size="small">{{ TEXT.modules.feeContracts.isPaid }}</el-tag>
@@ -72,7 +72,7 @@
<span v-else class="text-muted">{{ TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.verifiedFlag" width="200">
<el-table-column :label="TEXT.modules.feeContracts.verifiedFlag">
<template #default="scope">
<div v-if="scope.row.is_verified" class="status-cell">
<el-tag type="info" size="small">{{ TEXT.modules.feeContracts.isVerified }}</el-tag>
@@ -81,7 +81,7 @@
<span v-else class="text-muted">{{ TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.remark" min-width="200" show-overflow-tooltip>
<el-table-column :label="TEXT.common.fields.remark" show-overflow-tooltip>
<template #default="scope">{{ scope.row.remark || TEXT.common.fallback }}</template>
</el-table-column>
<template #empty>
+14 -13
View File
@@ -56,7 +56,7 @@
<div class="main-content-flat unified-shell" v-else>
<div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item class="filter-item">
<div class="filter-item">
<el-select v-model="filters.centerId" clearable :placeholder="TEXT.common.fields.site" class="filter-select">
<template #prefix>
<el-icon><Location /></el-icon>
@@ -68,17 +68,17 @@
:value="site.id"
/>
</el-select>
</el-form-item>
<el-form-item class="filter-item">
</div>
<div class="filter-item">
<el-input v-model="filters.q" :placeholder="TEXT.common.placeholders.keyword" clearable class="filter-input">
<template #prefix>
<el-icon><Search /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item class="filter-actions">
</div>
<div class="filter-actions">
<el-button @click="resetFilters">{{ TEXT.common.actions.reset }}</el-button>
</el-form-item>
</div>
<div class="filter-spacer"></div>
<el-button type="primary" :disabled="!canWrite" @click="goNew" class="header-action-btn">
<el-icon class="el-icon--left"><Plus /></el-icon>
@@ -93,27 +93,28 @@
@row-click="onRowClick"
:row-class-name="contractRowClass"
class="contract-table"
table-layout="fixed"
>
<el-table-column prop="center_name" :label="TEXT.common.fields.site" min-width="160">
<el-table-column prop="center_name" :label="TEXT.common.fields.site" width="170" show-overflow-tooltip>
<template #default="scope">
<div class="site-cell">
<span class="site-name">{{ scope.row.center_name || TEXT.common.fallback }}</span>
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.contractAmount" width="140" align="right">
<el-table-column :label="TEXT.modules.feeContracts.contractAmount" width="150" align="right">
<template #default="scope">
<span class="amount-text">{{ formatAmountWan(scope.row.contract_amount) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.caseProgress" min-width="140" align="center">
<el-table-column :label="TEXT.modules.feeContracts.caseProgress" width="170" align="center">
<template #default="scope">
<el-tag effect="plain" type="info">
{{ displayCases(scope.row.contract_cases, scope.row.actual_cases) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.paidSummary" min-width="200">
<el-table-column :label="TEXT.modules.feeContracts.paidSummary" width="190">
<template #default="scope">
<div class="summary-line">
<span>{{ TEXT.modules.feeContracts.paidTotal }}</span>
@@ -126,7 +127,7 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.verifySummary" min-width="200">
<el-table-column :label="TEXT.modules.feeContracts.verifySummary" width="190">
<template #default="scope">
<div class="summary-line">
<span>{{ TEXT.modules.feeContracts.verifiedTotal }}</span>
@@ -139,7 +140,7 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeContracts.recentDates" min-width="180">
<el-table-column :label="TEXT.modules.feeContracts.recentDates" width="170">
<template #default="scope">
<div class="date-line">
<span class="date-label">{{ TEXT.modules.feeContracts.lastPaid }}</span>
@@ -151,7 +152,7 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="100">
<el-table-column :label="TEXT.common.labels.actions" width="110">
<template #default="scope">
<el-button
link
+16 -15
View File
@@ -55,7 +55,7 @@
<div class="main-content-flat unified-shell" v-else>
<div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item class="filter-item">
<div class="filter-item">
<el-select v-model="filters.centerId" clearable :placeholder="TEXT.common.fields.site" class="filter-select">
<template #prefix>
<el-icon><Location /></el-icon>
@@ -67,16 +67,16 @@
:value="site.id"
/>
</el-select>
</el-form-item>
<el-form-item class="filter-item">
</div>
<div class="filter-item">
<el-select v-model="filters.category" clearable :placeholder="TEXT.common.fields.category" class="filter-select">
<template #prefix>
<el-icon><Menu /></el-icon>
</template>
<el-option v-for="option in categoryOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
<el-form-item class="filter-item">
</div>
<div class="filter-item">
<el-date-picker
v-model="filters.dateRange"
type="daterange"
@@ -86,10 +86,10 @@
:end-placeholder="TEXT.common.placeholders.endDate"
class="filter-date"
/>
</el-form-item>
<el-form-item class="filter-actions">
</div>
<div class="filter-actions">
<el-button @click="resetFilters">{{ TEXT.common.actions.reset }}</el-button>
</el-form-item>
</div>
<div class="filter-spacer"></div>
<el-button type="primary" :disabled="!canWrite" @click="goNew" class="header-action-btn">
<el-icon class="el-icon--left"><Plus /></el-icon>
@@ -104,35 +104,36 @@
@row-click="onRowClick"
:row-class-name="expenseRowClass"
class="special-expense-table"
table-layout="fixed"
>
<el-table-column :label="TEXT.common.fields.occurDate" width="140">
<el-table-column :label="TEXT.common.fields.occurDate">
<template #default="scope">
<span class="date-text">{{ displayDate(scope.row.happen_date) }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.site" min-width="160">
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">
<span class="site-text">{{ scope.row.center_name || TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.category" width="140">
<el-table-column :label="TEXT.common.fields.category">
<template #default="scope">
<el-tag size="small" :type="getCategoryType(scope.row.category)" effect="light" class="category-tag">
{{ displayEnum(TEXT.enums.feeSpecialCategory, scope.row.category) }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.amount" width="110" align="right">
<el-table-column :label="TEXT.common.fields.amount" align="right">
<template #default="scope">
<span class="amount-text">{{ formatAmount(scope.row.amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="description" :label="TEXT.common.fields.remark" min-width="200" show-overflow-tooltip>
<el-table-column prop="description" :label="TEXT.common.fields.remark" show-overflow-tooltip>
<template #default="scope">
{{ scope.row.description || TEXT.common.fallback }}
</template>
</el-table-column>
<el-table-column width="140" align="center" :label="TEXT.common.fields.status">
<el-table-column width="120" align="center" :label="TEXT.common.fields.status">
<template #default="scope">
<el-tooltip :content="scope.row.is_paid ? `${TEXT.modules.feeSpecials.isPaid} (${displayDate(scope.row.paid_date)})` : TEXT.modules.feeSpecials.unpaid" placement="top">
<el-icon :class="scope.row.is_paid ? 'status-icon success' : 'status-icon muted'"><Wallet /></el-icon>
@@ -142,7 +143,7 @@
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.feeSpecials.attachmentCount" width="120" align="center">
<el-table-column :label="TEXT.modules.feeSpecials.attachmentCount" align="center">
<template #default="scope">
<el-tag v-if="scope.row.attachments_count > 0" effect="plain" type="info" round size="small">
{{ scope.row.attachments_count }}
+17 -16
View File
@@ -4,7 +4,7 @@
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item class="filter-item">
<div class="filter-item">
<el-select v-model="filters.center_id" clearable :placeholder="TEXT.common.fields.site" class="filter-select">
<template #prefix>
<el-icon><Location /></el-icon>
@@ -16,8 +16,8 @@
:value="site.id"
/>
</el-select>
</el-form-item>
<el-form-item class="filter-item">
</div>
<div class="filter-item">
<el-select v-model="filters.direction" clearable :placeholder="TEXT.common.fields.direction" class="filter-select">
<template #prefix>
<el-icon><Menu /></el-icon>
@@ -25,8 +25,8 @@
<el-option :label="TEXT.enums.shipmentDirection.SEND" value="SEND" />
<el-option :label="TEXT.enums.shipmentDirection.RETURN" value="RETURN" />
</el-select>
</el-form-item>
<el-form-item class="filter-item">
</div>
<div class="filter-item">
<el-select v-model="filters.status" clearable :placeholder="TEXT.common.fields.status" class="filter-select">
<template #prefix>
<el-icon><CircleCheck /></el-icon>
@@ -37,10 +37,10 @@
<el-option :label="TEXT.enums.shipmentStatus.RETURNED" value="RETURNED" />
<el-option :label="TEXT.enums.shipmentStatus.EXCEPTION" value="EXCEPTION" />
</el-select>
</el-form-item>
<el-form-item class="filter-actions">
</div>
<div class="filter-actions">
<el-button @click="resetFilters">{{ TEXT.common.actions.reset }}</el-button>
</el-form-item>
</div>
<div class="filter-spacer"></div>
<el-button type="primary" @click="goNew">
<el-icon class="el-icon--left"><Plus /></el-icon>
@@ -56,8 +56,9 @@
class="shipment-table"
:row-class-name="shipmentRowClass"
@row-click="onRowClick"
table-layout="fixed"
>
<el-table-column prop="site_name" :label="TEXT.common.fields.site" min-width="160">
<el-table-column prop="site_name" :label="TEXT.common.fields.site" width="150" show-overflow-tooltip>
<template #default="scope">{{ scope.row.site_name || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="direction" :label="TEXT.common.fields.direction" width="120">
@@ -67,29 +68,29 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="ship_date" :label="TEXT.common.fields.shipDate" width="140">
<el-table-column prop="ship_date" :label="TEXT.common.fields.shipDate" width="165">
<template #default="scope">{{ displayDate(scope.row.ship_date) }}</template>
</el-table-column>
<el-table-column prop="receive_date" :label="TEXT.common.fields.receiveDate" width="140">
<el-table-column prop="receive_date" :label="TEXT.common.fields.receiveDate" width="145">
<template #default="scope">{{ displayDate(scope.row.receive_date) }}</template>
</el-table-column>
<el-table-column prop="quantity" :label="TEXT.common.fields.quantity" width="120" align="right">
<el-table-column prop="quantity" :label="TEXT.common.fields.quantity" width="100" align="right">
<template #default="scope">{{ typeof scope.row.quantity === "number" ? scope.row.quantity : TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="batch_no" :label="TEXT.common.fields.batchNo" min-width="140">
<el-table-column prop="batch_no" :label="TEXT.common.fields.batchNo" width="120" show-overflow-tooltip>
<template #default="scope">{{ scope.row.batch_no || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" width="140">
<el-table-column prop="status" :label="TEXT.common.fields.status" width="120">
<template #default="scope">
<el-tag :type="statusType(scope.row.status)" effect="plain" round size="small" class="status-tag">
{{ displayEnum(TEXT.enums.shipmentStatus, scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="remark" :label="TEXT.common.fields.remark" min-width="160" show-overflow-tooltip>
<el-table-column prop="remark" :label="TEXT.common.fields.remark" width="160" show-overflow-tooltip>
<template #default="scope">{{ scope.row.remark || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="120" align="center">
<el-table-column :label="TEXT.common.labels.actions" width="110" align="center">
<template #default="scope">
<el-button
link
+6 -5
View File
@@ -36,20 +36,21 @@
class="ctms-table"
@row-click="onRowClick"
:row-class-name="contractRowClass"
table-layout="fixed"
>
<el-table-column prop="site_name" :label="TEXT.common.fields.site" min-width="160" />
<el-table-column prop="contract_no" :label="TEXT.common.fields.contractNo" min-width="160" />
<el-table-column prop="signed_date" :label="TEXT.common.fields.signedDate" width="140">
<el-table-column prop="site_name" :label="TEXT.common.fields.site" show-overflow-tooltip />
<el-table-column prop="contract_no" :label="TEXT.common.fields.contractNo" show-overflow-tooltip />
<el-table-column prop="signed_date" :label="TEXT.common.fields.signedDate">
<template #default="scope">
{{ displayDate(scope.row.signed_date) }}
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.amount" width="160">
<el-table-column :label="TEXT.common.fields.amount">
<template #default="scope">
{{ scope.row.amount }} {{ scope.row.currency || TEXT.common.fields.currencyDefault }}
</template>
</el-table-column>
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" width="180">
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" show-overflow-tooltip>
<template #default="scope">
{{ displayDateTime(scope.row.updated_at) }}
</template>
+7 -6
View File
@@ -41,25 +41,26 @@
class="ctms-table"
@row-click="onRowClick"
:row-class-name="specialRowClass"
table-layout="fixed"
>
<el-table-column prop="site_name" :label="TEXT.common.fields.site" min-width="160" />
<el-table-column prop="fee_type" :label="TEXT.common.fields.type" width="120">
<el-table-column prop="site_name" :label="TEXT.common.fields.site" show-overflow-tooltip />
<el-table-column prop="fee_type" :label="TEXT.common.fields.type">
<template #default="scope">
{{ displayEnum(TEXT.enums.financeSpecialType, scope.row.fee_type) }}
</template>
</el-table-column>
<el-table-column prop="occur_date" :label="TEXT.common.fields.occurDate" width="140">
<el-table-column prop="occur_date" :label="TEXT.common.fields.occurDate">
<template #default="scope">
{{ displayDate(scope.row.occur_date) }}
</template>
</el-table-column>
<el-table-column prop="staff_name" :label="TEXT.common.fields.staff" min-width="120" />
<el-table-column :label="TEXT.common.fields.amount" width="140">
<el-table-column prop="staff_name" :label="TEXT.common.fields.staff" show-overflow-tooltip />
<el-table-column :label="TEXT.common.fields.amount">
<template #default="scope">
{{ scope.row.amount }}
</template>
</el-table-column>
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" width="180">
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" show-overflow-tooltip>
<template #default="scope">
{{ displayDateTime(scope.row.updated_at) }}
</template>
+11 -10
View File
@@ -4,25 +4,25 @@
<div class="main-content-flat unified-shell">
<div class="filter-container unified-action-bar bar--flush">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item class="filter-item-form">
<div class="filter-item-form">
<el-input
v-model="filters.site_name"
:placeholder="TEXT.common.fields.site"
clearable
class="filter-input-comp"
/>
</el-form-item>
<el-form-item class="filter-item-form">
</div>
<div class="filter-item-form">
<el-input
v-model="filters.keyword"
:placeholder="TEXT.common.fields.keyword"
clearable
class="filter-input-comp"
/>
</el-form-item>
<el-form-item class="filter-item-form">
</div>
<div class="filter-item-form">
<el-button @click="resetFilters">{{ TEXT.common.actions.reset }}</el-button>
</el-form-item>
</div>
<div class="filter-spacer"></div>
<el-button type="primary" @click="goNew">
{{ TEXT.modules.knowledgeNotes.newTitle }}
@@ -37,11 +37,12 @@
class="ctms-table"
@row-click="onRowClick"
:row-class-name="noteRowClass"
table-layout="fixed"
>
<el-table-column prop="site_name" :label="TEXT.common.fields.site" min-width="160" />
<el-table-column prop="title" :label="TEXT.common.fields.title" min-width="200" />
<el-table-column prop="level" :label="TEXT.common.fields.level" width="120" />
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" width="180">
<el-table-column prop="site_name" :label="TEXT.common.fields.site" show-overflow-tooltip />
<el-table-column prop="title" :label="TEXT.common.fields.title" show-overflow-tooltip />
<el-table-column prop="level" :label="TEXT.common.fields.level" />
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" show-overflow-tooltip>
<template #default="scope">{{ displayDateTime(scope.row.updated_at) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="120">
+5 -5
View File
@@ -16,16 +16,16 @@
</div>
<el-table v-loading="loading" :data="rows" class="ctms-table equipment-table" style="width: 100%" table-layout="fixed">
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="specModel" label="规格型号" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="brand" label="品牌" />
<el-table-column prop="name" label="设备名称" show-overflow-tooltip />
<el-table-column prop="specModel" label="规格型号" show-overflow-tooltip />
<el-table-column prop="unit" label="单位" show-overflow-tooltip />
<el-table-column prop="brand" label="品牌" show-overflow-tooltip />
<el-table-column label="是否需要校准">
<template #default="{ row }">
{{ row.needCalibration ? "是" : "否" }}
</template>
</el-table-column>
<el-table-column label="操作">
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button link type="primary" @click="openEdit(row)">编辑</el-button>
<el-button link type="danger" @click="removeRow(row)">删除</el-button>
+8 -8
View File
@@ -23,9 +23,9 @@
</div>
</section>
<section class="unified-section ctms-page-content-grid section--flush-x section--flush-top section--flush-bottom">
<el-table :data="rows" v-loading="loading" class="ctms-table" style="width: 100%">
<el-table-column prop="name" :label="TEXT.modules.projectMilestones.columns.name" min-width="140" />
<el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate" min-width="170">
<el-table :data="rows" v-loading="loading" class="ctms-table" style="width: 100%" table-layout="fixed">
<el-table-column prop="name" :label="TEXT.modules.projectMilestones.columns.name" show-overflow-tooltip />
<el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate">
<template #default="scope">
<div class="plan-time-cell">
<div class="plan-time-line">
@@ -46,7 +46,7 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.projectMilestones.columns.adjustedPlanDate" min-width="170">
<el-table-column :label="TEXT.modules.projectMilestones.columns.adjustedPlanDate">
<template #default="scope">
<div class="plan-time-cell">
<div class="plan-time-line">
@@ -67,7 +67,7 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.modules.projectMilestones.columns.actualTime" min-width="170">
<el-table-column :label="TEXT.modules.projectMilestones.columns.actualTime">
<template #default="scope">
<div class="plan-time-cell">
<div class="plan-time-line">
@@ -88,7 +88,7 @@
</div>
</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.modules.projectMilestones.columns.status" min-width="120">
<el-table-column prop="status" :label="TEXT.modules.projectMilestones.columns.status">
<template #default="scope">
<div class="status-cell" :class="`status-${getStatusView(scope.row).tone}`">
<div class="status-main">
@@ -99,10 +99,10 @@
</div>
</template>
</el-table-column>
<el-table-column prop="remark" :label="TEXT.modules.projectMilestones.columns.remark" min-width="100">
<el-table-column prop="remark" :label="TEXT.modules.projectMilestones.columns.remark" show-overflow-tooltip>
<template #default="scope">{{ scope.row.remark || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column :label="TEXT.modules.projectMilestones.columns.operations" width="84">
<el-table-column :label="TEXT.modules.projectMilestones.columns.operations" width="100">
<template #default="scope">
<el-button link type="primary" @click="openEditor(scope.row)">{{ TEXT.common.actions.edit }}</el-button>
</template>
@@ -57,31 +57,32 @@
style="width: 100%"
v-loading="loading"
:fit="true"
table-layout="fixed"
:span-method="tableSpanMethod"
:row-class-name="tableRowClassName"
>
<el-table-column label="问题编号" min-width="130">
<el-table-column label="问题编号" show-overflow-tooltip>
<template #default="{ row }">
<div v-if="isDescRow(row)" class="issue-desc">问题描述{{ row.description || TEXT.common.fallback }}</div>
<div v-else class="issue-no">{{ row.issue_no }}</div>
</template>
</el-table-column>
<el-table-column prop="open_duration" label="开放时长" min-width="130">
<el-table-column prop="open_duration" label="开放时长" show-overflow-tooltip>
<template #default="{ row }">{{ isDescRow(row) ? "" : row.open_duration }}</template>
</el-table-column>
<el-table-column prop="category" label="问题分类" min-width="130">
<el-table-column prop="category" label="问题分类" show-overflow-tooltip>
<template #default="{ row }">{{ isDescRow(row) ? "" : row.category }}</template>
</el-table-column>
<el-table-column prop="subject_code" label="受试者" min-width="120">
<el-table-column prop="subject_code" label="受试者" show-overflow-tooltip>
<template #default="{ row }">{{ isDescRow(row) ? "" : row.subject_code || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="monitor_item" label="监查项" min-width="130" show-overflow-tooltip>
<el-table-column prop="monitor_item" label="监查项" show-overflow-tooltip>
<template #default="{ row }">{{ isDescRow(row) ? "" : row.monitor_item || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="monitor_type" label="监查类型" min-width="130">
<el-table-column prop="monitor_type" label="监查类型" show-overflow-tooltip>
<template #default="{ row }">{{ isDescRow(row) ? "" : row.monitor_type || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column label="进度" min-width="120">
<el-table-column label="进度">
<template #default="{ row }">
<div v-if="!isDescRow(row)" class="progress-cell">
<span class="progress-dot" :class="`dot-${String(row.status).toLowerCase()}`"></span>
@@ -89,7 +90,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="操作" min-width="150" align="center">
<el-table-column label="操作" width="140" align="center">
<template #default="{ row }">
<template v-if="!isDescRow(row)">
<div class="action-cell">
+6 -6
View File
@@ -35,16 +35,16 @@
</div>
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" table-layout="fixed" class="risk-table">
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" min-width="160" show-overflow-tooltip />
<el-table-column prop="subject_no" :label="TEXT.modules.subjectManagement.screeningNo" min-width="160" show-overflow-tooltip />
<el-table-column :label="TEXT.common.fields.site" min-width="160" show-overflow-tooltip>
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" show-overflow-tooltip />
<el-table-column prop="subject_no" :label="TEXT.modules.subjectManagement.screeningNo" show-overflow-tooltip />
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">{{ siteMap[scope.row.site_id] || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" min-width="160">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">{{ displayEnum(TEXT.enums.pdStatus, scope.row.status) }}</template>
</el-table-column>
<el-table-column prop="description" :label="TEXT.common.fields.pdDescription" min-width="160" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.actions" min-width="160" align="center">
<el-table-column prop="description" :label="TEXT.common.fields.pdDescription" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.actions" width="120" align="center">
<template #default="scope">
<el-button link type="primary" size="small" @click="goSubject(scope.row.subject_id)">
{{ TEXT.common.actions.view }}
+8 -8
View File
@@ -52,24 +52,24 @@
</el-form>
</div>
<div class="unified-section table-section section--flush-x section--flush-top section--flush-bottom">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" class="risk-table">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140">
<el-table :data="filteredItems" v-loading="loading" style="width: 100%" class="risk-table" table-layout="fixed">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate">
<template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
</el-table-column>
<el-table-column prop="subject_no" :label="TEXT.modules.riskIssueSae.subjectNo" min-width="140">
<el-table-column prop="subject_no" :label="TEXT.modules.riskIssueSae.subjectNo" show-overflow-tooltip>
<template #default="scope">{{ subjectMap[scope.row.subject_id] || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.site" min-width="140">
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">{{ siteMap[scope.row.site_id] || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="term" :label="TEXT.common.fields.title" min-width="180" />
<el-table-column prop="seriousness" :label="TEXT.common.fields.seriousness" width="120">
<el-table-column prop="term" :label="TEXT.common.fields.title" show-overflow-tooltip />
<el-table-column prop="seriousness" :label="TEXT.common.fields.seriousness">
<template #default="scope">{{ displayEnum(TEXT.enums.aeSeriousness, scope.row.seriousness) }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" width="120">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">{{ displayEnum(TEXT.enums.aeStatus, scope.row.status) }}</template>
</el-table-column>
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" min-width="180">
<el-table-column prop="updated_at" :label="TEXT.common.labels.updatedAt" show-overflow-tooltip>
<template #default="scope">{{ displayDate(scope.row.updated_at) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="120">
@@ -19,29 +19,30 @@
class="ctms-table"
:row-class-name="feasibilityRowClass"
@row-click="onFeasibilityRowClick"
table-layout="fixed"
>
<el-table-column :label="TEXT.common.fields.site" width="180">
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">
<span class="font-medium">{{ displaySite(scope.row.site_id) }}</span>
</template>
</el-table-column>
<el-table-column prop="submit_date" :label="TEXT.common.fields.submitDate" width="140">
<el-table-column prop="submit_date" :label="TEXT.common.fields.submitDate">
<template #default="scope">{{ displayDate(scope.row.submit_date) }}</template>
</el-table-column>
<el-table-column prop="accept_date" :label="TEXT.common.fields.acceptDate" width="140">
<el-table-column prop="accept_date" :label="TEXT.common.fields.acceptDate">
<template #default="scope">{{ displayDate(scope.row.accept_date) }}</template>
</el-table-column>
<el-table-column prop="approved_date" :label="TEXT.common.fields.approvedDate" width="140">
<el-table-column prop="approved_date" :label="TEXT.common.fields.approvedDate">
<template #default="scope">{{ displayDate(scope.row.approved_date) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.status" width="120">
<el-table-column :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="statusTagType(getFeasibilityStatus(scope.row))">
{{ statusLabel(getFeasibilityStatus(scope.row)) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="project_no" :label="TEXT.common.fields.projectNo" min-width="160">
<el-table-column prop="project_no" :label="TEXT.common.fields.projectNo" show-overflow-tooltip>
<template #default="{ row }">
<span class="font-mono text-main">{{ row.project_no }}</span>
</template>
@@ -81,32 +82,33 @@
class="ctms-table"
:row-class-name="ethicsRowClass"
@row-click="onEthicsRowClick"
table-layout="fixed"
>
<el-table-column :label="TEXT.common.fields.site" width="180">
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">
<span class="font-medium">{{ displaySite(scope.row.site_id) }}</span>
</template>
</el-table-column>
<el-table-column prop="submit_date" :label="TEXT.common.fields.submitDate" width="140">
<el-table-column prop="submit_date" :label="TEXT.common.fields.submitDate">
<template #default="scope">{{ displayDate(scope.row.submit_date) }}</template>
</el-table-column>
<el-table-column prop="accept_date" :label="TEXT.common.fields.acceptDate" width="140">
<el-table-column prop="accept_date" :label="TEXT.common.fields.acceptDate">
<template #default="scope">{{ displayDate(scope.row.accept_date) }}</template>
</el-table-column>
<el-table-column prop="meeting_date" :label="TEXT.common.fields.meetingDate" width="140">
<el-table-column prop="meeting_date" :label="TEXT.common.fields.meetingDate">
<template #default="scope">{{ displayDate(scope.row.meeting_date) }}</template>
</el-table-column>
<el-table-column prop="approved_date" :label="TEXT.common.fields.approvedDate" width="140">
<el-table-column prop="approved_date" :label="TEXT.common.fields.approvedDate">
<template #default="scope">{{ displayDate(scope.row.approved_date) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.status" width="120">
<el-table-column :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="statusTagType(getEthicsStatus(scope.row))">
{{ statusLabel(getEthicsStatus(scope.row)) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="approval_no" :label="TEXT.common.fields.approvalNo" min-width="160">
<el-table-column prop="approval_no" :label="TEXT.common.fields.approvalNo" show-overflow-tooltip>
<template #default="{ row }">
<span class="font-mono text-main">{{ row.approval_no }}</span>
</template>
+5 -4
View File
@@ -9,15 +9,16 @@
class="ctms-table kickoff-table"
:row-class-name="kickoffRowClass"
@row-click="onKickoffRowClick"
table-layout="fixed"
>
<el-table-column prop="site_name" :label="TEXT.common.fields.site" min-width="180" />
<el-table-column prop="kickoff_date" :label="TEXT.common.fields.kickoffDate" width="160">
<el-table-column prop="site_name" :label="TEXT.common.fields.site" show-overflow-tooltip />
<el-table-column prop="kickoff_date" :label="TEXT.common.fields.kickoffDate">
<template #default="scope">{{ displayDate(scope.row.kickoff_date) }}</template>
</el-table-column>
<el-table-column :label="TEXT.modules.startupMeetingAuth.ownerLabel" min-width="160">
<el-table-column :label="TEXT.modules.startupMeetingAuth.ownerLabel" show-overflow-tooltip>
<template #default="scope">{{ contactLabel(scope.row) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.status" width="140">
<el-table-column :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag :type="scope.row.status === 'COMPLETED' ? 'success' : 'info'">
{{ scope.row.status === 'COMPLETED' ? TEXT.modules.startupMeetingAuth.statusCompleted : TEXT.modules.startupMeetingAuth.statusPending }}
+7 -6
View File
@@ -62,8 +62,9 @@
class="ctms-table"
:row-class-name="subjectRowClass"
@row-click="onRowClick"
table-layout="fixed"
>
<el-table-column prop="subject_no" :label="TEXT.modules.subjectManagement.screeningNo" min-width="160">
<el-table-column prop="subject_no" :label="TEXT.modules.subjectManagement.screeningNo" show-overflow-tooltip>
<template #default="scope">
<div class="subject-info-cell">
<span class="subject-no">{{ scope.row.subject_no || TEXT.common.fallback }}</span>
@@ -77,19 +78,19 @@
</div>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.site" min-width="160">
<el-table-column :label="TEXT.common.fields.site" show-overflow-tooltip>
<template #default="scope">{{ siteMap[scope.row.site_id] || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="consent_date" :label="TEXT.common.fields.consentDate" width="140">
<el-table-column prop="consent_date" :label="TEXT.common.fields.consentDate">
<template #default="scope">{{ displayDate(scope.row.consent_date) }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" width="120">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">{{ displayEnum(TEXT.enums.subjectStatus, scope.row.status) }}</template>
</el-table-column>
<el-table-column prop="enrollment_date" :label="TEXT.common.fields.enrollmentDate" width="140">
<el-table-column prop="enrollment_date" :label="TEXT.common.fields.enrollmentDate">
<template #default="scope">{{ displayDate(scope.row.enrollment_date) }}</template>
</el-table-column>
<el-table-column prop="completion_date" :label="TEXT.common.fields.completionDate" width="140">
<el-table-column prop="completion_date" :label="TEXT.common.fields.completionDate">
<template #default="scope">{{ displayDate(scope.row.completion_date) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="120">
+6 -6
View File
@@ -45,20 +45,20 @@
<div class="training-header">
<div class="training-title">{{ TEXT.modules.startupMeetingAuth.trainingTab }}</div>
</div>
<el-table :data="trainingRows" v-loading="loadingTraining" style="width: 100%" class="ctms-table">
<el-table-column prop="name" :label="TEXT.common.fields.name" min-width="140">
<el-table :data="trainingRows" v-loading="loadingTraining" style="width: 100%" class="ctms-table" table-layout="fixed">
<el-table-column prop="name" :label="TEXT.common.fields.name" show-overflow-tooltip>
<template #default="scope">
<el-input v-if="isTrainingEditing(scope.row)" v-model="trainingRowDraft.name" size="small" />
<span v-else>{{ scope.row.name || TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column prop="role" :label="TEXT.common.labels.role" min-width="120">
<el-table-column prop="role" :label="TEXT.common.labels.role" show-overflow-tooltip>
<template #default="scope">
<el-input v-if="isTrainingEditing(scope.row)" v-model="trainingRowDraft.role" size="small" />
<span v-else>{{ scope.row.role || TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.trained" width="120">
<el-table-column :label="TEXT.common.fields.trained">
<template #default="scope">
<el-checkbox
v-if="isTrainingEditing(scope.row)"
@@ -75,7 +75,7 @@
/>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.authorized" width="120">
<el-table-column :label="TEXT.common.fields.authorized">
<template #default="scope">
<el-checkbox
v-if="isTrainingEditing(scope.row)"
@@ -92,7 +92,7 @@
/>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="120">
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<template v-if="isTrainingEditing(scope.row)">
<el-button link type="primary" size="small" :loading="savingTraining" @click.stop="saveTraining(scope.row)">
+27 -27
View File
@@ -84,12 +84,12 @@
{{ TEXT.common.actions.newHistory }}
</el-button>
</div>
<el-table :data="historyItems" v-loading="loadingHistory" style="width: 100%" class="subject-detail-table">
<el-table-column prop="record_date" :label="TEXT.common.fields.recordDate" width="140">
<el-table :data="historyItems" v-loading="loadingHistory" style="width: 100%" class="subject-detail-table" table-layout="fixed">
<el-table-column prop="record_date" :label="TEXT.common.fields.recordDate" show-overflow-tooltip>
<template #default="scope">{{ displayDate(scope.row.record_date) }}</template>
</el-table-column>
<el-table-column prop="content" :label="TEXT.common.fields.content" min-width="240" />
<el-table-column :label="TEXT.common.labels.actions" width="200">
<el-table-column prop="content" :label="TEXT.common.fields.content" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<el-button
link
@@ -123,12 +123,12 @@
{{ TEXT.common.actions.newVisit }}
</el-button>
</div>
<el-table :data="visitItems" v-loading="loadingVisits" style="width: 100%" class="subject-detail-table">
<el-table-column prop="visit_code" :label="TEXT.common.fields.visitCode" width="120" />
<el-table-column prop="planned_date" :label="TEXT.common.fields.plannedDate" min-width="180">
<el-table :data="visitItems" v-loading="loadingVisits" style="width: 100%" class="subject-detail-table" table-layout="fixed">
<el-table-column prop="visit_code" :label="TEXT.common.fields.visitCode" show-overflow-tooltip />
<el-table-column prop="planned_date" :label="TEXT.common.fields.plannedDate" show-overflow-tooltip>
<template #default="scope">{{ displayDate(scope.row.planned_date) }}</template>
</el-table-column>
<el-table-column prop="actual_date" :label="TEXT.common.fields.actualDate" min-width="180">
<el-table-column prop="actual_date" :label="TEXT.common.fields.actualDate" show-overflow-tooltip>
<template #default="scope">
<el-date-picker
v-if="visitEditingRowId === scope.row.id"
@@ -140,7 +140,7 @@
<span v-else>{{ displayDate(scope.row.actual_date) }}</span>
</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" min-width="120">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">
<el-tag
:type="getVisitStatusTagType(getVisitStatus(scope.row, visitEditingRowId === scope.row.id ? visitRowDraft.actual_date : undefined))"
@@ -150,7 +150,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="notes" :label="TEXT.common.fields.notes" min-width="200">
<el-table-column prop="notes" :label="TEXT.common.fields.notes" show-overflow-tooltip>
<template #default="scope">
<el-input
v-if="visitEditingRowId === scope.row.id"
@@ -162,7 +162,7 @@
<span v-else>{{ scope.row.notes || TEXT.common.fallback }}</span>
</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" min-width="160">
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<template v-if="visitEditingRowId === scope.row.id">
<el-button link type="primary" size="small" :disabled="isReadOnly" @click="saveVisitRow(scope.row)">
@@ -206,31 +206,31 @@
{{ TEXT.common.actions.newAe }}
</el-button>
</div>
<el-table :data="aeItems" v-loading="loadingAes" style="width: 100%" class="subject-detail-table">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" width="140">
<el-table :data="aeItems" v-loading="loadingAes" style="width: 100%" class="subject-detail-table" table-layout="fixed">
<el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" show-overflow-tooltip>
<template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.fields.aeType" width="120">
<el-table-column :label="TEXT.common.fields.aeType">
<template #default="scope">
<el-tag size="small" effect="light" :class="getAeTypeClass(scope.row)">
{{ getAeTypeLabel(scope.row) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="term" :label="TEXT.common.fields.title" min-width="140" />
<el-table-column prop="seriousness" :label="TEXT.common.fields.seriousness" width="120">
<el-table-column prop="term" :label="TEXT.common.fields.title" show-overflow-tooltip />
<el-table-column prop="seriousness" :label="TEXT.common.fields.seriousness">
<template #default="scope">
{{ displayEnum(TEXT.enums.aeSeriousness, normalizeSeriousness(scope.row.seriousness)) }}
</template>
</el-table-column>
<el-table-column prop="causality" :label="TEXT.common.fields.causality" width="120">
<el-table-column prop="causality" :label="TEXT.common.fields.causality">
<template #default="scope">{{ displayText(scope.row.causality, TEXT.enums.aeCausality) }}</template>
</el-table-column>
<el-table-column prop="outcome" :label="TEXT.common.fields.outcome" width="120">
<el-table-column prop="outcome" :label="TEXT.common.fields.outcome">
<template #default="scope">{{ displayText(scope.row.outcome, TEXT.enums.aeOutcome) }}</template>
</el-table-column>
<el-table-column prop="description" :label="TEXT.common.fields.remark" min-width="200" />
<el-table-column :label="TEXT.common.labels.actions" width="200">
<el-table-column prop="description" :label="TEXT.common.fields.remark" show-overflow-tooltip />
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<el-button
link
@@ -264,19 +264,19 @@
{{ TEXT.modules.subjectDetail.newPd }}
</el-button>
</div>
<el-table :data="pdItems" v-loading="loadingPds" style="width: 100%" class="subject-detail-table">
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" width="130" />
<el-table-column prop="pd_type" :label="TEXT.common.fields.pdType" min-width="140" />
<el-table-column prop="pd_level" :label="TEXT.common.fields.pdLevel" min-width="120">
<el-table :data="pdItems" v-loading="loadingPds" style="width: 100%" class="subject-detail-table" table-layout="fixed">
<el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" show-overflow-tooltip />
<el-table-column prop="pd_type" :label="TEXT.common.fields.pdType" show-overflow-tooltip />
<el-table-column prop="pd_level" :label="TEXT.common.fields.pdLevel">
<template #default="scope">{{ displayEnum(TEXT.enums.pdLevel, scope.row.pd_level) }}</template>
</el-table-column>
<el-table-column prop="description" :label="TEXT.common.fields.pdDescription" min-width="240">
<el-table-column prop="description" :label="TEXT.common.fields.pdDescription" show-overflow-tooltip>
<template #default="scope">{{ scope.row.description || TEXT.common.fallback }}</template>
</el-table-column>
<el-table-column prop="status" :label="TEXT.common.fields.status" min-width="100">
<el-table-column prop="status" :label="TEXT.common.fields.status">
<template #default="scope">{{ displayEnum(TEXT.enums.pdStatus, scope.row.status) }}</template>
</el-table-column>
<el-table-column :label="TEXT.common.labels.actions" width="150">
<el-table-column :label="TEXT.common.labels.actions" width="140">
<template #default="scope">
<el-button
link
@@ -11,14 +11,15 @@
v-loading="loading"
empty-text="暂无数据"
class="custom-table center-summary-table"
table-layout="fixed"
>
<el-table-column prop="name" label="管理中心" min-width="180">
<el-table-column prop="name" label="管理中心" show-overflow-tooltip>
<template #default="{ row }">
<span class="center-name">{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="stage" label="进展阶段" width="120">
<el-table-column prop="stage" label="进展阶段">
<template #default="{ row }">
<el-tag :type="getStageType(row.stage_status)" effect="light" size="small" round>
{{ row.stage }}
@@ -26,7 +27,7 @@
</template>
</el-table-column>
<el-table-column label="实际入组例数/计划例数" width="200" align="right">
<el-table-column label="实际入组例数/计划例数" align="right">
<template #default="{ row }">
<div class="enrollment-ratio">
<span class="actual">{{ row.actual_enrolled }}</span>