导出功能调整
parent
b3f85504f6
commit
ab711362c7
|
|
@ -24,30 +24,30 @@
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"RequestMappingsPanelOrder0": "0",
|
"RequestMappingsPanelOrder0": "0",
|
||||||
"RequestMappingsPanelOrder1": "1",
|
"RequestMappingsPanelOrder1": "1",
|
||||||
"RequestMappingsPanelWidth0": "75",
|
"RequestMappingsPanelWidth0": "75",
|
||||||
"RequestMappingsPanelWidth1": "75",
|
"RequestMappingsPanelWidth1": "75",
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"WebServerToolWindowFactoryState": "false",
|
"WebServerToolWindowFactoryState": "false",
|
||||||
"git-widget-placeholder": "main",
|
"git-widget-placeholder": "main",
|
||||||
"last_opened_file_path": "/Users/kangwenjing/Downloads/crm/unis_crm",
|
"last_opened_file_path": "/Users/kangwenjing/Downloads/crm/unis_crm",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"project.structure.last.edited": "项目",
|
"project.structure.last.edited": "项目",
|
||||||
"project.structure.proportion": "0.14450866",
|
"project.structure.proportion": "0.14450866",
|
||||||
"project.structure.side.proportion": "0.18800648",
|
"project.structure.side.proportion": "0.18800648",
|
||||||
"settings.editor.selected.configurable": "configurable.group.appearance",
|
"settings.editor.selected.configurable": "configurable.group.appearance",
|
||||||
"ts.external.directory.path": "/Users/kangwenjing/Downloads/crm/unis_crm/frontend/node_modules/typescript/lib",
|
"ts.external.directory.path": "/Users/kangwenjing/Downloads/crm/unis_crm/frontend/node_modules/typescript/lib",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RunManager" selected="Spring Boot.UnisCrmBackendApplication">
|
<component name="RunManager" selected="Spring Boot.UnisCrmBackendApplication">
|
||||||
<configuration name="unis-crm-backend中的所有" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
<configuration name="unis-crm-backend中的所有" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||||
<module name="unis-crm-backend" />
|
<module name="unis-crm-backend" />
|
||||||
|
|
@ -94,6 +94,8 @@
|
||||||
<workItem from="1775541962012" duration="805000" />
|
<workItem from="1775541962012" duration="805000" />
|
||||||
<workItem from="1775611219527" duration="1273000" />
|
<workItem from="1775611219527" duration="1273000" />
|
||||||
<workItem from="1775721940000" duration="8576000" />
|
<workItem from="1775721940000" duration="8576000" />
|
||||||
|
<workItem from="1776219416113" duration="650000" />
|
||||||
|
<workItem from="1776238420843" duration="21000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="修改定位信息 0323">
|
<task id="LOCAL-00001" summary="修改定位信息 0323">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ public class ChannelExpansionItemDTO {
|
||||||
private String stage;
|
private String stage;
|
||||||
private Boolean landed;
|
private Boolean landed;
|
||||||
private String expectedSignDate;
|
private String expectedSignDate;
|
||||||
|
private String updatedAt;
|
||||||
private String notes;
|
private String notes;
|
||||||
private List<ChannelExpansionContactDTO> contacts = new ArrayList<>();
|
private List<ChannelExpansionContactDTO> contacts = new ArrayList<>();
|
||||||
private List<ChannelRelatedProjectSummaryDTO> relatedProjects = new ArrayList<>();
|
private List<ChannelRelatedProjectSummaryDTO> relatedProjects = new ArrayList<>();
|
||||||
|
|
@ -298,6 +299,14 @@ public class ChannelExpansionItemDTO {
|
||||||
this.expectedSignDate = expectedSignDate;
|
this.expectedSignDate = expectedSignDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(String updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
public String getNotes() {
|
public String getNotes() {
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ public class SalesExpansionItemDTO {
|
||||||
private Boolean active;
|
private Boolean active;
|
||||||
private String employmentStatus;
|
private String employmentStatus;
|
||||||
private String expectedJoinDate;
|
private String expectedJoinDate;
|
||||||
|
private String updatedAt;
|
||||||
private String notes;
|
private String notes;
|
||||||
private java.util.List<RelatedProjectSummaryDTO> relatedProjects = new java.util.ArrayList<>();
|
private java.util.List<RelatedProjectSummaryDTO> relatedProjects = new java.util.ArrayList<>();
|
||||||
private List<ExpansionFollowUpDTO> followUps = new ArrayList<>();
|
private List<ExpansionFollowUpDTO> followUps = new ArrayList<>();
|
||||||
|
|
@ -225,6 +226,14 @@ public class SalesExpansionItemDTO {
|
||||||
this.expectedJoinDate = expectedJoinDate;
|
this.expectedJoinDate = expectedJoinDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(String updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
public String getNotes() {
|
public String getNotes() {
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ public class OpportunityItemDTO {
|
||||||
private String name;
|
private String name;
|
||||||
private String client;
|
private String client;
|
||||||
private String owner;
|
private String owner;
|
||||||
|
private String updatedAt;
|
||||||
private String projectLocation;
|
private String projectLocation;
|
||||||
private String operatorCode;
|
private String operatorCode;
|
||||||
private String operatorName;
|
private String operatorName;
|
||||||
|
|
@ -85,6 +86,14 @@ public class OpportunityItemDTO {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(String updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
public String getProjectLocation() {
|
public String getProjectLocation() {
|
||||||
return projectLocation;
|
return projectLocation;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ public class OpportunitySearchToolProvider extends PermissionedMcpToolProvider {
|
||||||
properties.put("keyword", stringProperty("关键词,匹配商机名称、编号、客户名称、项目地点、产品类型。"));
|
properties.put("keyword", stringProperty("关键词,匹配商机名称、编号、客户名称、项目地点、产品类型。"));
|
||||||
properties.put("stage", stringProperty("商机阶段编码,例如 initial_contact/solution_discussion/bidding/business_negotiation/won/lost。"));
|
properties.put("stage", stringProperty("商机阶段编码,例如 initial_contact/solution_discussion/bidding/business_negotiation/won/lost。"));
|
||||||
properties.put("ownerUserId", integerProperty("商机负责人用户 ID,实际可见范围仍按系统数据权限裁剪。"));
|
properties.put("ownerUserId", integerProperty("商机负责人用户 ID,实际可见范围仍按系统数据权限裁剪。"));
|
||||||
properties.put("includeArchived", booleanProperty("是否包含已归档商机,默认 false。"));
|
properties.put("includeArchived", booleanProperty("是否包含已签单商机,默认 false。"));
|
||||||
properties.put("page", integerProperty("页码,默认 1。"));
|
properties.put("page", integerProperty("页码,默认 1。"));
|
||||||
properties.put("pageSize", integerProperty("每页条数,默认 10,最大 50。"));
|
properties.put("pageSize", integerProperty("每页条数,默认 10,最大 50。"));
|
||||||
properties.put("limit", integerProperty("返回条数,默认 10,最大 50。"));
|
properties.put("limit", integerProperty("返回条数,默认 10,最大 50。"));
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,26 @@
|
||||||
(s.employment_status = 'active') as active,
|
(s.employment_status = 'active') as active,
|
||||||
s.employment_status as employmentStatus,
|
s.employment_status as employmentStatus,
|
||||||
coalesce(to_char(s.expected_join_date, 'YYYY-MM-DD'), '无') as expectedJoinDate,
|
coalesce(to_char(s.expected_join_date, 'YYYY-MM-DD'), '无') as expectedJoinDate,
|
||||||
|
coalesce(
|
||||||
|
to_char(
|
||||||
|
case
|
||||||
|
when sales_followup.latest_followup_time is null then s.updated_at
|
||||||
|
else greatest(s.updated_at, sales_followup.latest_followup_time)
|
||||||
|
end,
|
||||||
|
'YYYY-MM-DD HH24:MI'
|
||||||
|
),
|
||||||
|
'无'
|
||||||
|
) as updatedAt,
|
||||||
coalesce(s.remark, '无') as notes
|
coalesce(s.remark, '无') as notes
|
||||||
from crm_sales_expansion s
|
from crm_sales_expansion s
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
f.biz_id,
|
||||||
|
max(f.followup_time) as latest_followup_time
|
||||||
|
from crm_expansion_followup f
|
||||||
|
where f.biz_type = 'sales'
|
||||||
|
group by f.biz_id
|
||||||
|
) sales_followup on sales_followup.biz_id = s.id
|
||||||
left join sys_user u
|
left join sys_user u
|
||||||
on u.user_id = s.owner_user_id
|
on u.user_id = s.owner_user_id
|
||||||
and u.is_deleted = 0
|
and u.is_deleted = 0
|
||||||
|
|
@ -168,8 +186,26 @@
|
||||||
end as stage,
|
end as stage,
|
||||||
c.landed_flag as landed,
|
c.landed_flag as landed,
|
||||||
coalesce(to_char(c.expected_sign_date, 'YYYY-MM-DD'), '无') as expectedSignDate,
|
coalesce(to_char(c.expected_sign_date, 'YYYY-MM-DD'), '无') as expectedSignDate,
|
||||||
|
coalesce(
|
||||||
|
to_char(
|
||||||
|
case
|
||||||
|
when channel_followup.latest_followup_time is null then c.updated_at
|
||||||
|
else greatest(c.updated_at, channel_followup.latest_followup_time)
|
||||||
|
end,
|
||||||
|
'YYYY-MM-DD HH24:MI'
|
||||||
|
),
|
||||||
|
'无'
|
||||||
|
) as updatedAt,
|
||||||
coalesce(c.remark, '无') as notes
|
coalesce(c.remark, '无') as notes
|
||||||
from crm_channel_expansion c
|
from crm_channel_expansion c
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
f.biz_id,
|
||||||
|
max(f.followup_time) as latest_followup_time
|
||||||
|
from crm_expansion_followup f
|
||||||
|
where f.biz_type = 'channel'
|
||||||
|
group by f.biz_id
|
||||||
|
) channel_followup on channel_followup.biz_id = c.id
|
||||||
left join sys_user u
|
left join sys_user u
|
||||||
on u.user_id = c.owner_user_id
|
on u.user_id = c.owner_user_id
|
||||||
and u.is_deleted = 0
|
and u.is_deleted = 0
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,16 @@
|
||||||
o.opportunity_name as name,
|
o.opportunity_name as name,
|
||||||
coalesce(c.customer_name, '未填写最终客户') as client,
|
coalesce(c.customer_name, '未填写最终客户') as client,
|
||||||
coalesce(u.display_name, '当前用户') as owner,
|
coalesce(u.display_name, '当前用户') as owner,
|
||||||
|
coalesce(
|
||||||
|
to_char(
|
||||||
|
case
|
||||||
|
when opportunity_followup.latest_followup_time is null then o.updated_at
|
||||||
|
else greatest(o.updated_at, opportunity_followup.latest_followup_time)
|
||||||
|
end,
|
||||||
|
'YYYY-MM-DD HH24:MI'
|
||||||
|
),
|
||||||
|
'无'
|
||||||
|
) as updatedAt,
|
||||||
coalesce(o.project_location, '') as projectLocation,
|
coalesce(o.project_location, '') as projectLocation,
|
||||||
coalesce(operator_dict.item_value, o.operator_name, '') as operatorCode,
|
coalesce(operator_dict.item_value, o.operator_name, '') as operatorCode,
|
||||||
coalesce(operator_dict.item_label, nullif(o.operator_name, ''), '') as operatorName,
|
coalesce(operator_dict.item_label, nullif(o.operator_name, ''), '') as operatorName,
|
||||||
|
|
@ -117,6 +127,13 @@
|
||||||
), '') as nextPlan,
|
), '') as nextPlan,
|
||||||
coalesce(o.description, '') as notes
|
coalesce(o.description, '') as notes
|
||||||
from crm_opportunity o
|
from crm_opportunity o
|
||||||
|
left join (
|
||||||
|
select
|
||||||
|
f.opportunity_id,
|
||||||
|
max(f.followup_time) as latest_followup_time
|
||||||
|
from crm_opportunity_followup f
|
||||||
|
group by f.opportunity_id
|
||||||
|
) opportunity_followup on opportunity_followup.opportunity_id = o.id
|
||||||
left join crm_customer c on c.id = o.customer_id
|
left join crm_customer c on c.id = o.customer_id
|
||||||
left join sys_user u on u.user_id = o.owner_user_id
|
left join sys_user u on u.user_id = o.owner_user_id
|
||||||
left join crm_sales_expansion se on se.id = o.sales_expansion_id
|
left join crm_sales_expansion se on se.id = o.sales_expansion_id
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,7 @@ flowchart TD
|
||||||
|
|
||||||
建议对以下数据建立归档策略:
|
建议对以下数据建立归档策略:
|
||||||
|
|
||||||
- 已归档商机
|
- 已签单商机
|
||||||
- 早期历史动态日志
|
- 早期历史动态日志
|
||||||
- 历史打卡照片
|
- 历史打卡照片
|
||||||
- 大体量日报附件或冗余快照
|
- 大体量日报附件或冗余快照
|
||||||
|
|
@ -638,4 +638,3 @@ flowchart TD
|
||||||
- `docs/opportunity-integration-api.md`
|
- `docs/opportunity-integration-api.md`
|
||||||
- `backend/README.md`
|
- `backend/README.md`
|
||||||
- `frontend/README.md`
|
- `frontend/README.md`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,8 +291,8 @@ const opportunityOverview = {
|
||||||
amount: 530000,
|
amount: 530000,
|
||||||
date: "2026-03-18",
|
date: "2026-03-18",
|
||||||
confidence: "C",
|
confidence: "C",
|
||||||
stageCode: "已归档",
|
stageCode: "已签单",
|
||||||
stage: "已归档",
|
stage: "已签单",
|
||||||
type: "替换",
|
type: "替换",
|
||||||
archived: true,
|
archived: true,
|
||||||
pushedToOms: false,
|
pushedToOms: false,
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,7 @@ export interface OpportunityItem {
|
||||||
name?: string;
|
name?: string;
|
||||||
client?: string;
|
client?: string;
|
||||||
owner?: string;
|
owner?: string;
|
||||||
|
updatedAt?: string;
|
||||||
projectLocation?: string;
|
projectLocation?: string;
|
||||||
operatorCode?: string;
|
operatorCode?: string;
|
||||||
operatorName?: string;
|
operatorName?: string;
|
||||||
|
|
@ -339,6 +340,7 @@ export interface OpportunityMeta {
|
||||||
operatorOptions?: OpportunityDictOption[];
|
operatorOptions?: OpportunityDictOption[];
|
||||||
projectLocationOptions?: OpportunityDictOption[];
|
projectLocationOptions?: OpportunityDictOption[];
|
||||||
opportunityTypeOptions?: OpportunityDictOption[];
|
opportunityTypeOptions?: OpportunityDictOption[];
|
||||||
|
confidenceOptions?: OpportunityDictOption[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OmsPreSalesOption {
|
export interface OmsPreSalesOption {
|
||||||
|
|
@ -416,6 +418,7 @@ export interface SalesExpansionItem {
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
employmentStatus?: string;
|
employmentStatus?: string;
|
||||||
expectedJoinDate?: string;
|
expectedJoinDate?: string;
|
||||||
|
updatedAt?: string;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
relatedProjects?: RelatedProjectSummary[];
|
relatedProjects?: RelatedProjectSummary[];
|
||||||
followUps?: ExpansionFollowUp[];
|
followUps?: ExpansionFollowUp[];
|
||||||
|
|
@ -461,6 +464,7 @@ export interface ChannelExpansionItem {
|
||||||
stage?: string;
|
stage?: string;
|
||||||
landed?: boolean;
|
landed?: boolean;
|
||||||
expectedSignDate?: string;
|
expectedSignDate?: string;
|
||||||
|
updatedAt?: string;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
contacts?: ChannelExpansionContact[];
|
contacts?: ChannelExpansionContact[];
|
||||||
relatedProjects?: ChannelRelatedProjectSummary[];
|
relatedProjects?: ChannelRelatedProjectSummary[];
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,7 @@ function buildSalesExportHeaders(items: SalesExpansionItem[]) {
|
||||||
"工号",
|
"工号",
|
||||||
"姓名",
|
"姓名",
|
||||||
"创建人",
|
"创建人",
|
||||||
|
"更新修改时间",
|
||||||
"联系方式",
|
"联系方式",
|
||||||
"代表处 / 办事处",
|
"代表处 / 办事处",
|
||||||
"所属部门",
|
"所属部门",
|
||||||
|
|
@ -357,6 +358,7 @@ function buildSalesExportData(items: SalesExpansionItem[]) {
|
||||||
normalizeExportText(item.employeeNo),
|
normalizeExportText(item.employeeNo),
|
||||||
normalizeExportText(item.name),
|
normalizeExportText(item.name),
|
||||||
normalizeExportText(item.owner),
|
normalizeExportText(item.owner),
|
||||||
|
normalizeExportText(item.updatedAt),
|
||||||
normalizeExportText(item.phone),
|
normalizeExportText(item.phone),
|
||||||
normalizeExportText(item.officeName),
|
normalizeExportText(item.officeName),
|
||||||
normalizeExportText(item.dept),
|
normalizeExportText(item.dept),
|
||||||
|
|
@ -389,6 +391,7 @@ function buildChannelExportHeaders(items: ChannelExpansionItem[]) {
|
||||||
"编码",
|
"编码",
|
||||||
"渠道名称",
|
"渠道名称",
|
||||||
"创建人",
|
"创建人",
|
||||||
|
"更新修改时间",
|
||||||
"省份",
|
"省份",
|
||||||
"市",
|
"市",
|
||||||
"办公地址",
|
"办公地址",
|
||||||
|
|
@ -426,6 +429,7 @@ function buildChannelExportData(items: ChannelExpansionItem[]) {
|
||||||
normalizeExportText(item.channelCode),
|
normalizeExportText(item.channelCode),
|
||||||
normalizeExportText(item.name),
|
normalizeExportText(item.name),
|
||||||
normalizeExportText(item.owner),
|
normalizeExportText(item.owner),
|
||||||
|
normalizeExportText(item.updatedAt),
|
||||||
normalizeExportText(item.province),
|
normalizeExportText(item.province),
|
||||||
normalizeExportText(item.city),
|
normalizeExportText(item.city),
|
||||||
normalizeExportText(item.officeAddress),
|
normalizeExportText(item.officeAddress),
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,13 @@ function formatAmount(value?: number) {
|
||||||
return new Intl.NumberFormat("zh-CN").format(Number(value));
|
return new Intl.NumberFormat("zh-CN").format(Number(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatOpportunityBoolean(value?: boolean, trueLabel = "是", falseLabel = "否") {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return value ? trueLabel : falseLabel;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeOpportunityExportText(value?: string | number | boolean | null) {
|
function normalizeOpportunityExportText(value?: string | number | boolean | null) {
|
||||||
if (value === null || value === undefined) {
|
if (value === null || value === undefined) {
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -648,8 +655,8 @@ function OpportunityExportFilterModal({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalShell
|
<ModalShell
|
||||||
title={`导出${archiveTab === "active" ? "未归档" : "已归档"}商机`}
|
title={`导出${archiveTab === "active" ? "未签单" : "已签单"}商机`}
|
||||||
subtitle="选择条件后导出 Excel;不填条件则导出当前归档页签下的全部可见商机。"
|
subtitle="选择条件后导出 Excel;不填条件则导出当前签单页签下的全部可见商机。"
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
footer={(
|
footer={(
|
||||||
<div className="flex flex-col-reverse gap-3 sm:flex-row sm:justify-between">
|
<div className="flex flex-col-reverse gap-3 sm:flex-row sm:justify-between">
|
||||||
|
|
@ -1603,7 +1610,7 @@ export default function Opportunities() {
|
||||||
.filter((item) => (archiveTab === "active" ? !item.archived : Boolean(item.archived)))
|
.filter((item) => (archiveTab === "active" ? !item.archived : Boolean(item.archived)))
|
||||||
.filter((item) => matchesOpportunityExportFilters(item, filters, effectiveConfidenceOptions));
|
.filter((item) => matchesOpportunityExportFilters(item, filters, effectiveConfidenceOptions));
|
||||||
if (exportItems.length <= 0) {
|
if (exportItems.length <= 0) {
|
||||||
throw new Error(`当前筛选条件下暂无可导出的${archiveTab === "active" ? "未归档" : "已归档"}商机`);
|
throw new Error(`当前筛选条件下暂无可导出的${archiveTab === "active" ? "未签单" : "已签单"}商机`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExcelJS = await import("exceljs");
|
const ExcelJS = await import("exceljs");
|
||||||
|
|
@ -1613,6 +1620,9 @@ export default function Opportunities() {
|
||||||
"项目编号",
|
"项目编号",
|
||||||
"项目名称",
|
"项目名称",
|
||||||
"创建人",
|
"创建人",
|
||||||
|
"更新修改时间",
|
||||||
|
"是否签单",
|
||||||
|
"是否推送OMS",
|
||||||
"项目地",
|
"项目地",
|
||||||
"最终用户",
|
"最终用户",
|
||||||
"建设类型",
|
"建设类型",
|
||||||
|
|
@ -1661,6 +1671,9 @@ export default function Opportunities() {
|
||||||
normalizeOpportunityExportText(item.code),
|
normalizeOpportunityExportText(item.code),
|
||||||
normalizeOpportunityExportText(item.name),
|
normalizeOpportunityExportText(item.name),
|
||||||
normalizeOpportunityExportText(item.owner),
|
normalizeOpportunityExportText(item.owner),
|
||||||
|
normalizeOpportunityExportText(item.updatedAt),
|
||||||
|
formatOpportunityBoolean(item.archived, "已签单", "未签单"),
|
||||||
|
formatOpportunityBoolean(item.pushedToOms, "已推送", "未推送"),
|
||||||
normalizeOpportunityExportText(item.projectLocation),
|
normalizeOpportunityExportText(item.projectLocation),
|
||||||
normalizeOpportunityExportText(item.client),
|
normalizeOpportunityExportText(item.client),
|
||||||
normalizeOpportunityExportText(item.type || "新建"),
|
normalizeOpportunityExportText(item.type || "新建"),
|
||||||
|
|
@ -1726,7 +1739,7 @@ export default function Opportunities() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
const buffer = await workbook.xlsx.writeBuffer();
|
||||||
const filename = `商机储备_${archiveTab === "active" ? "未归档" : "已归档"}_${formatOpportunityExportFilenameTime()}.xlsx`;
|
const filename = `商机储备_${archiveTab === "active" ? "未签单" : "已签单"}_${formatOpportunityExportFilenameTime()}.xlsx`;
|
||||||
downloadOpportunityExcelFile(filename, buffer);
|
downloadOpportunityExcelFile(filename, buffer);
|
||||||
setExportFilterOpen(false);
|
setExportFilterOpen(false);
|
||||||
} catch (exportErr) {
|
} catch (exportErr) {
|
||||||
|
|
@ -1943,7 +1956,7 @@ export default function Opportunities() {
|
||||||
|
|
||||||
const renderEmpty = () => (
|
const renderEmpty = () => (
|
||||||
<div className="crm-empty-panel">
|
<div className="crm-empty-panel">
|
||||||
{archiveTab === "active" ? "暂无未归档商机,先新增一条试试。" : "暂无已归档商机。"}
|
{archiveTab === "active" ? "暂无未签单商机,先新增一条试试。" : "暂无已签单商机。"}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1987,7 +2000,7 @@ export default function Opportunities() {
|
||||||
: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
|
: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
未归档
|
未签单
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -2000,7 +2013,7 @@ export default function Opportunities() {
|
||||||
: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
|
: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
已归档
|
已签单
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue