修复精准查找对拉黑关系显示"添加",跟实际能不能添加对不上(第5章复测发现)
/users/search 返回结果本身带 relationship 字段,服务端 imRelationshipAction() 对 blocked_by_me/blocked_by_peer 都明确映射成 action:"none"(不允许发起添加)——但 前端 actionLabel 只认 friend/pending_outbound/pending_inbound 三种,其余(含两种 拉黑关系)一律落到兜底的"添加"文案。点进去虽然会跳到资料页、由资料页自己的 cannotAddReason 挡住(不会真的误发出申请),但列表这一行本身的文案是误导的。 补上跟 Profile 组件里已有的 cannotAddReason 一致的两条文案(已拉黑/无法添加), 只是精简成适合一行列表项的长度。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7340b5e135
commit
d21d046443
@@ -265,8 +265,14 @@ function AddFriend({result = false, onToast, onOpenScanner}) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}).catch(err => onToast(err.message || '生成邀请链接失败'));
|
}).catch(err => onToast(err.message || '生成邀请链接失败'));
|
||||||
};
|
};
|
||||||
|
// Real search results carry a relationship for blocked pairs too (blocked_by_me/blocked_by_peer),
|
||||||
|
// which previously fell through to the same generic "添加" as an untouched stranger -- misleading
|
||||||
|
// since tapping through leads to a profile page whose own cannotAddReason (see the Profile
|
||||||
|
// component below) already refuses to let the request go anywhere. Matches that component's
|
||||||
|
// wording, just condensed to fit this one-line list item.
|
||||||
const actionLabel = item => item.relationship === 'friend' ? '已是好友' :
|
const actionLabel = item => item.relationship === 'friend' ? '已是好友' :
|
||||||
item.relationship === 'pending_outbound' ? '已申请' : item.relationship === 'pending_inbound' ? '待通过' : '添加';
|
item.relationship === 'pending_outbound' ? '已申请' : item.relationship === 'pending_inbound' ? '待通过' :
|
||||||
|
item.relationship === 'blocked_by_me' ? '已拉黑' : item.relationship === 'blocked_by_peer' ? '无法添加' : '添加';
|
||||||
return <div className="people-page"><Header title="添加好友" back="address-book" />
|
return <div className="people-page"><Header title="添加好友" back="address-book" />
|
||||||
<Search value={query} onChange={v => { setQuery(v); if (!v.trim()) { setSearched(false); setResults([]); } }} placeholder="查找账号" onSubmit={() => runSearch(query)} />
|
<Search value={query} onChange={v => { setQuery(v); if (!v.trim()) { setSearched(false); setResults([]); } }} placeholder="查找账号" onSubmit={() => runSearch(query)} />
|
||||||
<main>
|
<main>
|
||||||
|
|||||||
+50
-14
@@ -4401,9 +4401,8 @@ const updateMonthlyDraft = (reportId, workSummary, nextPlan, version, attachment
|
|||||||
const submitMonthlyReport = (reportId, version) => imPost('/reports/monthly/' + encodeURIComponent(reportId) + '/submit', {
|
const submitMonthlyReport = (reportId, version) => imPost('/reports/monthly/' + encodeURIComponent(reportId) + '/submit', {
|
||||||
version
|
version
|
||||||
});
|
});
|
||||||
const reopenMonthlyReport = (reportId, version, reason = '补充内容') => imPost('/reports/monthly/' + encodeURIComponent(reportId) + '/reopen', {
|
const reopenMonthlyReport = (reportId, version) => imPost('/reports/monthly/' + encodeURIComponent(reportId) + '/reopen', {
|
||||||
version,
|
version
|
||||||
reason
|
|
||||||
});
|
});
|
||||||
const getMonthlyStatistics = month => imGet('/reports/monthly/statistics' + qs({
|
const getMonthlyStatistics = month => imGet('/reports/monthly/statistics' + qs({
|
||||||
month
|
month
|
||||||
@@ -7820,7 +7819,7 @@ function AddFriend({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}).catch(err => onToast(err.message || '生成邀请链接失败'));
|
}).catch(err => onToast(err.message || '生成邀请链接失败'));
|
||||||
};
|
};
|
||||||
const actionLabel = item => item.relationship === 'friend' ? '已是好友' : item.relationship === 'pending_outbound' ? '已申请' : item.relationship === 'pending_inbound' ? '待通过' : '添加';
|
const actionLabel = item => item.relationship === 'friend' ? '已是好友' : item.relationship === 'pending_outbound' ? '已申请' : item.relationship === 'pending_inbound' ? '待通过' : item.relationship === 'blocked_by_me' ? '已拉黑' : item.relationship === 'blocked_by_peer' ? '无法添加' : '添加';
|
||||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||||
className: "people-page",
|
className: "people-page",
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Header, {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Header, {
|
||||||
@@ -12961,7 +12960,7 @@ function normalizeConversations(chatList, myUserId) {
|
|||||||
icon: isGroup ? 'group' : 'person',
|
icon: isGroup ? 'group' : 'person',
|
||||||
online: isGroup ? undefined : !!item.online,
|
online: isGroup ? undefined : !!item.online,
|
||||||
muted: !!(item.acs && item.acs.isMuted && item.acs.isMuted()),
|
muted: !!(item.acs && item.acs.isMuted && item.acs.isMuted()),
|
||||||
pinned: !!item.pinned
|
pinned: !!(item.private && item.private.pinned)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -21109,18 +21108,24 @@ function DailyReportList({
|
|||||||
const cacheKey = 'daily-reports:' + (team ? 'managed' : 'mine');
|
const cacheKey = 'daily-reports:' + (team ? 'managed' : 'mine');
|
||||||
const statsCacheKey = 'daily-stats:' + toDateInputValue(new Date());
|
const statsCacheKey = 'daily-stats:' + toDateInputValue(new Date());
|
||||||
const [reports, setReports] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)(cacheKey) || null);
|
const [reports, setReports] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)(cacheKey) || null);
|
||||||
|
const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
const [query, setQuery] = react__WEBPACK_IMPORTED_MODULE_0___default().useState('');
|
const [query, setQuery] = react__WEBPACK_IMPORTED_MODULE_0___default().useState('');
|
||||||
const [stats, setStats] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => team && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)(statsCacheKey) || null);
|
const [stats, setStats] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => team && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)(statsCacheKey) || null);
|
||||||
const ids = (reports || []).map(r => r.author_id);
|
const ids = (reports || []).map(r => r.author_id);
|
||||||
const names = useUserNames(ids, myUserId);
|
const names = useUserNames(ids, myUserId);
|
||||||
const load = () => {
|
const load = () => {
|
||||||
|
setLoadError(false);
|
||||||
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.getDailyReports)({
|
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.getDailyReports)({
|
||||||
scope: team ? 'managed' : 'mine'
|
scope: team ? 'managed' : 'mine'
|
||||||
}).then(d => {
|
}).then(d => {
|
||||||
const list = d.reports || d.items || [];
|
const list = d.reports || d.items || [];
|
||||||
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.writeCachedData)(cacheKey, list);
|
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.writeCachedData)(cacheKey, list);
|
||||||
setReports(list);
|
setReports(list);
|
||||||
}).catch(() => setReports(prev => prev || []));
|
}).catch(err => {
|
||||||
|
onToast(err.message || '日报列表加载失败');
|
||||||
|
setLoadError(true);
|
||||||
|
setReports(prev => prev || []);
|
||||||
|
});
|
||||||
if (team) (0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.getDailyStatistics)(toDateInputValue(new Date())).then(s => {
|
if (team) (0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.getDailyStatistics)(toDateInputValue(new Date())).then(s => {
|
||||||
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.writeCachedData)(statsCacheKey, s);
|
(0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.writeCachedData)(statsCacheKey, s);
|
||||||
setStats(s);
|
setStats(s);
|
||||||
@@ -21211,7 +21216,7 @@ function DailyReportList({
|
|||||||
children: "加载中…"
|
children: "加载中…"
|
||||||
}, void 0, false) : filtered.length === 0 ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
|
}, void 0, false) : filtered.length === 0 ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
|
||||||
className: "organization-loading",
|
className: "organization-loading",
|
||||||
children: "暂无日报"
|
children: loadError ? '日报列表加载失败' : '暂无日报'
|
||||||
}, void 0, false) : filtered.map(r => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(DailyReportCard, {
|
}, void 0, false) : filtered.map(r => (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(DailyReportCard, {
|
||||||
report: r,
|
report: r,
|
||||||
names: names,
|
names: names,
|
||||||
@@ -21311,6 +21316,7 @@ function MonthlyReportEditor({
|
|||||||
};
|
};
|
||||||
const [summary, setSummary] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(cached ? cached.summary : '');
|
const [summary, setSummary] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(cached ? cached.summary : '');
|
||||||
const [plan, setPlan] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(cached ? cached.plan : '');
|
const [plan, setPlan] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(cached ? cached.plan : '');
|
||||||
|
const [hydrated, setHydrated] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(!cached);
|
||||||
const [saved, setSaved] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
const [saved, setSaved] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
const [saveError, setSaveError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
const [saveError, setSaveError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
const [submitting, setSubmitting] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
const [submitting, setSubmitting] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
@@ -21353,17 +21359,18 @@ function MonthlyReportEditor({
|
|||||||
summary: nextSummary,
|
summary: nextSummary,
|
||||||
plan: nextPlan
|
plan: nextPlan
|
||||||
});
|
});
|
||||||
|
setHydrated(true);
|
||||||
}).catch(err => onToast(err.message || '创建月报失败'));
|
}).catch(err => onToast(err.message || '创建月报失败'));
|
||||||
}, []);
|
}, []);
|
||||||
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(() => {
|
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(() => {
|
||||||
if (!reportId) return undefined;
|
if (!reportId || !hydrated) return undefined;
|
||||||
setSaved(false);
|
setSaved(false);
|
||||||
draftTimerRef.current = window.setTimeout(() => {
|
draftTimerRef.current = window.setTimeout(() => {
|
||||||
draftTimerRef.current = null;
|
draftTimerRef.current = null;
|
||||||
saveDraft(summary, plan).catch(() => setSaveError(true));
|
saveDraft(summary, plan).catch(() => setSaveError(true));
|
||||||
}, 600);
|
}, 600);
|
||||||
return () => window.clearTimeout(draftTimerRef.current);
|
return () => window.clearTimeout(draftTimerRef.current);
|
||||||
}, [summary, plan, reportId, saveDraft]);
|
}, [summary, plan, reportId, hydrated, saveDraft]);
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!summary.trim() || !plan.trim()) {
|
if (!summary.trim() || !plan.trim()) {
|
||||||
onToast('请完成必填内容');
|
onToast('请完成必填内容');
|
||||||
@@ -21514,6 +21521,7 @@ function MonthlyReportDetail({
|
|||||||
const reportId = hashParams && hashParams.report_id;
|
const reportId = hashParams && hashParams.report_id;
|
||||||
const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('monthly-report:' + reportId) || null);
|
const [report, setReport] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(() => reportId && (0,_lib_use_cached_data_js__WEBPACK_IMPORTED_MODULE_4__.readCachedData)('monthly-report:' + reportId) || null);
|
||||||
const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
const [loadError, setLoadError] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
|
const [reopening, setReopening] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(false);
|
||||||
const names = useUserNames(report ? [report.author_id] : [], myUserId);
|
const names = useUserNames(report ? [report.author_id] : [], myUserId);
|
||||||
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(() => {
|
react__WEBPACK_IMPORTED_MODULE_0___default().useEffect(() => {
|
||||||
if (!reportId) return;
|
if (!reportId) return;
|
||||||
@@ -21538,6 +21546,14 @@ function MonthlyReportDetail({
|
|||||||
}, void 0, false)
|
}, void 0, false)
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true);
|
}, void 0, true);
|
||||||
|
const canReopen = report.author_id === myUserId && report.status === 'submitted';
|
||||||
|
const reopen = () => {
|
||||||
|
setReopening(true);
|
||||||
|
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.reopenMonthlyReport)(report.report_id, report.version).then(() => {
|
||||||
|
onToast('已重新打开,可继续编辑');
|
||||||
|
navigate('monthly-report-editor');
|
||||||
|
}).catch(err => onToast(err.message || '重新打开失败')).finally(() => setReopening(false));
|
||||||
|
};
|
||||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("div", {
|
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("div", {
|
||||||
className: "workplace-page",
|
className: "workplace-page",
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Header, {
|
||||||
@@ -21576,7 +21592,15 @@ function MonthlyReportDetail({
|
|||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("p", {
|
||||||
children: report.next_plan || '未填写'
|
children: report.next_plan || '未填写'
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true)]
|
}, void 0, true), canReopen ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("section", {
|
||||||
|
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||||
|
type: "button",
|
||||||
|
className: "workplace-primary",
|
||||||
|
disabled: reopening,
|
||||||
|
onClick: reopen,
|
||||||
|
children: reopening ? '处理中…' : '重新编辑'
|
||||||
|
}, void 0, false)
|
||||||
|
}, void 0, false) : null]
|
||||||
}, void 0, true)]
|
}, void 0, true)]
|
||||||
}, void 0, true);
|
}, void 0, true);
|
||||||
}
|
}
|
||||||
@@ -21605,11 +21629,23 @@ function ExecutiveMailbox({
|
|||||||
enabled: false
|
enabled: false
|
||||||
}));
|
}));
|
||||||
}, []);
|
}, []);
|
||||||
const pickFile = () => fileInputRef.current && fileInputRef.current.click();
|
const attachmentPolicy = config && config.attachment_policy || {};
|
||||||
|
const maxFiles = attachmentPolicy.max_files || attachmentPolicy.max_count || 5;
|
||||||
|
const pickFile = () => {
|
||||||
|
if (attachments.length >= maxFiles) {
|
||||||
|
onToast(`最多上传 ${maxFiles} 个附件`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileInputRef.current && fileInputRef.current.click();
|
||||||
|
};
|
||||||
const handleFile = event => {
|
const handleFile = event => {
|
||||||
const file = event.target.files && event.target.files[0];
|
const file = event.target.files && event.target.files[0];
|
||||||
event.target.value = '';
|
event.target.value = '';
|
||||||
if (!file || !tinode) return;
|
if (!file || !tinode) return;
|
||||||
|
if (attachments.length >= maxFiles) {
|
||||||
|
onToast(`最多上传 ${maxFiles} 个附件`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setUploading(true);
|
setUploading(true);
|
||||||
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.uploadLargeFile)(tinode, file).then(({
|
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_3__.uploadLargeFile)(tinode, file).then(({
|
||||||
fileId
|
fileId
|
||||||
@@ -21678,12 +21714,12 @@ function ExecutiveMailbox({
|
|||||||
children: [content.length, "/", config && config.max_length || 1000]
|
children: [content.length, "/", config && config.max_length || 1000]
|
||||||
}, void 0, true)]
|
}, void 0, true)]
|
||||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
|
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
|
||||||
children: "附件"
|
children: ["附件(", attachments.length, "/", maxFiles, ")"]
|
||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("button", {
|
||||||
type: "button",
|
type: "button",
|
||||||
className: "mailbox-upload",
|
className: "mailbox-upload",
|
||||||
onClick: pickFile,
|
onClick: pickFile,
|
||||||
disabled: uploading,
|
disabled: uploading || attachments.length >= maxFiles,
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Icon, {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)(Icon, {
|
||||||
children: uploading ? 'hourglass_top' : 'upload_file'
|
children: uploading ? 'hourglass_top' : 'upload_file'
|
||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxDEV)("span", {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user