20260719215738
This commit is contained in:
1 parent
35aa108a34
commit
cda7f16d3a
116 files changed
+11826
-3669
No files matched your search
@@ -1,134 +0,0 @@
|
||||
export const mockRecords = [
|
||||
{
|
||||
id: "FY-2026-0001",
|
||||
name: "华东区域运费结算",
|
||||
state: "草稿",
|
||||
customer: "华东客户中心",
|
||||
businessType: "海运",
|
||||
owner: "张三",
|
||||
amount: "4,960.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-16 09:20",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0002",
|
||||
name: "华南客户月度账单",
|
||||
state: "处理中",
|
||||
customer: "华南供应链有限公司",
|
||||
businessType: "空运",
|
||||
owner: "李四",
|
||||
amount: "6,240.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-16 08:45",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0003",
|
||||
name: "北方港口代理费用",
|
||||
state: "已完成",
|
||||
customer: "北方港口服务公司",
|
||||
businessType: "陆运",
|
||||
owner: "王五",
|
||||
amount: "7,520.00",
|
||||
currency: "USD",
|
||||
updated_at: "2026-07-15 17:32",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0004",
|
||||
name: "国际空运服务费",
|
||||
state: "处理中",
|
||||
customer: "国际物流有限公司",
|
||||
businessType: "空运",
|
||||
owner: "张三",
|
||||
amount: "8,800.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-15 16:10",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0005",
|
||||
name: "出口报关服务费用",
|
||||
state: "已完成",
|
||||
customer: "远洋贸易有限公司",
|
||||
businessType: "海运",
|
||||
owner: "李四",
|
||||
amount: "10,080.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-15 14:56",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0006",
|
||||
name: "华中干线运输费用",
|
||||
state: "草稿",
|
||||
customer: "华中运输服务公司",
|
||||
businessType: "陆运",
|
||||
owner: "王五",
|
||||
amount: "11,360.00",
|
||||
currency: "USD",
|
||||
updated_at: "2026-07-15 11:24",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0007",
|
||||
name: "仓储增值服务结算",
|
||||
state: "已取消",
|
||||
customer: "城市仓储有限公司",
|
||||
businessType: "铁路",
|
||||
owner: "张三",
|
||||
amount: "12,640.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-14 18:05",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0008",
|
||||
name: "跨境电商物流账单",
|
||||
state: "已完成",
|
||||
customer: "跨境电商有限公司",
|
||||
businessType: "空运",
|
||||
owner: "李四",
|
||||
amount: "13,920.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-14 15:40",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0009",
|
||||
name: "西南区域配送费用",
|
||||
state: "处理中",
|
||||
customer: "西南配送服务中心",
|
||||
businessType: "陆运",
|
||||
owner: "王五",
|
||||
amount: "15,200.00",
|
||||
currency: "USD",
|
||||
updated_at: "2026-07-14 13:18",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0010",
|
||||
name: "危险品运输服务费",
|
||||
state: "草稿",
|
||||
customer: "特种运输有限公司",
|
||||
businessType: "海运",
|
||||
owner: "张三",
|
||||
amount: "16,480.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-14 10:02",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0011",
|
||||
name: "铁路联运代理费用",
|
||||
state: "已完成",
|
||||
customer: "铁路联运服务公司",
|
||||
businessType: "铁路",
|
||||
owner: "李四",
|
||||
amount: "17,760.00",
|
||||
currency: "CNY",
|
||||
updated_at: "2026-07-13 16:27",
|
||||
},
|
||||
{
|
||||
id: "FY-2026-0012",
|
||||
name: "客户临时加急费用",
|
||||
state: "已取消",
|
||||
customer: "重点客户服务中心",
|
||||
businessType: "空运",
|
||||
owner: "王五",
|
||||
amount: "19,040.00",
|
||||
currency: "USD",
|
||||
updated_at: "2026-07-13 09:51",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,668 @@
|
||||
/**
|
||||
* 模块管理 Demo 数据。
|
||||
*
|
||||
* 设计边界:
|
||||
* - 模块配置服务于通用数据接口和标准 ModuleTable / ModuleForm。
|
||||
* - 字段配置标准字段的显隐、必填、类型、字典与顺序,不定义页面整体布局。
|
||||
* - 菜单由模块树中启用页面能力的模块投影,不单独维护菜单数据。
|
||||
* - 权限仅用于前端菜单、路由和操作控制。
|
||||
*/
|
||||
|
||||
export const localeOptions = [
|
||||
{ label: "简体中文", value: "zh-CN" },
|
||||
{ label: "English", value: "en-US" },
|
||||
{ label: "繁體中文", value: "zh-TW" },
|
||||
];
|
||||
|
||||
export const roles = [
|
||||
{ id: "admin", name: "系统管理员" },
|
||||
{ id: "operator", name: "业务操作员" },
|
||||
{ id: "finance", name: "财务人员" },
|
||||
{ id: "guest", name: "只读访客" },
|
||||
];
|
||||
|
||||
export const fieldTypeOptions = [
|
||||
{ label: "单行文本", value: "string" },
|
||||
{ label: "多行文本", value: "text" },
|
||||
{ label: "数字", value: "number" },
|
||||
{ label: "字典选择", value: "select" },
|
||||
{ label: "日期", value: "date" },
|
||||
{ label: "开关", value: "boolean" },
|
||||
];
|
||||
|
||||
export const dictionaryOptions = [
|
||||
{ label: "业务类型", value: "BIZ_TYPE" },
|
||||
{ label: "业务状态", value: "BIZ_STATUS" },
|
||||
{ label: "用户状态", value: "USER_STATUS" },
|
||||
{ label: "币种", value: "CURRENCY" },
|
||||
];
|
||||
|
||||
export const dictionaries = {
|
||||
BIZ_TYPE: [
|
||||
{ value: "SEA", i18nKey: "dict.BIZ_TYPE.SEA" },
|
||||
{ value: "AIR", i18nKey: "dict.BIZ_TYPE.AIR" },
|
||||
],
|
||||
BIZ_STATUS: [
|
||||
{ value: "DRAFT", i18nKey: "dict.BIZ_STATUS.DRAFT" },
|
||||
{ value: "SUBMITTED", i18nKey: "dict.BIZ_STATUS.SUBMITTED" },
|
||||
{ value: "APPROVED", i18nKey: "dict.BIZ_STATUS.APPROVED" },
|
||||
],
|
||||
USER_STATUS: [
|
||||
{ value: "ENABLED", i18nKey: "dict.USER_STATUS.ENABLED" },
|
||||
{ value: "DISABLED", i18nKey: "dict.USER_STATUS.DISABLED" },
|
||||
],
|
||||
CURRENCY: [
|
||||
{ value: "CNY", i18nKey: "dict.CURRENCY.CNY" },
|
||||
{ value: "USD", i18nKey: "dict.CURRENCY.USD" },
|
||||
{ value: "EUR", i18nKey: "dict.CURRENCY.EUR" },
|
||||
],
|
||||
};
|
||||
|
||||
export const modules = {
|
||||
M_SYSTEM: {
|
||||
code: "M_SYSTEM",
|
||||
parentId: null,
|
||||
sort: 10,
|
||||
i18nKey: "module.M_SYSTEM",
|
||||
isDirectory: true,
|
||||
isPage: false,
|
||||
route: "",
|
||||
showInMenu: true,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [],
|
||||
sampleRows: [],
|
||||
},
|
||||
|
||||
M_MODULE: {
|
||||
code: "M_MODULE",
|
||||
parentId: "M_SYSTEM",
|
||||
sort: 10,
|
||||
i18nKey: "module.M_MODULE",
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/demo/modules",
|
||||
showInMenu: true,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [{ code: "view", name: "查看" }],
|
||||
sampleRows: [{}],
|
||||
},
|
||||
|
||||
M_BUSINESS: {
|
||||
code: "M_BUSINESS",
|
||||
parentId: null,
|
||||
sort: 20,
|
||||
i18nKey: "module.M_BUSINESS",
|
||||
isDirectory: true,
|
||||
isPage: false,
|
||||
route: "",
|
||||
showInMenu: true,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [],
|
||||
sampleRows: [],
|
||||
},
|
||||
|
||||
M_BIZ: {
|
||||
code: "M_BIZ",
|
||||
i18nKey: "module.M_BIZ",
|
||||
parentId: "M_BUSINESS",
|
||||
sort: 10,
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/business/orders",
|
||||
showInMenu: true,
|
||||
querySource: "v_bs_business",
|
||||
saveTarget: "b_business",
|
||||
primaryKey: "b_id",
|
||||
defaultOrder: "b_id DESC",
|
||||
enabled: true,
|
||||
fields: [
|
||||
{
|
||||
id: "F_BIZ_NO",
|
||||
code: "b_ywno",
|
||||
i18nKey: "field.M_BIZ.b_ywno",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 10,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_CUSTOMER",
|
||||
code: "b_customer",
|
||||
i18nKey: "field.M_BIZ.b_customer",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 20,
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_TYPE",
|
||||
code: "b_type",
|
||||
i18nKey: "field.M_BIZ.b_type",
|
||||
dataType: "select",
|
||||
dictionaryCode: "BIZ_TYPE",
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 30,
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_AMOUNT",
|
||||
code: "b_amount",
|
||||
i18nKey: "field.M_BIZ.b_amount",
|
||||
dataType: "number",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: false,
|
||||
queryable: true,
|
||||
sort: 40,
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_STATUS",
|
||||
code: "b_state",
|
||||
i18nKey: "field.M_BIZ.b_state",
|
||||
dataType: "select",
|
||||
dictionaryCode: "BIZ_STATUS",
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 50,
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_REMARK",
|
||||
code: "b_remark",
|
||||
i18nKey: "field.M_BIZ.b_remark",
|
||||
dataType: "text",
|
||||
dictionaryCode: null,
|
||||
showInList: false,
|
||||
showInForm: true,
|
||||
required: false,
|
||||
queryable: false,
|
||||
sort: 60,
|
||||
width: 180,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "create", name: "新增" },
|
||||
{ code: "update", name: "修改" },
|
||||
{ code: "delete", name: "删除" },
|
||||
{ code: "submit", name: "提交" },
|
||||
{ code: "audit", name: "审核" },
|
||||
{ code: "export", name: "导出" },
|
||||
],
|
||||
sampleRows: [
|
||||
{
|
||||
b_id: "10001",
|
||||
b_ywno: "SE-2026-0719",
|
||||
b_customer: "远海贸易",
|
||||
b_type: "SEA",
|
||||
b_amount: 128600,
|
||||
b_state: "SUBMITTED",
|
||||
b_remark: "等待审核",
|
||||
},
|
||||
{
|
||||
b_id: "10002",
|
||||
b_ywno: "AE-2026-0720",
|
||||
b_customer: "华东供应链",
|
||||
b_type: "AIR",
|
||||
b_amount: 35600,
|
||||
b_state: "DRAFT",
|
||||
b_remark: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
M_USER: {
|
||||
code: "M_USER",
|
||||
i18nKey: "module.M_USER",
|
||||
parentId: "M_SYSTEM",
|
||||
sort: 20,
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/system/users",
|
||||
showInMenu: true,
|
||||
querySource: "b_user",
|
||||
saveTarget: "b_user",
|
||||
primaryKey: "b_id",
|
||||
defaultOrder: "b_userid ASC",
|
||||
enabled: true,
|
||||
fields: [
|
||||
{
|
||||
id: "F_USER_ACCOUNT",
|
||||
code: "b_userid",
|
||||
i18nKey: "field.M_USER.b_userid",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 10,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
id: "F_USER_NAME",
|
||||
code: "b_name",
|
||||
i18nKey: "field.M_USER.b_name",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 20,
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
id: "F_USER_DEPT",
|
||||
code: "b_dept",
|
||||
i18nKey: "field.M_USER.b_dept",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: false,
|
||||
queryable: true,
|
||||
sort: 30,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: "F_USER_STATUS",
|
||||
code: "b_canuse",
|
||||
i18nKey: "field.M_USER.b_canuse",
|
||||
dataType: "select",
|
||||
dictionaryCode: "USER_STATUS",
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 40,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "create", name: "新增" },
|
||||
{ code: "update", name: "修改" },
|
||||
{ code: "disable", name: "禁用" },
|
||||
{ code: "reset-password", name: "重置密码" },
|
||||
],
|
||||
sampleRows: [
|
||||
{ b_id: "U001", b_userid: "zhangsan", b_name: "张三", b_dept: "操作部", b_canuse: "ENABLED" },
|
||||
{ b_id: "U002", b_userid: "lisi", b_name: "李四", b_dept: "财务部", b_canuse: "DISABLED" },
|
||||
],
|
||||
},
|
||||
|
||||
M_BIZ_QUERY: {
|
||||
code: "M_BIZ_QUERY",
|
||||
parentId: "M_BUSINESS",
|
||||
sort: 20,
|
||||
i18nKey: "module.M_BIZ_QUERY",
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/business/query",
|
||||
showInMenu: true,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "export", name: "导出" },
|
||||
],
|
||||
sampleRows: [{}],
|
||||
},
|
||||
|
||||
M_BIZ_AUDIT: {
|
||||
code: "M_BIZ_AUDIT",
|
||||
parentId: "M_BUSINESS",
|
||||
sort: 30,
|
||||
i18nKey: "module.M_BIZ_AUDIT",
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/business/audit",
|
||||
showInMenu: false,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "audit", name: "审核" },
|
||||
],
|
||||
sampleRows: [{}],
|
||||
},
|
||||
|
||||
M_BIZ_FEE: {
|
||||
code: "M_BIZ_FEE",
|
||||
parentId: "M_BIZ",
|
||||
sort: 10,
|
||||
i18nKey: "module.M_BIZ_FEE",
|
||||
isDirectory: false,
|
||||
isPage: false,
|
||||
route: "",
|
||||
showInMenu: false,
|
||||
querySource: "v_bs_business_fee",
|
||||
saveTarget: "b_business_fee",
|
||||
primaryKey: "b_id",
|
||||
defaultOrder: "b_id ASC",
|
||||
enabled: true,
|
||||
fields: [
|
||||
{
|
||||
id: "F_BIZ_FEE_AMOUNT",
|
||||
code: "b_amount",
|
||||
i18nKey: "field.M_BIZ_FEE.b_amount",
|
||||
dataType: "number",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 10,
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
id: "F_BIZ_FEE_CURRENCY",
|
||||
code: "b_currency",
|
||||
i18nKey: "field.M_BIZ_FEE.b_currency",
|
||||
dataType: "select",
|
||||
dictionaryCode: "CURRENCY",
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 20,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "create", name: "新增" },
|
||||
{ code: "update", name: "修改" },
|
||||
{ code: "delete", name: "删除" },
|
||||
],
|
||||
sampleRows: [{ b_id: "BF01", b_amount: 6800, b_currency: "CNY" }],
|
||||
},
|
||||
|
||||
M_BIZ_ATTACHMENT: {
|
||||
code: "M_BIZ_ATTACHMENT",
|
||||
parentId: "M_BIZ",
|
||||
sort: 20,
|
||||
i18nKey: "module.M_BIZ_ATTACHMENT",
|
||||
isDirectory: false,
|
||||
isPage: false,
|
||||
route: "",
|
||||
showInMenu: false,
|
||||
querySource: "b_business_attachment",
|
||||
saveTarget: "b_business_attachment",
|
||||
primaryKey: "b_id",
|
||||
defaultOrder: "b_id DESC",
|
||||
enabled: true,
|
||||
fields: [
|
||||
{
|
||||
id: "F_ATTACHMENT_NAME",
|
||||
code: "b_filename",
|
||||
i18nKey: "field.M_BIZ_ATTACHMENT.b_filename",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 10,
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
id: "F_ATTACHMENT_REMARK",
|
||||
code: "b_remark",
|
||||
i18nKey: "field.M_BIZ_ATTACHMENT.b_remark",
|
||||
dataType: "text",
|
||||
dictionaryCode: null,
|
||||
showInList: false,
|
||||
showInForm: true,
|
||||
required: false,
|
||||
queryable: false,
|
||||
sort: 20,
|
||||
width: 180,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "upload", name: "上传" },
|
||||
{ code: "delete", name: "删除" },
|
||||
],
|
||||
sampleRows: [{ b_id: "A01", b_filename: "booking.pdf", b_remark: "订舱附件" }],
|
||||
},
|
||||
|
||||
M_FINANCE: {
|
||||
code: "M_FINANCE",
|
||||
parentId: null,
|
||||
sort: 30,
|
||||
i18nKey: "module.M_FINANCE",
|
||||
isDirectory: true,
|
||||
isPage: false,
|
||||
route: "",
|
||||
showInMenu: true,
|
||||
querySource: "",
|
||||
saveTarget: "",
|
||||
primaryKey: "",
|
||||
defaultOrder: "",
|
||||
enabled: true,
|
||||
fields: [],
|
||||
actions: [],
|
||||
sampleRows: [],
|
||||
},
|
||||
|
||||
M_FEE: {
|
||||
code: "M_FEE",
|
||||
i18nKey: "module.M_FEE",
|
||||
parentId: "M_FINANCE",
|
||||
sort: 10,
|
||||
isDirectory: false,
|
||||
isPage: true,
|
||||
route: "/finance/receivables",
|
||||
showInMenu: true,
|
||||
querySource: "v_fee_receivable",
|
||||
saveTarget: "b_fee_receivable",
|
||||
primaryKey: "b_id",
|
||||
defaultOrder: "b_id DESC",
|
||||
enabled: true,
|
||||
fields: [
|
||||
{
|
||||
id: "F_FEE_NO",
|
||||
code: "b_feeno",
|
||||
i18nKey: "field.M_FEE.b_feeno",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 10,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: "F_FEE_BIZ_NO",
|
||||
code: "b_ywno",
|
||||
i18nKey: "field.M_FEE.b_ywno",
|
||||
dataType: "string",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 20,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: "F_FEE_AMOUNT",
|
||||
code: "b_amount",
|
||||
i18nKey: "field.M_FEE.b_amount",
|
||||
dataType: "number",
|
||||
dictionaryCode: null,
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 30,
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
id: "F_FEE_CURRENCY",
|
||||
code: "b_currency",
|
||||
i18nKey: "field.M_FEE.b_currency",
|
||||
dataType: "select",
|
||||
dictionaryCode: "CURRENCY",
|
||||
showInList: true,
|
||||
showInForm: true,
|
||||
required: true,
|
||||
queryable: true,
|
||||
sort: 40,
|
||||
width: 90,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{ code: "view", name: "查看" },
|
||||
{ code: "create", name: "新增" },
|
||||
{ code: "write-off", name: "核销" },
|
||||
{ code: "export", name: "导出" },
|
||||
],
|
||||
sampleRows: [
|
||||
{
|
||||
b_id: "F001",
|
||||
b_feeno: "AR-260719-01",
|
||||
b_ywno: "SE-2026-0719",
|
||||
b_amount: 128600,
|
||||
b_currency: "CNY",
|
||||
},
|
||||
{
|
||||
b_id: "F002",
|
||||
b_feeno: "AR-260719-02",
|
||||
b_ywno: "AE-2026-0720",
|
||||
b_amount: 5200,
|
||||
b_currency: "USD",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const rolePermissions = {
|
||||
admin: [
|
||||
...Object.values(modules).flatMap((module) =>
|
||||
module.actions.map((action) => `module.${module.code}.${action.code}`),
|
||||
),
|
||||
],
|
||||
operator: [
|
||||
"module.M_BIZ.view",
|
||||
"module.M_BIZ.create",
|
||||
"module.M_BIZ.update",
|
||||
"module.M_BIZ.submit",
|
||||
"module.M_BIZ.export",
|
||||
"module.M_BIZ_QUERY.view",
|
||||
"module.M_BIZ_QUERY.export",
|
||||
"module.M_BIZ_FEE.view",
|
||||
"module.M_BIZ_FEE.create",
|
||||
"module.M_BIZ_FEE.update",
|
||||
"module.M_BIZ_ATTACHMENT.view",
|
||||
"module.M_BIZ_ATTACHMENT.upload",
|
||||
"module.M_FEE.view",
|
||||
],
|
||||
finance: [
|
||||
"module.M_BIZ_QUERY.view",
|
||||
"module.M_BIZ_QUERY.export",
|
||||
"module.M_FEE.view",
|
||||
"module.M_FEE.create",
|
||||
"module.M_FEE.write-off",
|
||||
"module.M_FEE.export",
|
||||
],
|
||||
guest: ["module.M_BIZ_QUERY.view"],
|
||||
};
|
||||
|
||||
export const i18nData = {
|
||||
"module.M_SYSTEM": { "zh-CN": "系统管理", "en-US": "System", "zh-TW": "系統管理" },
|
||||
"module.M_MODULE": { "zh-CN": "模块管理", "en-US": "Module Management", "zh-TW": "模組管理" },
|
||||
"module.M_USER": { "zh-CN": "用户管理", "en-US": "Users", "zh-TW": "用戶管理" },
|
||||
"module.M_BUSINESS": { "zh-CN": "业务管理", "en-US": "Operations", "zh-TW": "業務管理" },
|
||||
"module.M_BIZ": { "zh-CN": "海运业务单", "en-US": "Sea Orders", "zh-TW": "海運業務單" },
|
||||
"module.M_BIZ_QUERY": { "zh-CN": "业务单查询", "en-US": "Order Query", "zh-TW": "業務單查詢" },
|
||||
"module.M_BIZ_AUDIT": { "zh-CN": "业务单审核", "en-US": "Order Audit", "zh-TW": "業務單審核" },
|
||||
"module.M_BIZ_FEE": { "zh-CN": "业务单费用", "en-US": "Order Fees", "zh-TW": "業務單費用" },
|
||||
"module.M_BIZ_ATTACHMENT": {
|
||||
"zh-CN": "业务单附件",
|
||||
"en-US": "Order Attachments",
|
||||
"zh-TW": "業務單附件",
|
||||
},
|
||||
"module.M_FINANCE": { "zh-CN": "财务中心", "en-US": "Finance", "zh-TW": "財務中心" },
|
||||
"module.M_FEE": { "zh-CN": "应收费用", "en-US": "Receivable Fee", "zh-TW": "應收費用" },
|
||||
|
||||
"field.M_BIZ.b_ywno": { "zh-CN": "业务单号", "en-US": "Order No.", "zh-TW": "業務單號" },
|
||||
"field.M_BIZ.b_customer": { "zh-CN": "客户", "en-US": "Customer", "zh-TW": "客戶" },
|
||||
"field.M_BIZ.b_type": { "zh-CN": "业务类型", "en-US": "Business Type", "zh-TW": "業務類型" },
|
||||
"field.M_BIZ.b_amount": { "zh-CN": "金额", "en-US": "Amount", "zh-TW": "金額" },
|
||||
"field.M_BIZ.b_state": { "zh-CN": "状态", "en-US": "Status", "zh-TW": "狀態" },
|
||||
"field.M_BIZ.b_remark": { "zh-CN": "备注", "en-US": "Remark", "zh-TW": "備註" },
|
||||
"field.M_BIZ_FEE.b_amount": { "zh-CN": "费用金额", "en-US": "Fee Amount", "zh-TW": "費用金額" },
|
||||
"field.M_BIZ_FEE.b_currency": { "zh-CN": "币种", "en-US": "Currency", "zh-TW": "幣別" },
|
||||
"field.M_BIZ_ATTACHMENT.b_filename": {
|
||||
"zh-CN": "文件名",
|
||||
"en-US": "File Name",
|
||||
"zh-TW": "檔案名稱",
|
||||
},
|
||||
"field.M_BIZ_ATTACHMENT.b_remark": {
|
||||
"zh-CN": "附件说明",
|
||||
"en-US": "Description",
|
||||
"zh-TW": "附件說明",
|
||||
},
|
||||
"field.M_USER.b_userid": { "zh-CN": "账号", "en-US": "Account", "zh-TW": "帳號" },
|
||||
"field.M_USER.b_name": { "zh-CN": "姓名", "en-US": "Name", "zh-TW": "姓名" },
|
||||
"field.M_USER.b_dept": { "zh-CN": "部门", "en-US": "Department", "zh-TW": "部門" },
|
||||
"field.M_USER.b_canuse": { "zh-CN": "状态", "en-US": "Status", "zh-TW": "狀態" },
|
||||
"field.M_FEE.b_feeno": { "zh-CN": "费用单号", "en-US": "Fee No.", "zh-TW": "費用單號" },
|
||||
"field.M_FEE.b_ywno": { "zh-CN": "业务单号", "en-US": "Order No.", "zh-TW": "業務單號" },
|
||||
"field.M_FEE.b_amount": { "zh-CN": "金额", "en-US": "Amount", "zh-TW": "金額" },
|
||||
"field.M_FEE.b_currency": { "zh-CN": "币种", "en-US": "Currency", "zh-TW": "幣別" },
|
||||
|
||||
"dict.BIZ_TYPE.SEA": { "zh-CN": "海运", "en-US": "Sea", "zh-TW": "海運" },
|
||||
"dict.BIZ_TYPE.AIR": { "zh-CN": "空运", "en-US": "Air", "zh-TW": "空運" },
|
||||
"dict.BIZ_STATUS.DRAFT": { "zh-CN": "草稿", "en-US": "Draft", "zh-TW": "草稿" },
|
||||
"dict.BIZ_STATUS.SUBMITTED": { "zh-CN": "已提交", "en-US": "Submitted", "zh-TW": "已提交" },
|
||||
"dict.BIZ_STATUS.APPROVED": { "zh-CN": "已审核", "en-US": "Approved", "zh-TW": "已審核" },
|
||||
"dict.USER_STATUS.ENABLED": { "zh-CN": "启用", "en-US": "Enabled", "zh-TW": "啟用" },
|
||||
"dict.USER_STATUS.DISABLED": { "zh-CN": "禁用", "en-US": "Disabled", "zh-TW": "停用" },
|
||||
"dict.CURRENCY.CNY": { "zh-CN": "人民币", "en-US": "CNY", "zh-TW": "人民幣" },
|
||||
"dict.CURRENCY.USD": { "zh-CN": "美元", "en-US": "USD", "zh-TW": "美元" },
|
||||
"dict.CURRENCY.EUR": { "zh-CN": "欧元", "en-US": "EUR", "zh-TW": "歐元" },
|
||||
};
|
||||
@@ -36,15 +36,18 @@ import AppToolbar from "./components/AppToolbar.vue";
|
||||
}
|
||||
|
||||
.app-main {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--fms-bg);
|
||||
}
|
||||
|
||||
.app-content {
|
||||
width: 100%;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -20,8 +20,9 @@ const route = useRoute();
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const menuIcon = (icon) => () => h(icon, { size: 16, strokeWidth: 1.8 });
|
||||
const effectiveCollapsed = computed(() => appStore.sidebarCollapsed);
|
||||
|
||||
const menuItems = [
|
||||
const fallbackMenuItems = [
|
||||
{
|
||||
key: "/dashboard",
|
||||
icon: menuIcon(House),
|
||||
@@ -139,8 +140,8 @@ const menuItems = [
|
||||
{ key: "/system/field", label: "字段配置" },
|
||||
{ key: "/system/statisticalSettings", label: "查询设置" },
|
||||
{ key: "/system/mappingConfig", label: "映射配置" },
|
||||
{ key: "/system/moduleSettings", label: "模块设置" },
|
||||
{ key: "/system/autoId", label: "自动编码" },
|
||||
{ key: "/demo/modules", label: "模块管理" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -160,20 +161,30 @@ const menuItems = [
|
||||
},
|
||||
];
|
||||
|
||||
const menuItems = ref(fallbackMenuItems);
|
||||
|
||||
const selectedKeys = computed(() => [route.meta.menuKey || route.path]);
|
||||
const openKeys = ref([]);
|
||||
const parentKeyByRoute = new Map(
|
||||
menuItems.flatMap((item) =>
|
||||
item.children?.map((child) => [child.key, item.key]) ?? [],
|
||||
),
|
||||
);
|
||||
const parentKeysByRoute = computed(() => {
|
||||
const result = new Map();
|
||||
const visit = (items, parents = []) => {
|
||||
items.forEach((item) => {
|
||||
if (item.children?.length) visit(item.children, [...parents, item.key]);
|
||||
else result.set(item.key, parents);
|
||||
});
|
||||
};
|
||||
visit(menuItems.value);
|
||||
return result;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => route.meta.menuKey || route.path,
|
||||
(menuKey) => {
|
||||
const parentKey = parentKeyByRoute.get(menuKey);
|
||||
if (parentKey && !openKeys.value.includes(parentKey)) {
|
||||
openKeys.value = [...openKeys.value, parentKey];
|
||||
[() => route.meta.menuKey || route.path, menuItems],
|
||||
([menuKey]) => {
|
||||
const parentKeys = parentKeysByRoute.value.get(menuKey) || [];
|
||||
const nextKeys = new Set(openKeys.value);
|
||||
parentKeys.forEach((key) => nextKeys.add(key));
|
||||
if (nextKeys.size !== openKeys.value.length) {
|
||||
openKeys.value = Array.from(nextKeys);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
@@ -193,16 +204,16 @@ function updateOpenKeys(keys) {
|
||||
<template>
|
||||
<a-layout-sider
|
||||
class="app-sider"
|
||||
:collapsed="appStore.sidebarCollapsed"
|
||||
:collapsed="effectiveCollapsed"
|
||||
:trigger="null"
|
||||
:collapsed-width="56"
|
||||
collapsible
|
||||
theme="light"
|
||||
width="208"
|
||||
>
|
||||
<div class="brand" :class="{ 'brand--collapsed': appStore.sidebarCollapsed }">
|
||||
<div class="brand" :class="{ 'brand--collapsed': effectiveCollapsed }">
|
||||
<div class="brand__mark">F</div>
|
||||
<div class="brand__copy" :aria-hidden="appStore.sidebarCollapsed">
|
||||
<div class="brand__copy" :aria-hidden="effectiveCollapsed">
|
||||
<strong>FMS 管理系统</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -219,7 +230,7 @@ function updateOpenKeys(keys) {
|
||||
</div>
|
||||
|
||||
<div class="sider-footer">
|
||||
<a-tooltip :title="appStore.sidebarCollapsed ? '展开侧栏' : '收起侧栏'" placement="right">
|
||||
<a-tooltip :title="effectiveCollapsed ? '展开侧栏' : '收起侧栏'" placement="right">
|
||||
<a-button
|
||||
type="text"
|
||||
class="sider-collapse"
|
||||
@@ -227,7 +238,7 @@ function updateOpenKeys(keys) {
|
||||
@click="appStore.toggleSidebar"
|
||||
>
|
||||
<template #icon>
|
||||
<PanelLeftOpen v-if="appStore.sidebarCollapsed" />
|
||||
<PanelLeftOpen v-if="effectiveCollapsed" />
|
||||
<PanelLeftClose v-else />
|
||||
</template>
|
||||
</a-button>
|
||||
|
||||
@@ -36,6 +36,7 @@ const routes = [
|
||||
section: "业务管理",
|
||||
menuKey: "/business/orders",
|
||||
source: "v_bs_business",
|
||||
orderBy: "b_id DESC",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -48,6 +49,7 @@ const routes = [
|
||||
section: "业务管理",
|
||||
menuKey: "/business/orders",
|
||||
listPath: "/business/orders",
|
||||
source: "v_bs_business",
|
||||
detail: true,
|
||||
},
|
||||
},
|
||||
@@ -60,6 +62,7 @@ const routes = [
|
||||
section: "费用管理",
|
||||
menuKey: "/fees/receivable",
|
||||
source: "v_fee_receivable",
|
||||
orderBy: "b_id DESC",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -72,6 +75,7 @@ const routes = [
|
||||
section: "费用管理",
|
||||
menuKey: "/fees/receivable",
|
||||
listPath: "/fees/receivable",
|
||||
source: "v_fee_receivable",
|
||||
detail: true,
|
||||
},
|
||||
},
|
||||
@@ -84,6 +88,7 @@ const routes = [
|
||||
section: "报表中心",
|
||||
menuKey: "/reports/operations",
|
||||
source: "v_report_operations",
|
||||
orderBy: "b_id DESC",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -96,6 +101,7 @@ const routes = [
|
||||
section: "报表中心",
|
||||
menuKey: "/reports/operations",
|
||||
listPath: "/reports/operations",
|
||||
source: "v_report_operations",
|
||||
detail: true,
|
||||
},
|
||||
},
|
||||
@@ -107,7 +113,8 @@ const routes = [
|
||||
title: "用户管理",
|
||||
section: "系统设置",
|
||||
menuKey: "/system/users",
|
||||
source: "sys_user",
|
||||
source: "b_user",
|
||||
orderBy: "b_id ASC",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -120,9 +127,20 @@ const routes = [
|
||||
section: "系统设置",
|
||||
menuKey: "/system/users",
|
||||
listPath: "/system/users",
|
||||
source: "b_user",
|
||||
detail: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "demo/modules",
|
||||
name: "demo-modules",
|
||||
component: () => import("../views/ModuleManageDemo.vue"),
|
||||
meta: {
|
||||
title: "模块管理",
|
||||
section: "系统管理",
|
||||
menuKey: "/demo/modules",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
import { post } from "./http";
|
||||
import { get, post } from "./http";
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {object} ApiResult
|
||||
* @property {boolean} success 前端根据 code 补充的成功标记。
|
||||
* @property {number} code 后端业务状态码,0 表示成功。
|
||||
* @property {string} message 响应消息。
|
||||
* @property {T} data 响应数据。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 机构用户登录。
|
||||
* @param {string} orgId 机构码。
|
||||
* @param {string} userId 用户 ID。
|
||||
* @param {string} password 密码。
|
||||
* @returns {Promise<{success: boolean, code: number, message: string, data: {token: string, orgid: string, user: {id: string, name: string}}}>} 登录响应。
|
||||
* @returns {Promise<ApiResult<{token: string, orgid: string, user: {id: string, name: string}}>>} 登录响应。
|
||||
*/
|
||||
export function loginApi(orgId, userId, password) {
|
||||
return post("/auth/login", {
|
||||
@@ -19,15 +28,15 @@ export function loginApi(orgId, userId, password) {
|
||||
* 按表或视图加载数据。
|
||||
* @param {string} viewName 表名或视图名,必填。
|
||||
* @param {string} [searchCondition] 查询条件,不包含 WHERE。
|
||||
* @param {string} [orderField] 排序字段,可带 ASC 或 DESC。
|
||||
* @param {string} [orderBy] 排序字段,可带 ASC 或 DESC。
|
||||
* @param {string[]} [searchColumns] 需要返回的字段列表,省略时返回全部字段。
|
||||
* @returns {Promise<{success: boolean, code: number, message: string, data: object[]}>} 查询响应。
|
||||
* @returns {Promise<ApiResult<object[]>>} 查询响应。
|
||||
*/
|
||||
export function loadDataApi(viewName, searchCondition, orderField, searchColumns) {
|
||||
export function loadDataApi(viewName, searchCondition, orderBy, searchColumns) {
|
||||
return post("/data/loaddata", {
|
||||
view_name: viewName,
|
||||
search_condition: searchCondition,
|
||||
order_field: orderField,
|
||||
order_by: orderBy,
|
||||
search_columns: searchColumns,
|
||||
});
|
||||
}
|
||||
@@ -35,8 +44,54 @@ export function loadDataApi(viewName, searchCondition, orderField, searchColumns
|
||||
/**
|
||||
* 执行只读 SQL 查询。
|
||||
* @param {string} sql 完整的 SELECT 或 WITH 查询语句。
|
||||
* @returns {Promise<{success: boolean, code: number, message: string, data: object[]}>} 查询响应。
|
||||
* @returns {Promise<ApiResult<object[]>>} 查询响应。
|
||||
*/
|
||||
export function loadDataBySqlApi(sql) {
|
||||
return post("/data/loaddatabysql", { sql });
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页加载表或视图数据。
|
||||
* @param {object} options 分页查询参数。
|
||||
* @param {string} options.viewName 表名或视图名,必填。
|
||||
* @param {string} options.orderBy 排序字段,必填,可用逗号分隔多个字段。
|
||||
* @param {string[]} [options.searchColumns] 需要返回的字段列表。
|
||||
* @param {string} [options.searchCondition] 查询条件,不包含 WHERE。
|
||||
* @param {number} [options.pageNo=1] 页码,从 1 开始。
|
||||
* @param {number} [options.pageSize=20] 每页记录数。
|
||||
* @returns {Promise<ApiResult<{rows: object[], row_count: number, total: number, page_no: number, page_size: number}>>} 分页响应。
|
||||
*/
|
||||
export function pageDataApi({
|
||||
viewName,
|
||||
orderBy,
|
||||
searchColumns,
|
||||
searchCondition,
|
||||
pageNo = 1,
|
||||
pageSize = 20,
|
||||
}) {
|
||||
return post("/data/page", {
|
||||
view_name: viewName,
|
||||
search_columns: searchColumns,
|
||||
search_condition: searchCondition,
|
||||
order_by: orderBy,
|
||||
page_no: pageNo,
|
||||
page_size: pageSize,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 在同一事务中保存一个或多个表的数据变更。
|
||||
* @param {{table: string, key_field: string, inserts?: object[], updates?: object[], deletes?: object[]}[]} requests 保存配置,不能为空数组。
|
||||
* @returns {Promise<ApiResult<null>>} 保存响应。
|
||||
*/
|
||||
export function saveObjectApi(requests) {
|
||||
return post("/data/saveobjt", requests);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个雪花 ID。
|
||||
* @returns {Promise<ApiResult<string>>} 取号响应,雪花 ID 使用字符串避免精度丢失。
|
||||
*/
|
||||
export function nextIdApi() {
|
||||
return get("/data/nextid");
|
||||
}
|
||||
@@ -87,4 +87,8 @@ export function post(path, data, config) {
|
||||
return http.post(path, data, config);
|
||||
}
|
||||
|
||||
export function get(path, config) {
|
||||
return http.get(path, config);
|
||||
}
|
||||
|
||||
export default http;
|
||||
@@ -2,7 +2,7 @@
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Ellipsis, ListFilter, Plus, Search } from "@lucide/vue";
|
||||
import { loadDataApi } from "../services/api";
|
||||
import { loadDataApi, pageDataApi } from "../services/api";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -53,6 +53,9 @@ const advancedFilters = reactive(createEmptyAdvancedFilters());
|
||||
const draftFilterCount = computed(
|
||||
() => Object.values(advancedFilters).filter(isFilterValueFilled).length,
|
||||
);
|
||||
const hasActiveFilters = computed(
|
||||
() => Boolean(filters.keyword.trim()) || appliedFilterCount.value > 0,
|
||||
);
|
||||
|
||||
function createEmptyAdvancedFilters() {
|
||||
return {
|
||||
@@ -89,9 +92,22 @@ function getRowValue(row, candidates) {
|
||||
|
||||
function normalizeRow(row, index) {
|
||||
const id = getRowValue(row, ["id", "b_id", "user_id", "userid"]);
|
||||
const name = getRowValue(row, ["name", "b_name", "customer_name", "title"]);
|
||||
const state = getRowValue(row, ["state", "b_state", "status"]);
|
||||
const updatedAt = getRowValue(row, ["updated_at", "update_time", "updated_time", "b_updated_at"]);
|
||||
const name = getRowValue(row, [
|
||||
"name",
|
||||
"b_name",
|
||||
"customer_name",
|
||||
"v_customer_company",
|
||||
"b_ywno",
|
||||
"title",
|
||||
]);
|
||||
const state = getRowValue(row, ["state", "b_state", "status", "b_canuse"]);
|
||||
const updatedAt = getRowValue(row, [
|
||||
"updated_at",
|
||||
"b_updatedatetime",
|
||||
"update_time",
|
||||
"updated_time",
|
||||
"b_updated_at",
|
||||
]);
|
||||
|
||||
return {
|
||||
...row,
|
||||
@@ -176,7 +192,7 @@ function applyLocalFilters() {
|
||||
|
||||
function searchData() {
|
||||
pagination.current = 1;
|
||||
applyLocalFilters();
|
||||
loadData();
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
@@ -188,11 +204,27 @@ async function loadData() {
|
||||
loadError.value = "";
|
||||
|
||||
try {
|
||||
const response = await loadDataApi(viewName);
|
||||
const result = response.data;
|
||||
const response = hasActiveFilters.value
|
||||
? await loadDataApi(viewName)
|
||||
: await pageDataApi({
|
||||
viewName,
|
||||
orderBy: String(route.meta.orderBy || "b_id DESC"),
|
||||
pageNo: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
});
|
||||
if (currentSequence !== loadSequence) return;
|
||||
sourceRows.value = (Array.isArray(result) ? result : []).map(normalizeRow);
|
||||
applyLocalFilters();
|
||||
|
||||
if (hasActiveFilters.value) {
|
||||
sourceRows.value = (Array.isArray(response.data) ? response.data : []).map(normalizeRow);
|
||||
applyLocalFilters();
|
||||
} else {
|
||||
const result = response.data ?? {};
|
||||
sourceRows.value = [];
|
||||
rows.value = (Array.isArray(result.rows) ? result.rows : []).map(normalizeRow);
|
||||
total.value = Number(result.total) || 0;
|
||||
pagination.current = Number(result.page_no) || pagination.current;
|
||||
pagination.pageSize = Number(result.page_size) || pagination.pageSize;
|
||||
}
|
||||
} catch (error) {
|
||||
if (currentSequence !== loadSequence) return;
|
||||
sourceRows.value = [];
|
||||
@@ -211,7 +243,11 @@ function openDetail(record) {
|
||||
function changePage(page, pageSize) {
|
||||
pagination.current = page;
|
||||
pagination.pageSize = pageSize;
|
||||
applyLocalFilters();
|
||||
if (hasActiveFilters.value) {
|
||||
applyLocalFilters();
|
||||
} else {
|
||||
loadData();
|
||||
}
|
||||
}
|
||||
|
||||
function resetAdvancedFilters() {
|
||||
@@ -222,7 +258,7 @@ function applyAdvancedFilters() {
|
||||
pagination.current = 1;
|
||||
appliedFilterCount.value = draftFilterCount.value;
|
||||
advancedOpen.value = false;
|
||||
applyLocalFilters();
|
||||
loadData();
|
||||
}
|
||||
|
||||
function updateTableHeight() {
|
||||
@@ -593,13 +629,4 @@ watch(
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.advanced-filter-form {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.filter-span-full {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,33 +1,79 @@
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ArrowLeft } from "@lucide/vue";
|
||||
import { mockRecords } from "../data/mockRecords";
|
||||
import { loadDataApi } from "../services/api";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const remark = ref("");
|
||||
const loading = ref(false);
|
||||
const loadError = ref("");
|
||||
const sourceRecord = ref(null);
|
||||
let loadSequence = 0;
|
||||
|
||||
const recordId = computed(() => String(route.params.id ?? ""));
|
||||
const detailTitle = computed(() => route.meta.listTitle || route.meta.title || "详情");
|
||||
const record = computed(
|
||||
() =>
|
||||
mockRecords.find((item) => item.id === recordId.value) ?? {
|
||||
id: recordId.value,
|
||||
name: `${detailTitle.value} ${recordId.value}`,
|
||||
state: "草稿",
|
||||
businessType: "未设置",
|
||||
owner: "未设置",
|
||||
customer: "未设置",
|
||||
amount: "0.00",
|
||||
currency: "CNY",
|
||||
updated_at: "--",
|
||||
},
|
||||
);
|
||||
|
||||
function getRowValue(row, candidates) {
|
||||
if (!row) return undefined;
|
||||
const keys = Object.keys(row);
|
||||
for (const candidate of candidates) {
|
||||
const matchedKey = keys.find((key) => key.toLowerCase() === candidate.toLowerCase());
|
||||
if (matchedKey !== undefined && row[matchedKey] != null) return row[matchedKey];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const record = computed(() => {
|
||||
const row = sourceRecord.value;
|
||||
return {
|
||||
id: recordId.value,
|
||||
name: getRowValue(row, ["name", "b_name", "v_customer_company", "b_ywno", "title"]) ?? "--",
|
||||
state: getRowValue(row, ["state", "b_state", "status", "b_canuse"]) ?? "--",
|
||||
businessType: getRowValue(row, ["business_type", "b_ywtype", "b_type"]) ?? "--",
|
||||
owner: getRowValue(row, ["owner", "owner_name", "v_sales_name", "b_owner_id"]) ?? "--",
|
||||
customer: getRowValue(row, ["customer", "customer_name", "v_customer_company"]) ?? "--",
|
||||
amount: getRowValue(row, ["amount", "total_amount", "b_amount"]) ?? "--",
|
||||
currency: getRowValue(row, ["currency", "currency_code", "b_currency"]) ?? "",
|
||||
updated_at:
|
||||
getRowValue(row, ["updated_at", "b_updatedatetime", "update_time", "updated_time"]) ?? "--",
|
||||
};
|
||||
});
|
||||
|
||||
function escapeSqlString(value) {
|
||||
return String(value).replaceAll("'", "''");
|
||||
}
|
||||
|
||||
async function loadDetail() {
|
||||
const currentSequence = ++loadSequence;
|
||||
const source = String(route.meta.source || "");
|
||||
if (!source || !recordId.value) {
|
||||
sourceRecord.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
loadError.value = "";
|
||||
sourceRecord.value = null;
|
||||
try {
|
||||
const response = await loadDataApi(source, `b_id = N'${escapeSqlString(recordId.value)}'`);
|
||||
if (currentSequence !== loadSequence) return;
|
||||
sourceRecord.value = Array.isArray(response.data) ? (response.data[0] ?? null) : null;
|
||||
if (!sourceRecord.value) loadError.value = "未找到对应记录";
|
||||
} catch (error) {
|
||||
if (currentSequence !== loadSequence) return;
|
||||
loadError.value = error.message || "详情加载失败";
|
||||
} finally {
|
||||
if (currentSequence === loadSequence) loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function backToList() {
|
||||
router.push(String(route.meta.listPath || "/dashboard"));
|
||||
}
|
||||
|
||||
watch([() => route.meta.source, recordId], loadDetail, { immediate: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -44,16 +90,24 @@ function backToList() {
|
||||
</header>
|
||||
|
||||
<main class="detail-content">
|
||||
<a-descriptions bordered size="small" :column="{ xs: 1, sm: 2, md: 3 }">
|
||||
<a-descriptions-item label="编号">{{ recordId }}</a-descriptions-item>
|
||||
<a-descriptions-item label="名称">{{ record.name }}</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">{{ record.state }}</a-descriptions-item>
|
||||
<a-descriptions-item label="客户">{{ record.customer }}</a-descriptions-item>
|
||||
<a-descriptions-item label="业务类型">{{ record.businessType }}</a-descriptions-item>
|
||||
<a-descriptions-item label="负责人">{{ record.owner }}</a-descriptions-item>
|
||||
<a-descriptions-item label="金额">{{ record.amount }} {{ record.currency }}</a-descriptions-item>
|
||||
<a-descriptions-item label="更新时间">{{ record.updated_at }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-spin :spinning="loading">
|
||||
<a-alert v-if="loadError" type="error" show-icon :message="loadError">
|
||||
<template #action><a-button size="small" @click="loadDetail">重试</a-button></template>
|
||||
</a-alert>
|
||||
|
||||
<a-descriptions v-else bordered size="small" :column="3">
|
||||
<a-descriptions-item label="编号">{{ recordId }}</a-descriptions-item>
|
||||
<a-descriptions-item label="名称">{{ record.name }}</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">{{ record.state }}</a-descriptions-item>
|
||||
<a-descriptions-item label="客户">{{ record.customer }}</a-descriptions-item>
|
||||
<a-descriptions-item label="业务类型">{{ record.businessType }}</a-descriptions-item>
|
||||
<a-descriptions-item label="负责人">{{ record.owner }}</a-descriptions-item>
|
||||
<a-descriptions-item label="金额">
|
||||
{{ record.amount }} {{ record.currency }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="更新时间">{{ record.updated_at }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-spin>
|
||||
|
||||
<section class="detail-remark">
|
||||
<div class="detail-remark__label">备注</div>
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user