Commit a3e29145 by DaiJiezhang

Refine wechat list layout and image actions

parent f7030db4
......@@ -347,6 +347,23 @@ async function saveWechatRecord(payload) {
}
/**
* 代码作用(白话):在列表里删除企微手机图片时,先取最新记录再清空图片字段并复用统一保存接口;关联文件:F:/Project/xyw_console/src/modules/wechat/wechat-list-runtime.js、F:/Project/xyw_console/src/modules/shared/wechat-api-client.js;关联逻辑(调用链/消息链/数据流):列表删除图片按钮 -> removeWechatRecordImage() -> getWechatRecordById() -> saveWechatRecord() -> refreshWechatList()。
*/
async function removeWechatRecordImage(recordId) {
const record = await getWechatRecordById(recordId);
if (!record) {
throw new Error('未找到对应企微记录');
}
const payload = {
...record,
phone_image: '',
phoneImage: '',
'手机图片': ''
};
return saveWechatRecord(payload);
}
/**
* 代码作用(白话):在企微保存成功后刷新当前页面,保证列表、详情和弹窗看到的是同一份最新数据;关联文件:F:/Project/xyw_console/src/modules/wechat/wechat-add-dialog.js;关联逻辑(调用链/消息链/数据流):WechatAddDialogActions.afterSave() -> refreshWechatList() -> renderModule() -> 重新挂载 wechat 列表。
*/
async function refreshWechatList() {
......@@ -477,24 +494,32 @@ function renderExternalRuntime(moduleKey) {
add: '新增资料',
reset: '重置',
realName: '姓名',
account: '账号',
alias: '别名',
department: '部门',
gender: '性别',
phone: '手机号',
wxId: '微信 ID',
status: '状态',
owner: '负责人',
updatedAt: '更新时间',
owner: '实名人',
accountLocation: '账号位置',
ownerStatus: '实名状态',
phoneImage: '手机图片',
action: '操作',
view: '查看',
edit: '编辑',
replaceImage: '更换图片',
removeImage: '删除图片',
imageMissing: '暂无图片',
selected: '已选',
items: '项',
batchAction: '批量操作',
total: '共',
records: '条',
pageSuffix: ' 条/页',
searchPlaceholder: '搜索姓名、微信 ID、手机号或部门',
searchPlaceholder: '搜索姓名、账号、手机号、部门或实名人',
loadFailed: '加载企微列表失败,请确认本地后端已启动',
openFailed: '打开企微详情失败,请稍后重试'
openFailed: '打开企微详情失败,请稍后重试',
imageRemoved: '已删除手机图片',
imageRemoveFailed: '删除手机图片失败,请稍后重试'
},
wechatTablePageSizes: [10, 20, 50, 100],
mountState: moduleMountState.wechat,
......@@ -502,6 +527,7 @@ function renderExternalRuntime(moduleKey) {
loadWechatRows,
openAddDialog: openWechatAddDialog,
openDrawer: openWechatDrawer,
removeRecordImage: removeWechatRecordImage,
getVisiblePageNumbers,
getWechatStatusDotClass,
notifyError: showError,
......@@ -696,3 +722,7 @@ document.addEventListener('DOMContentLoaded', initPage);
......@@ -12,33 +12,45 @@
const ownerStatusRaw = source.ownerStatus ?? source.real_name_owner_status ?? source.realNameOwnerStatus;
const status = ownerStatusRaw === 'abnormal' || ownerStatusRaw === '异常' || ownerStatusRaw === 0 ? '异常' : '正常';
const remark = source.remark || source.project || '暂无备注';
const accountLocation = source.account_location || source.accountLocation || source['账号位置'] || '';
const phoneImage = source.phone_image || source.phoneImage || source['手机图片'] || '';
const departmentName = departmentMap[source.department] || source.department || source.department_name || source.departmentName || '';
const realName = source.realName || source.real_name || '';
const aliasName = source.alias_name || source.alias || source.aliasName || '';
const account = source.account || source.wxId || '';
const phoneNumber = source.phone_number || source.phone || source.phoneNumber || '';
const ownerName = source.real_name_owner || source.owner || source.realNameOwner || '';
return {
...source,
realName: source.realName || source.real_name || '',
real_name: source.real_name || source.realName || '',
alias: source.alias || source.alias_name || source.aliasName || '',
alias_name: source.alias_name || source.alias || source.aliasName || '',
account: source.account || source.wxId || '',
department: departmentMap[source.department] || source.department || source.department_name || source.departmentName || '未分配',
department_name: source.department_name || source.department || source.departmentName || '',
phone: source.phone || source.phone_number || source.phoneNumber || '',
phone_number: source.phone_number || source.phone || source.phoneNumber || '',
owner: source.owner || source.real_name_owner || source.realNameOwner || '',
real_name_owner: source.real_name_owner || source.owner || source.realNameOwner || '',
realName,
real_name: realName,
alias: aliasName,
alias_name: aliasName,
account,
department: departmentName || '未分配',
department_name: departmentName,
phone: phoneNumber,
phone_number: phoneNumber,
owner: ownerName,
real_name_owner: ownerName,
ownerStatus: status,
real_name_owner_status: status === '正常' ? 1 : 0,
status,
wxId: source.wxId || source.account || '',
wxId: source.wxId || account,
createdAt: source.createdAt || source.created_at || '',
created_at: source.created_at || source.createdAt || '',
updatedAt: source.updatedAt || source.updated_at || '',
updated_at: source.updated_at || source.updatedAt || '',
remark,
project: source.project || remark,
gender: source.gender || '男',
account_location: source.account_location || source.accountLocation || source['账号位置'] || '',
phone_image: source.phone_image || source.phoneImage || source['手机图片'] || ''
gender: source.gender || '',
account_location: accountLocation,
accountLocation,
'账号位置': accountLocation,
phone_image: phoneImage,
phoneImage,
'手机图片': phoneImage
};
}
......
(function attachWechatApiClient() {
// 当前企微资料接口对应测试数据库;后续切换到生产数据库(正式业务库)时,需要同步改成生产环境对应的后端配置。
const BASE_URL = 'http://localhost:8080/api/wechat-records';
/**
......@@ -55,3 +56,4 @@
saveWechatRecord
};
})();
/* Import original styles first */
/* Import original styles first */
@import url('styles.css');
/* Overrides for right side replication */
......@@ -306,16 +306,16 @@
}
.fselect:after {
content: "▾";
content: "鈻?;
color: #9ca3af;
}
/* Custom icon for el-select to match batch action button icon */
/* Custom icon for el-select to match batch action button icon 鈻?*/
.custom-fselect .el-input__suffix-inner > .el-icon > svg {
display: none !important;
}
.custom-fselect .el-input__suffix-inner > .el-icon::before {
content: "▾";
content: "鈻?;
color: #9ca3af;
font-size: 14px;
display: flex;
......@@ -1003,7 +1003,143 @@
fill: currentColor !important;
}
/* 消除原来的旧外边距干扰 */
/* 娑堥櫎鍘熸潵鐨勬棫澶栬竟璺濆共鎵?*/
.domain-mode .action-dots {
margin: 0;
}
.wechat-list-table {
table-layout: fixed;
}
.table-wrap-refined {
overflow-x: auto;
overflow-y: hidden;
}
.wechat-location-cell {
white-space: normal;
word-break: break-word;
}
.wechat-image-cell {
display: flex;
align-items: center;
}
.wechat-image-thumb {
width: 84px;
height: 84px;
border-radius: 10px;
overflow: hidden;
border: 1px solid #dbe4f0;
background: #f8fafc;
}
.wechat-image-thumb .el-image__inner {
width: 100%;
height: 100%;
object-fit: cover;
}
.wechat-image-empty {
color: #94a3b8;
font-size: 12px;
}
.wechat-action-cluster {
flex-wrap: wrap;
justify-content: flex-start;
gap: 6px;
}
.action-pill-danger {
color: #dc2626;
}
.action-pill-danger:hover:not(:disabled) {
background: #fef2f2;
color: #b91c1c;
}
.action-pill:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.table-area-refined {
flex: 1 1 auto;
min-height: 0;
height: 100%;
}
.table-toolbar-refined {
flex: 0 0 auto;
}
.table-wrap-refined {
flex: 1 1 auto;
min-height: 0;
height: 0;
overflow-x: auto;
overflow-y: auto;
}
#wechatListRoot,
#phoneListRoot {
min-height: 0;
}
#vue-router-app,
.legacy-wrapper {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
height: 100%;
}
#pageHeader {
flex: 0 0 auto;
}
#pageBody {
display: flex !important;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
#wechatListRoot,
#phoneListRoot,
#overviewListRoot {
flex: 1 1 auto;
min-height: 0;
height: 100%;
}
#wechatListRoot[style*='display: block'],
#phoneListRoot[style*='display: block'],
#overviewListRoot[style*='display: block'] {
display: flex !important;
flex-direction: column;
}
.table-area-refined {
flex: 1 1 auto !important;
min-height: 0 !important;
height: 100% !important;
}
.table-wrap-refined {
flex: 1 1 auto !important;
min-height: 0 !important;
height: 0 !important;
overflow-x: auto !important;
overflow-y: auto !important;
}
:root {
:root {
--page-bg: #f5f7fb;
--surface: #ffffff;
--surface-soft: #fafcff;
......@@ -2922,14 +2922,38 @@ button {
/* Professional admin dashboard visual override */
.shell-main { background: linear-gradient(180deg, #f7f9fc 0%, #eff4f9 100%); }
.shell-header { padding: 28px 28px 20px; border-bottom: 1px solid rgba(15, 23, 42, 0.06); background: rgba(255, 255, 255, 0.92); }
.workspace-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }
.heading-copy { display: grid; gap: 12px; max-width: 760px; }
.legacy-wrapper {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0;
height: 100%;
}
#pageHeader {
flex: 0 0 auto;
}
#pageBody {
flex: 1 1 auto;
min-height: 0;
}
#pageBody > #wechatListRoot,
#pageBody > #phoneListRoot,
#pageBody > #overviewListRoot {
height: 100%;
min-height: 0;
}
.shell-header { padding: 20px 28px 16px; border-bottom: 1px solid rgba(15, 23, 42, 0.06); background: rgba(255, 255, 255, 0.92); }
.workspace-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; min-height: 88px; }
.heading-copy { display: grid; gap: 8px; flex: 1 1 420px; min-width: 0; max-width: 760px; align-content: start; }
.heading-caption-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.heading-caption { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #6b7a90; }
.heading-badge { display: inline-flex; align-items: center; height: 28px; padding: 0 12px; border-radius: 999px; background: #eef4ff; color: #2554cf; font-size: 12px; font-weight: 700; }
.page-title { margin: 0; font-size: 32px; line-height: 1.1; font-weight: 800; color: #0f172a; }
.page-summary { margin: 0; color: #667085; font-size: 14px; line-height: 1.7; }
.page-title { margin: 0; font-size: 30px; line-height: 1.08; font-weight: 800; color: #0f172a; }
.page-summary { margin: 0; color: #667085; font-size: 14px; line-height: 1.5; }
.admin-summary-pills { display: flex; flex-wrap: wrap; gap: 10px; }
.status-pill { display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.18); background: #fff; box-shadow: 0 10px 24px rgba(15, 23, 42, 0.04); font-size: 13px; color: #475467; }
.status-pill strong { color: #0f172a; }
......@@ -2937,7 +2961,7 @@ button {
.status-pill.green { background: #edfdf3; color: #177245; }
.status-pill.orange { background: #fff6ea; color: #c76a00; }
.status-pill.red { background: #fff1f3; color: #d92d20; }
.header-tools { display: flex; flex: 0 0 460px; flex-direction: column; gap: 14px; }
.header-tools { display: flex; flex: 1 1 360px; min-width: 280px; max-width: 460px; margin-left: auto; flex-direction: column; gap: 14px; }
.header-search { display: flex; align-items: center; gap: 10px; width: 100%; min-width: 0; height: 52px; padding: 0 16px; border: 1px solid rgba(148, 163, 184, 0.24); border-radius: 16px; background: rgba(255, 255, 255, 0.98); box-shadow: 0 12px 30px rgba(15, 23, 42, 0.05); }
.header-search::before { content: none; }
.header-search-icon { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: #eef4ff; color: #2554cf; font-size: 14px; }
......@@ -2946,7 +2970,7 @@ button {
.header-button, .header-button-primary, .toolbar-button, .footer-button, .footer-button-primary, .preview-link { height: 42px; padding: 0 16px; border-radius: 14px; font-weight: 700; }
.header-button, .toolbar-button, .footer-button, .preview-link { border: 1px solid rgba(148, 163, 184, 0.2); background: #fff; box-shadow: 0 8px 22px rgba(15, 23, 42, 0.05); }
.header-button-primary, .footer-button-primary { border: 1px solid #2563eb; background: linear-gradient(180deg, #3b82f6 0%, #2563eb 100%); color: #fff; box-shadow: 0 14px 28px rgba(37, 99, 235, 0.24); }
.shell-body { gap: 20px; padding: 20px 28px 28px; background: transparent; }
.shell-body { display: flex; flex: 1 1 auto; flex-direction: column; gap: 16px; min-height: 0; overflow: hidden; padding: 16px 28px 20px; background: transparent; }
.stats-grid { gap: 16px; }
.metric-card-premium { position: relative; display: flex; flex-direction: column; gap: 16px; min-height: 190px; padding: 20px 22px; border-radius: 22px; border: 1px solid rgba(226, 232, 240, 0.92); box-shadow: 0 18px 42px rgba(15, 23, 42, 0.06); overflow: hidden; }
.metric-card-premium[data-tone="blue"] { background: linear-gradient(180deg, #eef5ff 0%, #ffffff 100%); }
......@@ -3034,7 +3058,7 @@ button {
.timeline-time { color: #98a2b3; font-size: 12px; }
.detail-footer { display: flex; gap: 10px; }
.detail-footer > * { flex: 1; }
@media (max-width: 1360px) { .workspace-heading, .table-head-v3, .filter-toolbar, .preview-head-v3 { flex-direction: column; align-items: stretch; } .header-tools { flex: 1 1 auto; } .table-selection-chip { min-width: 0; } }
@media (max-width: 1360px) { .workspace-heading, .table-head-v3, .filter-toolbar, .preview-head-v3 { flex-direction: column; align-items: stretch; } .header-tools { flex: 1 1 auto; min-width: 0; max-width: none; margin-left: 0; } .table-selection-chip { min-width: 0; } }
@media (max-width: 1180px) { .shell-header, .shell-body { padding-left: 18px; padding-right: 18px; } .page-title { font-size: 28px; } .preview-row-v3 { grid-template-columns: 32px minmax(0, 1fr); } .preview-link { grid-column: 2; justify-self: start; } }
@media (max-width: 840px) { .shell-header, .shell-body { padding-left: 14px; padding-right: 14px; } .page-title { font-size: 24px; } .detail-grid { grid-template-columns: 1fr; } }
@media (min-width: 1280px) {
......@@ -3047,3 +3071,5 @@ button {
.workspace:not(.sidebar-collapsed) .nav-link,
.workspace:not(.sidebar-collapsed) .nav-toggle-button { justify-content: flex-start; gap: 12px; padding: 0 14px; }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment