修复全页面走查发现的问题(第五批:失效文件状态、日报搜索、client_context)
- content-library-view: 收藏列表的 FileCard 一直没传 removed,需求 7.3「失效文件需展示明确 状态而非直接报错」在收藏页就没生效(聊天记录页本来就传了,只有这条漏了)。后端 messageAvailability 在源消息被删/撤回时给 'removed'。 - workplace-collaboration-view: 日报"团队统计"的搜索占位符写着"搜索姓名/部门",但过滤用的 department_name 后端根本不返回(dailyReportListPayload 只有 report_id/author_id/report_date/ content_short/status/draft_updated_at/read_state/version),拼进来恒为空串,"部门"那半个 搜索永远搜不到任何东西。改为按真实有的字段搜(姓名+摘要),占位符也改成如实的; 卡片上同样读了这个不存在字段的角色徽章一并改掉。 - im-api: 企业注册申请 / 入口反馈 / 意见反馈三个接口后端都定义了 client_context 且会入库 (im_http.go:255/263/367,落库点 :790/:840/:1478),需求与对接文档也都要求带设备版本信息, 前端一直没发。在 im-api 层统一注入,三处调用点不用各写一遍。navigator.connection 不是所有 浏览器都有,拿不到就不发 network 这一项。 已用真实提交验证(返回 fb_G9GtMsAbSHQ6z6Li)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
35d3e1cf6b
commit
08bd8915c5
+20
-3
@@ -351,12 +351,29 @@ export function resolveTenant(tenantCode) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 企业注册申请 / 入口反馈 / 意见反馈三个接口后端都定义了 client_context 且会入库
|
||||||
|
// (imTenantApplicationRequest / imTenantEntryFeedbackRequest / imFeedbackRequest,
|
||||||
|
// server/im_http.go:255/263/367,落库点 :790/:840/:1478),需求文档和对接文档也都要求带上
|
||||||
|
// 设备与版本信息。前端一直没发。在这里统一注入,省得三处各写一遍、也不会再漏。
|
||||||
|
function clientContext() {
|
||||||
|
return {
|
||||||
|
platform: 'web',
|
||||||
|
app_version: PACKAGE_VERSION || '',
|
||||||
|
user_agent: (typeof navigator !== 'undefined' && navigator.userAgent) || '',
|
||||||
|
language: (typeof navigator !== 'undefined' && navigator.language) || '',
|
||||||
|
// 网络类型不是所有浏览器都有(Safari/Firefox 没有 navigator.connection),拿不到就不发这一项
|
||||||
|
network: (typeof navigator !== 'undefined' && navigator.connection && navigator.connection.effectiveType) || undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function submitTenantApplication(body) {
|
export function submitTenantApplication(body) {
|
||||||
return imRequest('/tenant-applications', {method: 'POST', auth: false, headers: idem(), body});
|
return imRequest('/tenant-applications', {method: 'POST', auth: false, headers: idem(),
|
||||||
|
body: {client_context: clientContext(), ...body}});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function submitTenantEntryFeedback(body) {
|
export function submitTenantEntryFeedback(body) {
|
||||||
return imRequest('/tenant-entry-feedback', {method: 'POST', auth: false, headers: idem(), body});
|
return imRequest('/tenant-entry-feedback', {method: 'POST', auth: false, headers: idem(),
|
||||||
|
body: {client_context: clientContext(), ...body}});
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- 1.4/1.5/1.6 Phone verification codes (register / reset_password / security scenes). --
|
// -- 1.4/1.5/1.6 Phone verification codes (register / reset_password / security scenes). --
|
||||||
@@ -697,4 +714,4 @@ export const updateDevicePushToken = (deviceId, body) => imPut('/devices/' + enc
|
|||||||
export const getAbuseReasons = (targetType = 'user') => imGet('/reports/abuse/reasons' + qs({target_type: targetType}));
|
export const getAbuseReasons = (targetType = 'user') => imGet('/reports/abuse/reasons' + qs({target_type: targetType}));
|
||||||
export const submitAbuseReport = body => imPost('/reports/abuse', body);
|
export const submitAbuseReport = body => imPost('/reports/abuse', body);
|
||||||
export const getFeedbackConfig = () => imGet('/feedback/config');
|
export const getFeedbackConfig = () => imGet('/feedback/config');
|
||||||
export const submitFeedback = body => imPost('/feedback', body);
|
export const submitFeedback = body => imPost('/feedback', {client_context: clientContext(), ...body});
|
||||||
|
|||||||
@@ -157,7 +157,11 @@ function FavoriteItem({item, onOpen, selecting, selected, onSelect}) {
|
|||||||
{selecting ? <button type="button" className={'library-check' + (selected ? ' checked' : '')} onClick={onSelect} aria-label="选择收藏"><Icon>{selected ? 'check' : ''}</Icon></button> : null}
|
{selecting ? <button type="button" className={'library-check' + (selected ? ' checked' : '')} onClick={onSelect} aria-label="选择收藏"><Icon>{selected ? 'check' : ''}</Icon></button> : null}
|
||||||
<div className="library-favorite-content">
|
<div className="library-favorite-content">
|
||||||
{item.type === 'text' ? <p className="library-text-content">{plainTextOf(item.snapshot && item.snapshot.content, item.snapshot && item.snapshot.text)}</p> : null}
|
{item.type === 'text' ? <p className="library-text-content">{plainTextOf(item.snapshot && item.snapshot.content, item.snapshot && item.snapshot.text)}</p> : null}
|
||||||
{item.type === 'file' ? <FileCard name={att && att.name} size={att && Drafty.getEntitySize(att)} mime={att && att.mime} onOpen={onOpen} /> : null}
|
{/* removed 一直没传,需求 7.3「失效文件需展示明确状态而非直接报错」在收藏列表里就没生效——
|
||||||
|
聊天记录页(下面 history-files 那处)本来就传了,只有收藏这条漏了。后端
|
||||||
|
messageAvailability(im_http.go:9113)在源消息被删/被撤回时给 'removed'。 */}
|
||||||
|
{item.type === 'file' ? <FileCard name={att && att.name} size={att && Drafty.getEntitySize(att)} mime={att && att.mime}
|
||||||
|
removed={item.availability === 'removed'} onOpen={onOpen} /> : null}
|
||||||
{item.type === 'voice' ? <VoiceCard att={att} head={item.snapshot && item.snapshot.head} /> : null}
|
{item.type === 'voice' ? <VoiceCard att={att} head={item.snapshot && item.snapshot.head} /> : null}
|
||||||
{item.type === 'link' ? <LinkText url={(item.snapshot && item.snapshot.content && item.snapshot.content.url) || plainTextOf(item.snapshot && item.snapshot.content, item.snapshot && item.snapshot.text)} onOpen={onOpen} /> : null}
|
{item.type === 'link' ? <LinkText url={(item.snapshot && item.snapshot.content && item.snapshot.content.url) || plainTextOf(item.snapshot && item.snapshot.content, item.snapshot && item.snapshot.text)} onOpen={onOpen} /> : null}
|
||||||
{item.type === 'image' || item.type === 'video' ? <MediaThumb url={item._thumbUrl} video={item.type === 'video'} onOpen={onOpen} /> : null}
|
{item.type === 'image' || item.type === 'video' ? <MediaThumb url={item._thumbUrl} video={item.type === 'video'} onOpen={onOpen} /> : null}
|
||||||
|
|||||||
@@ -652,7 +652,7 @@ const STATUS_LABEL = {submitted: '已提交', draft: '未提交'};
|
|||||||
|
|
||||||
function DailyReportCard({report, names, team}) {
|
function DailyReportCard({report, names, team}) {
|
||||||
return <article>
|
return <article>
|
||||||
<header><span><strong>{names[report.author_id] || report.author_id}</strong><small className="role-badge">{team ? (report.department_name || '员工') : '员工'}</small></span>
|
<header><span><strong>{names[report.author_id] || report.author_id}</strong><small className="role-badge">员工</small></span>
|
||||||
<em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></header>
|
<em className={report.status}>{STATUS_LABEL[report.status] || report.status}</em></header>
|
||||||
<p>{report.content_short || '(未填写内容)'}</p>
|
<p>{report.content_short || '(未填写内容)'}</p>
|
||||||
<footer><span><Icon>schedule</Icon>{report.report_date}</span>
|
<footer><span><Icon>schedule</Icon>{report.report_date}</span>
|
||||||
@@ -682,7 +682,10 @@ function DailyReportList({team, myUserId, onToast}) {
|
|||||||
React.useEffect(load, [team]);
|
React.useEffect(load, [team]);
|
||||||
|
|
||||||
const filtered = (reports || []).filter(r => {
|
const filtered = (reports || []).filter(r => {
|
||||||
const hay = team ? `${names[r.author_id] || ''}${r.department_name || ''}` : r.report_date;
|
// department_name 后端根本不返回(dailyReportListPayload 的字段只有 report_id/author_id/
|
||||||
|
// report_date/content_short/status/draft_updated_at/read_state/version),拼进来恒为空串,
|
||||||
|
// 等于占位符承诺的"部门"那半个搜索永远搜不到任何东西。改为按真实有的字段搜:姓名 + 摘要内容。
|
||||||
|
const hay = team ? `${names[r.author_id] || ''}${r.content_short || ''}` : r.report_date;
|
||||||
return hay.includes(query);
|
return hay.includes(query);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -703,7 +706,7 @@ function DailyReportList({team, myUserId, onToast}) {
|
|||||||
<button type="button" onClick={remindMissing}><Icon>notifications_active</Icon>提醒未提交成员</button>
|
<button type="button" onClick={remindMissing}><Icon>notifications_active</Icon>提醒未提交成员</button>
|
||||||
</section> : null}
|
</section> : null}
|
||||||
<label className="workplace-search"><Icon>search</Icon>
|
<label className="workplace-search"><Icon>search</Icon>
|
||||||
<input value={query} onChange={e => setQuery(e.target.value)} placeholder={team ? '搜索姓名/部门' : '搜索日期'} /></label>
|
<input value={query} onChange={e => setQuery(e.target.value)} placeholder={team ? '搜索姓名或内容' : '搜索日期'} /></label>
|
||||||
{!team ? <nav className="report-role-switch">
|
{!team ? <nav className="report-role-switch">
|
||||||
<button type="button" className="active">我的日报</button>
|
<button type="button" className="active">我的日报</button>
|
||||||
<button type="button" onClick={() => navigate('daily-report-team')}>团队统计</button>
|
<button type="button" onClick={() => navigate('daily-report-team')}>团队统计</button>
|
||||||
|
|||||||
+25
-6
@@ -3841,12 +3841,24 @@ function resolveTenant(tenantCode) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function clientContext() {
|
||||||
|
return {
|
||||||
|
platform: 'web',
|
||||||
|
app_version: _version_js__WEBPACK_IMPORTED_MODULE_1__.PACKAGE_VERSION || '',
|
||||||
|
user_agent: typeof navigator !== 'undefined' && navigator.userAgent || '',
|
||||||
|
language: typeof navigator !== 'undefined' && navigator.language || '',
|
||||||
|
network: typeof navigator !== 'undefined' && navigator.connection && navigator.connection.effectiveType || undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
function submitTenantApplication(body) {
|
function submitTenantApplication(body) {
|
||||||
return imRequest('/tenant-applications', {
|
return imRequest('/tenant-applications', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
auth: false,
|
auth: false,
|
||||||
headers: idem(),
|
headers: idem(),
|
||||||
body
|
body: {
|
||||||
|
client_context: clientContext(),
|
||||||
|
...body
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function submitTenantEntryFeedback(body) {
|
function submitTenantEntryFeedback(body) {
|
||||||
@@ -3854,7 +3866,10 @@ function submitTenantEntryFeedback(body) {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
auth: false,
|
auth: false,
|
||||||
headers: idem(),
|
headers: idem(),
|
||||||
body
|
body: {
|
||||||
|
client_context: clientContext(),
|
||||||
|
...body
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function requestVerificationCode(scene, phone) {
|
function requestVerificationCode(scene, phone) {
|
||||||
@@ -4422,7 +4437,10 @@ const getAbuseReasons = (targetType = 'user') => imGet('/reports/abuse/reasons'
|
|||||||
}));
|
}));
|
||||||
const submitAbuseReport = body => imPost('/reports/abuse', body);
|
const submitAbuseReport = body => imPost('/reports/abuse', body);
|
||||||
const getFeedbackConfig = () => imGet('/feedback/config');
|
const getFeedbackConfig = () => imGet('/feedback/config');
|
||||||
const submitFeedback = body => imPost('/feedback', body);
|
const submitFeedback = body => imPost('/feedback', {
|
||||||
|
client_context: clientContext(),
|
||||||
|
...body
|
||||||
|
});
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
@@ -8915,6 +8933,7 @@ function FavoriteItem({
|
|||||||
name: att && att.name,
|
name: att && att.name,
|
||||||
size: att && tinode_sdk__WEBPACK_IMPORTED_MODULE_1__.Drafty.getEntitySize(att),
|
size: att && tinode_sdk__WEBPACK_IMPORTED_MODULE_1__.Drafty.getEntitySize(att),
|
||||||
mime: att && att.mime,
|
mime: att && att.mime,
|
||||||
|
removed: item.availability === 'removed',
|
||||||
onOpen: onOpen
|
onOpen: onOpen
|
||||||
}, void 0, false) : null, item.type === 'voice' ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)(VoiceCard, {
|
}, void 0, false) : null, item.type === 'voice' ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)(VoiceCard, {
|
||||||
att: att,
|
att: att,
|
||||||
@@ -20907,7 +20926,7 @@ function DailyReportCard({
|
|||||||
children: names[report.author_id] || report.author_id
|
children: names[report.author_id] || report.author_id
|
||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("small", {
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("small", {
|
||||||
className: "role-badge",
|
className: "role-badge",
|
||||||
children: team ? report.department_name || '员工' : '员工'
|
children: "员工"
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("em", {
|
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("em", {
|
||||||
className: report.status,
|
className: report.status,
|
||||||
@@ -20959,7 +20978,7 @@ function DailyReportList({
|
|||||||
};
|
};
|
||||||
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(load, [team]);
|
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(load, [team]);
|
||||||
const filtered = (reports || []).filter(r => {
|
const filtered = (reports || []).filter(r => {
|
||||||
const hay = team ? `${names[r.author_id] || ''}${r.department_name || ''}` : r.report_date;
|
const hay = team ? `${names[r.author_id] || ''}${r.content_short || ''}` : r.report_date;
|
||||||
return hay.includes(query);
|
return hay.includes(query);
|
||||||
});
|
});
|
||||||
const remindMissing = () => {
|
const remindMissing = () => {
|
||||||
@@ -21022,7 +21041,7 @@ function DailyReportList({
|
|||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("input", {
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("input", {
|
||||||
value: query,
|
value: query,
|
||||||
onChange: e => setQuery(e.target.value),
|
onChange: e => setQuery(e.target.value),
|
||||||
placeholder: team ? '搜索姓名/部门' : '搜索日期'
|
placeholder: team ? '搜索姓名或内容' : '搜索日期'
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true), !team ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("nav", {
|
}, void 0, true), !team ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("nav", {
|
||||||
className: "report-role-switch",
|
className: "report-role-switch",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user