2026-07-27 09:26:52 +08:00
|
|
|
export type ResourceMode = 'writable' | 'readonly' | 'append_only';
|
2026-07-27 09:56:33 +08:00
|
|
|
export type ResourcePageKind = 'list' | 'tree';
|
2026-07-27 09:26:52 +08:00
|
|
|
export type ResourceField = { key: string; label: string; required?: boolean };
|
2026-07-27 09:56:33 +08:00
|
|
|
export type DetailAction = { name: string; resource: string; fields: ResourceField[] };
|
|
|
|
|
export type ResourceUiDefinition = { key: string; name: string; resource: string; title: string; mode: ResourceMode; pageKind: ResourcePageKind; fields: ResourceField[]; requiredIdentities: string[]; detailActions?: DetailAction[] };
|
|
|
|
|
|
|
|
|
|
const field = (value: string): ResourceField => ({ key: value.replace(/!$/, ''), label: value.replace(/!$/, ''), required: value.endsWith('!') || undefined });
|
|
|
|
|
const define = (name: string, resource: string, mode: ResourceMode, pageKind: ResourcePageKind, keys: string[], detailActions?: DetailAction[]): ResourceUiDefinition => {
|
|
|
|
|
const fields = keys.map(field);
|
|
|
|
|
return { key: name.replace(/_/g, '-'), name, resource, title: name, mode, pageKind, fields, requiredIdentities: fields.filter((item) => item.required && item.key.endsWith('_identity')).map((item) => item.key), ...(detailActions ? { detailActions } : {}) };
|
|
|
|
|
};
|
|
|
|
|
const action = (name: string, resource: string, keys: string[]): DetailAction => ({ name, resource, fields: keys.map(field) });
|
|
|
|
|
|
|
|
|
|
/** Exact UI contract for every backend ExpectedResources entry. */
|
2026-07-27 09:26:52 +08:00
|
|
|
export const resources: ResourceUiDefinition[] = [
|
2026-07-27 09:56:33 +08:00
|
|
|
define('gas_basic', '/gas/gas_basic', 'writable', 'list', ['code!', 'name!', 'credit_code', 'principal', 'address', 'longitude', 'latitude']),
|
|
|
|
|
define('gas_account', '/gas/gas_account', 'writable', 'list', ['username!', 'password!', 'display_name', 'role_code', 'gas_basic_identity!']),
|
|
|
|
|
define('delivery_basic', '/delivery/delivery_basic', 'writable', 'list', ['delivery_code!', 'name!', 'gas_basic_identity', 'principal', 'address']),
|
|
|
|
|
define('delivery_account', '/delivery/delivery_account', 'writable', 'list', ['username!', 'password!', 'display_name', 'role_code', 'delivery_basic_identity!']),
|
|
|
|
|
define('delivery_task', '/delivery/delivery_task', 'writable', 'list', ['ec_order_identity!', 'delivery_basic_identity!', 'staff_account_identity']),
|
|
|
|
|
define('delivery_track', '/delivery/delivery_track', 'writable', 'list', ['delivery_task_identity!', 'started_at', 'completed_at']),
|
|
|
|
|
define('delivery_track_point', '/delivery/delivery_track_point', 'writable', 'list', ['delivery_track_identity!', 'point_type!', 'occurred_at!', 'longitude!', 'latitude!']),
|
|
|
|
|
define('staff_account', '/staff/account', 'writable', 'list', ['username!', 'password!', 'name!', 'phone', 'avatar', 'role_code', 'gas_basic_identity', 'delivery_basic_identity', 'work_status']),
|
|
|
|
|
define('staff_credential', '/staff/credential', 'writable', 'list', ['staff_account_identity!', 'credential_type!', 'credential_no', 'expired_at']),
|
|
|
|
|
define('user_account', '/user/account', 'writable', 'list', ['username!', 'password!', 'name!', 'phone', 'avatar', 'real_name']),
|
|
|
|
|
define('user_address', '/user/address', 'writable', 'list', ['user_account_identity!', 'address!', 'longitude', 'latitude', 'is_default']),
|
|
|
|
|
define('user_service_relation', '/user/service_relation', 'writable', 'list', ['user_account_identity!', 'gas_basic_identity', 'delivery_basic_identity', 'staff_account_identity']),
|
|
|
|
|
define('dev_smart_cylinder_valve', '/device/dev_smart_cylinder_valve', 'writable', 'list', ['device_no!', 'model', 'online_status', 'owner_identity']),
|
|
|
|
|
define('dev_device_binding', '/device/dev_device_binding', 'writable', 'list', ['smart_cylinder_valve_identity!', 'user_account_identity!', 'effective_at', 'expired_at']),
|
|
|
|
|
define('dev_telemetry', '/device/dev_telemetry', 'readonly', 'list', ['smart_cylinder_valve_identity', 'recorded_at', 'payload']),
|
|
|
|
|
define('saf_rule', '/safety/saf_rule', 'writable', 'list', ['rule_code!', 'version_no', 'threshold', 'action', 'gray_scope']),
|
|
|
|
|
define('saf_event', '/safety/saf_event', 'writable', 'list', ['event_code!', 'level!', 'title!', 'smart_cylinder_valve_identity!', 'sla_at'], [action('saf_event_disposal', '/safety/saf_event/:identity/disposals', ['action!', 'reason!'])]),
|
|
|
|
|
define('saf_inspection', '/safety/saf_inspection', 'writable', 'list', ['user_account_identity!', 'staff_account_identity!', 'result!', 'evidence_uri']),
|
|
|
|
|
define('saf_event_disposal', '/safety/saf_event/:identity/disposals', 'append_only', 'list', ['action!', 'reason!']),
|
|
|
|
|
define('ec_category', '/ec/ec_category', 'writable', 'tree', ['parent_identity', 'name!', 'sort_no']),
|
|
|
|
|
define('ec_product', '/ec/ec_product', 'writable', 'list', ['ec_category_identity!', 'product_code!', 'name!', 'price_amount!', 'stock_quantity']),
|
|
|
|
|
define('ec_product_attribute', '/ec/ec_product_attribute', 'writable', 'list', ['ec_product_identity!', 'name!', 'value!', 'sort_no']),
|
|
|
|
|
define('ec_product_image', '/ec/ec_product_image', 'writable', 'list', ['ec_product_identity!', 'image_uri!', 'sort_no', 'is_cover']),
|
|
|
|
|
define('ec_cart', '/ec/ec_cart', 'writable', 'list', ['user_account_identity!', 'ec_product_identity!', 'quantity!', 'selected']),
|
|
|
|
|
define('ec_order', '/ec/ec_order', 'writable', 'list', ['user_account_identity!', 'gas_basic_identity', 'delivery_basic_identity', 'order_no!', 'total_amount!']),
|
|
|
|
|
define('ec_order_item', '/ec/ec_order_item', 'writable', 'list', ['ec_order_identity!', 'ec_product_identity!', 'product_snapshot!', 'quantity!', 'sale_amount!']),
|
|
|
|
|
define('ec_review', '/ec/ec_review', 'writable', 'list', ['ec_order_identity!', 'ec_product_identity!', 'user_account_identity!', 'score!', 'content!']),
|
|
|
|
|
define('fin_payment', '/finance/fin_payment', 'writable', 'list', ['ec_order_identity!', 'channel!', 'amount!', 'paid_at']),
|
|
|
|
|
define('fin_settlement', '/finance/fin_settlement', 'writable', 'list', ['settlement_no!', 'subject_type!', 'subject_identity!', 'period_start!', 'period_end!']),
|
|
|
|
|
define('fin_reconciliation', '/finance/fin_reconciliation', 'writable', 'list', ['channel!', 'bill_date!', 'difference_amount!']),
|
|
|
|
|
define('cnt_content', '/content/cnt_content', 'writable', 'list', ['content_type!', 'title!', 'body!', 'version_no', 'publish_status']),
|
|
|
|
|
define('ntf_template', '/notification/ntf_template', 'writable', 'list', ['template_code!', 'channel!', 'content!']),
|
|
|
|
|
define('cs_ticket', '/customer_service/cs_ticket', 'writable', 'list', ['user_account_identity!', 'ticket_no!', 'category!', 'priority!']),
|
|
|
|
|
define('platfrom_account', '/platform/platfrom_account', 'writable', 'list', ['username!', 'password!', 'display_name', 'avatar', 'platform_role_code', 'phone']),
|
|
|
|
|
define('platform_role', '/platform/platform_role', 'writable', 'list', ['role_code!', 'name!', 'data_scope!']),
|
|
|
|
|
define('platform_menu', '/platform/platform_menu', 'writable', 'tree', ['parent_identity', 'menu_code!', 'name!', 'icon', 'path', 'sort_no']),
|
|
|
|
|
define('wallet', '/wallet/wallet', 'readonly', 'list', ['owner_identity', 'balance_amount', 'status']),
|
|
|
|
|
define('wallet_ledger', '/wallet/wallet_ledger', 'readonly', 'list', ['wallet_identity', 'change_amount', 'balance_after']),
|
|
|
|
|
define('wallet_recharge', '/wallet/wallet_recharge', 'readonly', 'list', ['wallet_identity', 'amount', 'status']),
|
|
|
|
|
define('wallet_withdrawal', '/wallet/wallet_withdrawal', 'readonly', 'list', ['wallet_identity', 'amount', 'status']),
|
|
|
|
|
define('report', '/report/report', 'readonly', 'list', ['report_code', 'name', 'status']),
|
|
|
|
|
define('report_item', '/report/report_item', 'readonly', 'list', ['report_identity', 'metric_code', 'value']),
|
|
|
|
|
define('report_metric_snapshot', '/report/report_metric_snapshot', 'readonly', 'list', ['report_identity', 'metric_code', 'value', 'captured_at']),
|
|
|
|
|
define('aud_operation_log', '/audit/aud_operation_log', 'readonly', 'list', ['operator_identity', 'action', 'object_identity', 'created_at']),
|
|
|
|
|
define('aud_export_log', '/audit/aud_export_log', 'readonly', 'list', ['operator_identity', 'resource_type', 'created_at']),
|
|
|
|
|
define('aud_approval', '/audit/aud_approval', 'readonly', 'list', ['operator_identity', 'status', 'handled_at']),
|
2026-07-27 09:26:52 +08:00
|
|
|
];
|
2026-07-27 09:56:33 +08:00
|
|
|
|
2026-07-27 09:26:52 +08:00
|
|
|
export const resourceByName = Object.fromEntries(resources.map((definition) => [definition.resource, definition])) as Record<string, ResourceUiDefinition>;
|
|
|
|
|
export function getResource(resourcePath: string): ResourceUiDefinition {
|
|
|
|
|
const definition = resourceByName[resourcePath];
|
2026-07-27 09:44:08 +08:00
|
|
|
if (!definition) throw new Error('Unknown resource: ' + resourcePath);
|
2026-07-27 09:26:52 +08:00
|
|
|
return definition;
|
|
|
|
|
}
|