最新修改

This commit is contained in:
2026-05-26 14:08:13 +08:00
parent 93bd773c51
commit f54c58c366
18 changed files with 2180 additions and 1720 deletions

View File

@@ -20,7 +20,7 @@
<el-icon>
<User />
</el-icon>
牛马身份: {{ realStaffInfo.name }}
牛马身份: {{ realStaffInfo.username }}
</el-tag>
<el-tag v-else type="danger" round size="small"
>未录入员工表,无权接单</el-tag
@@ -71,11 +71,10 @@
</el-radio-group>
</div>
<div class="table-card">
<el-table
:data="paginatedTickets"
v-loading="loading"
border
style="width: 100%; margin-top: 20px"
class="custom-table"
>
<template #empty>
@@ -203,7 +202,7 @@
</template>
</el-table-column>
<el-table-column prop="operator" label="运营" width="120" align="center" />
<el-table-column prop="operator_name" label="运营" width="120" align="center" />
<el-table-column label="备注" min-width="150" align="center">
<template #default="scope">
@@ -274,7 +273,7 @@
<el-table-column label="操作" width="190" fixed="right" align="center">
<template #default="scope">
<el-button
v-if="scope.row.is_complete === '未分配'"
v-if="Number(scope.row.status) === 0"
type="primary"
size="small"
:disabled="!realStaffInfo"
@@ -283,8 +282,8 @@
>
<template
v-if="
scope.row.is_complete === '进行中' &&
String(scope.row.staff_id) === String(realStaffInfo?.id)
Number(scope.row.status) === 1 &&
String(scope.row.user_id) === String(realStaffInfo?.id)
"
>
<el-button type="success" size="small" @click="handleFinish(scope.row)"
@@ -310,6 +309,7 @@
background
/>
</div>
</div>
</div>
</template>
@@ -339,6 +339,7 @@ const editValue = ref("");
const currentPage = ref(1);
const pageSize = ref(15);
const emptyText = computed(() => `暂无${currentStatus.value}的工单`);
// js计算时间
const welcomeMessage = computed(() => {
@@ -386,7 +387,7 @@ const fetchTickets = async () => {
loading.value = false;
return;
}
params.staff_id = realStaffInfo.value.id;
params.user_id = realStaffInfo.value.id;
}
const res = await ticketApi.getTickets(params);
@@ -457,8 +458,8 @@ const handleAccept = (row) => {
ElMessageBox.confirm(`确认接手工单 #${row.id}?`).then(async () => {
try {
const res = await ticketApi.updateTicket(row.id, {
staff_id: realStaffInfo.value.id,
is_complete: "进行中",
user_id: realStaffInfo.value.id,
status: 1,
progress: 0,
});
if (res.code === 200 || res.code === true) {
@@ -478,9 +479,9 @@ const handleFinish = (row) => {
const currentTimestamp = Math.floor(Date.now() / 1000);
// 关键修改:在提交时增加 progress: 100
const res = await ticketApi.updateTicket(row.id, {
is_complete: "已完成",
status: 2,
lock_time: String(currentTimestamp),
progress: 100, // 默认改为100
progress: 100,
});
if (res.code === 200 || res.code === true) {
@@ -502,8 +503,8 @@ const handleCancel = (row) => {
).then(async () => {
try {
const res = await ticketApi.updateTicket(row.id, {
staff_id: null,
is_complete: "未分配",
user_id: null,
status: 0,
progress: 0,
});
if (res.code === 200 || res.code === true) {
@@ -534,9 +535,9 @@ const handleLogout = () => {
onMounted(async () => {
try {
const res = await ticketApi.getStaffs();
const res = await ticketApi.getUserStaffs();
if (res.code === 200 || res.code === true) {
const match = (res.data || []).find((s) => s.name === currentUser.value.username);
const match = (res.data || []).find((s) => s.username === currentUser.value.username);
if (match) realStaffInfo.value = match;
}
} catch (e) {}
@@ -545,226 +546,357 @@ onMounted(async () => {
</script>
<style scoped>
/* 容器布局 */
.header-main {
display: flex;
flex-direction: column;
justify-content: center;
/* ============================================
ENERGY WORKBENCH — Gamified Employee Desk
============================================ */
.user-view-container {
padding: 12px 12px 0;
min-height: 0;
background: none;
--glow-indigo: rgba(99, 102, 241, 0.35);
--glow-amber: rgba(245, 158, 11, 0.3);
--glow-green: rgba(34, 197, 94, 0.3);
--glow-rose: rgba(244, 63, 94, 0.25);
}
.welcome-container {
display: flex;
flex-direction: column;
gap: 8px;
/* 这里统一控制欢迎语、副标题、标签之间的垂直间距 */
/* ---- Header Card (Gradient Hero) ---- */
.user-header-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
border: none;
border-radius: 16px;
padding: 28px 32px;
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 20px;
box-shadow:
0 4px 16px rgba(102, 126, 234, 0.2),
0 8px 32px rgba(118, 75, 162, 0.15);
position: relative;
overflow: hidden;
}
/* 清除标题默认的垂直 margin,防止撑开间距 */
.user-header-card::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(circle at 20% 50%, rgba(255,255,255,0.08) 0%, transparent 50%),
radial-gradient(circle at 80% 50%, rgba(255,255,255,0.04) 0%, transparent 50%);
pointer-events: none;
}
.header-main { display: flex; flex-direction: column; justify-content: center; position: relative; z-index: 1; }
.welcome-container { display: flex; flex-direction: column; gap: 8px; }
.greeting {
margin: 0;
color: #1a1a1a;
color: #fff;
font-size: 22px;
line-height: 1.2;
line-height: 1.3;
font-weight: 700;
letter-spacing: -0.02em;
text-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
/* 副标题紧贴标题 */
.sub-text {
margin: 4px 0 0 0;
/* 仅顶部保留微小间距 */
color: #8c8c8c;
margin: 4px 0 0;
color: rgba(255,255,255,0.75);
font-size: 13px;
font-weight: 400;
letter-spacing: 0.01em;
}
/* 标签组位置微调 */
.identity-badges {
margin-top: 4px;
/* 让标签组靠近上方的文字 */
display: flex;
align-items: center;
}
/* 针对 el-tag 内部图标和文字的微调 */
:deep(.el-tag) {
display: inline-flex;
align-items: center;
border-style: dashed;
/* 既然是牛马,边框可以搞成虚线更有自嘲感 */
}
.user-view-container {
padding: 24px;
background-color: #f0f2f5;
min-height: 100vh;
}
.user-header-card {
background: white;
padding: 24px;
border-radius: 12px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}
.greeting {
margin: 0 0 8px 0;
color: #1a1a1a;
font-size: 24px;
.identity-badges { margin-top: 8px; display: flex; align-items: center; position: relative; z-index: 1; }
:deep(.identity-badges .el-tag) {
display: inline-flex !important;
align-items: center !important;
gap: 5px !important;
background: rgba(255,255,255,0.18) !important;
backdrop-filter: blur(8px);
border: 1px solid rgba(255,255,255,0.25) !important;
color: #fff !important;
font-weight: 600 !important;
padding: 4px 14px !important;
border-radius: 20px !important;
}
:deep(.identity-badges .el-tag .el-icon) { color: #fbbf24 !important; }
.header-action { position: relative; z-index: 1; }
.header-action :deep(.el-button) {
background: rgba(255,255,255,0.15) !important;
border: 1px solid rgba(255,255,255,0.25) !important;
color: #fff !important;
backdrop-filter: blur(8px);
border-radius: 24px !important;
padding: 8px 18px !important;
}
.header-action :deep(.el-button:hover) {
background: rgba(255,255,255,0.25) !important;
}
/* ---- Tab Switcher ---- */
.status-tabs-wrapper {
background: white;
padding: 8px;
border-radius: 8px;
background: #fff;
border: 1px solid rgba(0,0,0,0.06);
border-radius: 14px;
padding: 5px;
display: inline-block;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
margin-bottom: 18px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.custom-radio-group :deep(.el-radio-button__inner) {
border: none !important;
border-radius: 6px !important;
margin: 0 4px;
padding: 10px 20px;
display: flex;
align-items: center;
gap: 6px;
border-radius: 10px !important;
margin: 0 1px;
padding: 10px 18px;
display: flex; align-items: center; gap: 6px;
font-weight: 500;
font-size: 13px;
color: #6b6d7a;
background: none;
transition: all 0.2s;
}
.custom-table {
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
.custom-radio-group :deep(.el-radio-button__inner:hover) {
color: #667eea;
}
.cell-content-card {
.custom-radio-group :deep(.is-active .el-radio-button__inner) {
background: linear-gradient(135deg, #667eea, #764ba2);
color: #fff;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.35);
}
/* ---- Table Card ---- */
.table-card {
background: #fff;
border: 1px solid rgba(0,0,0,0.06);
border-radius: 16px;
padding: 20px 24px;
box-shadow:
0 2px 8px rgba(0,0,0,0.03),
0 4px 20px rgba(0,0,0,0.04);
}
.custom-table { overflow: hidden; border-radius: var(--radius-md); }
:deep(.el-table__header th) {
background: #f8f9fc;
color: #5b5d68;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.4px;
text-transform: uppercase;
border-bottom: 2px solid #eef0f4 !important;
}
:deep(.el-table__body tr) { transition: all 0.15s; }
:deep(.el-table__body tr:hover > td) {
background: linear-gradient(90deg, rgba(102,126,234,0.03), rgba(118,75,162,0.02)) !important;
}
:deep(.el-table__body tr) { border-bottom: 1px solid #f5f5f8; }
/* Staggered row tints */
:deep(.el-table__body tr:nth-child(odd) td) { background: #fdfdfe; }
:deep(.el-table__body tr:nth-child(even) td) { background: #fafbfd; }
.cell-content-card { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; min-height: 60px; }
.data-display-area { min-height: 24px; display: flex; align-items: center; justify-content: center; width: 100%; }
.display-val { font-weight: 700; color: #667eea; font-size: 15px; font-family: "Courier New", monospace; }
.display-remark {
font-size: 12px; color: #5b5d68; max-width: 180px; line-height: 1.4;
background: #f8f9fc; padding: 4px 12px; border-radius: 6px; text-align: center;
}
.no-data-placeholder { color: #c0c4cc; font-size: 12px; }
.pure-date { color: #6b6d7a; font-weight: 500; font-family: "Courier New", monospace; font-size: 12px; }
.edit-link-btn { font-size: 12px; height: auto; padding: 0; opacity: 0.6; color: #667eea; transition: all 0.15s; }
.edit-link-btn:hover { opacity: 1; color: #4f46e5; font-weight: 600; }
/* ---- Pagination ---- */
.pagination-container {
margin-top: 18px; display: flex; justify-content: flex-end;
padding-top: 16px;
border-top: 1px solid #f0f1f4;
}
/* ---- Progress ---- */
:deep(.el-progress-bar__outer) { background: #eef0f4; border-radius: 10px; overflow: hidden; }
:deep(.el-progress-bar__inner) {
background: linear-gradient(90deg, #667eea, #764ba2) !important;
}
:deep(.el-progress-bar__innerText) {
display: flex !important; align-items: center !important;
justify-content: center !important; height: 100% !important;
line-height: 1 !important; vertical-align: middle !important;
}
:deep(.el-progress-bar__innerText svg),
:deep(.el-progress-bar__innerText .el-icon) {
margin: 0 !important; position: relative !important;
top: -1px !important; width: 0.8em; height: 0.8em;
}
:deep(.el-progress) { display: flex; align-items: center; }
.progress-radio-group { display: flex; justify-content: center; margin: 10px 0; }
.progress-radio-group :deep(.el-radio-button__inner) { padding: 8px 10px !important; }
/* ---- Table Overrides ---- */
:deep(.el-table__row) { height: 100px; }
:deep(.el-table .cell) { overflow: visible !important; }
/* ---- Popover (Inline Edit Flyout) ---- */
:deep(.el-popover) {
border-radius: 16px !important;
border: none !important;
box-shadow:
0 8px 32px rgba(0,0,0,0.1),
0 2px 8px rgba(0,0,0,0.06) !important;
padding: 20px !important;
}
.popover-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
min-height: 60px;
}
.data-display-area {
min-height: 24px;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
.display-val {
font-weight: 700;
color: #409eff;
font-size: 15px;
}
.display-remark {
font-size: 12px;
color: #595959;
max-width: 180px;
line-height: 1.4;
background: #f5f7fa;
padding: 4px 10px;
border-radius: 4px;
text-align: center;
}
.no-data-placeholder {
color: #dcdfe6;
font-size: 12px;
}
.pure-date {
color: #606266;
font-weight: 500;
font-family: monospace;
font-size: 14px;
}
.edit-link-btn {
font-size: 12px;
height: auto;
padding: 0;
opacity: 0.7;
}
.edit-link-btn:hover {
opacity: 1;
text-decoration: underline;
}
.pagination-container {
margin-top: 24px;
display: flex;
justify-content: flex-end;
padding: 10px 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.progress-radio-group {
display: flex;
justify-content: center;
margin: 10px 0;
}
.progress-radio-group :deep(.el-radio-button__inner) {
padding: 8px 10px !important;
}
:deep(.el-table__row) {
height: 100px;
}
:deep(.el-table .cell) {
overflow: visible !important;
gap: 4px;
}
.pop-header {
font-size: 14px;
font-weight: 600;
margin-bottom: 12px;
color: #434343;
text-align: center;
font-size: 13px;
font-weight: 700;
margin-bottom: 4px;
color: #1c1c28;
text-align: left;
letter-spacing: -0.01em;
display: flex;
align-items: center;
gap: 6px;
}
.pop-header::before {
content: "";
width: 3px; height: 14px;
background: linear-gradient(180deg, #667eea, #764ba2);
border-radius: 2px;
}
:deep(.popover-content .el-input__wrapper) {
border-radius: 10px !important;
box-shadow: 0 0 0 1px rgba(0,0,0,0.08) inset !important;
transition: box-shadow 0.2s;
}
:deep(.popover-content .el-input__wrapper:hover) {
box-shadow: 0 0 0 1px rgba(102,126,234,0.3) inset !important;
}
:deep(.popover-content .el-input__wrapper.is-focus) {
box-shadow: 0 0 0 2px rgba(102,126,234,0.15), 0 0 0 1px #667eea inset !important;
}
:deep(.popover-content .el-textarea__inner) {
border-radius: 10px !important;
box-shadow: 0 0 0 1px rgba(0,0,0,0.08) inset !important;
transition: box-shadow 0.2s;
font-size: 13px;
}
:deep(.popover-content .el-textarea__inner:focus) {
box-shadow: 0 0 0 2px rgba(102,126,234,0.15), 0 0 0 1px #667eea inset !important;
}
.pop-footer {
margin-top: 12px;
margin-top: 10px;
text-align: right;
}
/* 1. 强行修正进度条内部容器的对齐方式 */
:deep(.el-progress-bar__innerText) {
display: flex !important;
align-items: center !important;
/* 垂直居中 */
justify-content: center !important;
/* 水平居中 */
height: 100% !important;
line-height: 1 !important;
/* 移除默认的基线对齐 */
vertical-align: middle !important;
.pop-footer :deep(.el-button--primary) {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
border: none !important;
border-radius: 10px !important;
padding: 7px 20px !important;
font-weight: 600 !important;
box-shadow: 0 2px 8px rgba(102,126,234,0.3);
transition: all 0.2s;
}
.pop-footer :deep(.el-button--primary:hover) {
box-shadow: 0 4px 16px rgba(102,126,234,0.4);
transform: translateY(-1px);
}
/* 2. 针对 100% 时出现的那个 svg 图标进行位移修正 */
:deep(.el-progress-bar__innerText svg),
:deep(.el-progress-bar__innerText .el-icon) {
margin: 0 !important;
/* 关键:利用相对定位向上平移 1px,抵消视觉上的下沉 */
position: relative !important;
top: -1px !important;
/* 稍微调整图标大小,让它在 10px 的进度条里更协调 */
width: 0.8em;
height: 0.8em;
/* Progress radio buttons in popover */
:deep(.popover-content .el-radio-button__inner) {
border-radius: 8px !important;
padding: 6px 12px !important;
}
:deep(.popover-content .el-radio-button__inner:hover) {
color: #667eea !important;
}
:deep(.popover-content .is-active .el-radio-button__inner) {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
border-color: transparent !important;
color: #fff !important;
box-shadow: 0 2px 6px rgba(102,126,234,0.3);
}
/* 3. 如果还是觉得整体偏,可以给进度条容器加一个微调 */
:deep(.el-progress) {
display: flex;
align-items: center;
/* ---- Action Buttons Glow ---- */
:deep(.el-table .el-button--primary) { transition: all 0.2s; }
:deep(.el-table .el-button--primary:hover) { box-shadow: 0 0 12px var(--glow-indigo); }
:deep(.el-table .el-button--success:hover) { box-shadow: 0 0 12px var(--glow-green); }
:deep(.el-table .el-button--warning:hover) { box-shadow: 0 0 12px var(--glow-amber); }
/* ---- Logout Dropdown ---- */
:deep(.el-dropdown-menu) {
border-radius: 14px !important;
border: none !important;
box-shadow: 0 8px 32px rgba(0,0,0,0.1), 0 2px 8px rgba(0,0,0,0.06) !important;
padding: 6px !important;
}
:deep(.el-dropdown-menu__item) {
border-radius: 10px !important;
padding: 9px 16px !important;
font-size: 13px !important;
font-weight: 500 !important;
transition: all 0.15s !important;
}
:deep(.el-dropdown-menu__item:hover) {
background: linear-gradient(135deg, rgba(244,63,94,0.06), rgba(244,63,94,0.02)) !important;
color: #e11d48 !important;
}
/* ---- Message Box (Logout Confirm) ---- */
:deep(.el-message-box) {
border-radius: 18px !important;
border: none !important;
box-shadow: 0 12px 48px rgba(0,0,0,0.12), 0 4px 16px rgba(0,0,0,0.06) !important;
padding: 28px !important;
}
:deep(.el-message-box__title) {
font-size: 16px !important;
font-weight: 700 !important;
color: #1c1c28 !important;
}
:deep(.el-message-box__message) {
font-size: 13px !important;
color: #6b6d7a !important;
line-height: 1.6 !important;
}
:deep(.el-message-box__btns) {
padding-top: 12px !important;
}
:deep(.el-message-box__btns .el-button) {
border-radius: 10px !important;
padding: 9px 22px !important;
font-weight: 500 !important;
font-size: 13px !important;
}
:deep(.el-message-box__btns .el-button--primary) {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
border: none !important;
box-shadow: 0 2px 8px rgba(102,126,234,0.3) !important;
}
:deep(.el-message-box__btns .el-button--primary:hover) {
box-shadow: 0 4px 16px rgba(102,126,234,0.4) !important;
}
</style>