From 30c6f5984408a50c62ff2af34f2f6d9d211a0d38 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 14:42:21 +0800 Subject: [PATCH 1/7] update compose --- docker_nocobase/demo/docker-compose.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker_nocobase/demo/docker-compose.yml b/docker_nocobase/demo/docker-compose.yml index 91e4f58..b303447 100644 --- a/docker_nocobase/demo/docker-compose.yml +++ b/docker_nocobase/demo/docker-compose.yml @@ -18,19 +18,21 @@ services: # su postgres && psql -d nocobase svc-nocobase: - image: quay.io/labnow/nocobase container_name: svc-nocobase hostname: svc-nocobase + image: quay.io/labnow/nocobase:latest + pull_policy: always + restart: unless-stopped depends_on: ["db-postgres-common"] environment: TZ: Asia/Shanghai + LOCALE: zh-CN DB_DIALECT: postgres DB_HOST: db-postgres-common DB_PORT: 5432 DB_USER: postgres DB_PASSWORD: postgres DB_DATABASE: nocobase - LOCALE: zh-CN # INIT_ROOT_USERNAME: nocobase # INIT_ROOT_EMAIL: admin@nocobase.com # INIT_ROOT_PASSWORD: admin123 From ac52ec85ac6ec914f0021f59d6dbed9354d7fdb5 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 08:10:23 +0000 Subject: [PATCH 2/7] update model --- docker_nocobase/demo/nocobase-crm.sql | 431 +++++++++++++++++--------- 1 file changed, 287 insertions(+), 144 deletions(-) diff --git a/docker_nocobase/demo/nocobase-crm.sql b/docker_nocobase/demo/nocobase-crm.sql index e8440c5..a1085f4 100644 --- a/docker_nocobase/demo/nocobase-crm.sql +++ b/docker_nocobase/demo/nocobase-crm.sql @@ -1,31 +1,99 @@ /* NocoBase fresh-database bootstrap (PostgreSQL) - "public" schema - - Standalone initial DDL for CRM tables (prefixed with "t_crm_") + - Standalone initial DDL for CRM/meta tables (prefixed with "t_crm_" or "t_meta_") - Sequence + DEFAULT nextval(...) - - Physical foreign key constraints, M2M junction table (t_crm_contactTags) & O2M table (t_crm_contactRecords) + - Physical foreign key constraints, M2M junction table (t_crm_customerTags) & O2M table (t_crm_customerRecords) - Built-in NocoBase metadata registration (categories, collections & fields) - Association metadata (m2o, m2m, o2m / belongsTo, belongsToMany, hasMany) - Collection sort numbers starting from 101 - - Composite primary key & filterTargetKey configuration for junction table (t_crm_contactTags) + - Snowflake ID style primary keys with _id suffix */ -- ========================================================= --- 1. Sequences +-- 0. Utility function for business code generation -- ========================================================= -CREATE SEQUENCE IF NOT EXISTS "t_crm_contacts_id_seq"; +CREATE OR REPLACE FUNCTION generate_biz_code( + p_prefix text, + p_with_date boolean DEFAULT false, + p_length int DEFAULT 6, + p_charset text DEFAULT 'base32' +) +RETURNS text +LANGUAGE plpgsql +AS $$ +DECLARE + v_charset text; + v_result text := ''; + v_date text; + i int; + v_index int; +BEGIN + IF p_length < 1 OR p_length > 32 THEN + RAISE EXCEPTION 'length must be between 1 and 32'; + END IF; + + CASE lower(p_charset) + WHEN 'numeric' THEN v_charset := '0123456789'; + WHEN 'alphanumeric' THEN v_charset := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + WHEN 'base32' THEN v_charset := '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; + ELSE + RAISE EXCEPTION 'unsupported charset: %, allowed: numeric, alphanumeric, base32', p_charset; + END CASE; + + FOR i IN 1..p_length LOOP + v_index := + floor( + random() * length(v_charset) + )::int + 1; + v_result := v_result || substr(v_charset, v_index, 1); + END LOOP; + + IF p_with_date THEN + v_date := to_char(current_date, 'YYYYMMDD'); + RETURN format('%s-%s-%s', upper(p_prefix), v_date, v_result); + ELSE + RETURN format('%s-%s', upper(p_prefix), v_result); + END IF; +END; +$$; + +-- ========================================================= +-- 1. Reset existing objects for a fresh bootstrap +-- ========================================================= +DROP TABLE IF EXISTS "t_crm_orderItems" CASCADE; +DROP TABLE IF EXISTS "t_crm_orders" CASCADE; +DROP TABLE IF EXISTS "t_meta_skus" CASCADE; +DROP TABLE IF EXISTS "t_meta_spus" CASCADE; +DROP TABLE IF EXISTS "t_crm_customerTags" CASCADE; +DROP TABLE IF EXISTS "t_crm_customerRecords" CASCADE; +DROP TABLE IF EXISTS "t_crm_tags" CASCADE; +DROP TABLE IF EXISTS "t_crm_customer" CASCADE; + +DROP SEQUENCE IF EXISTS "t_crm_customer_id_seq"; +DROP SEQUENCE IF EXISTS "t_crm_tags_id_seq"; +DROP SEQUENCE IF EXISTS "t_crm_customerTags_id_seq"; +DROP SEQUENCE IF EXISTS "t_crm_customerRecords_id_seq"; +DROP SEQUENCE IF EXISTS "t_meta_spus_id_seq"; +DROP SEQUENCE IF EXISTS "t_meta_skus_id_seq"; +DROP SEQUENCE IF EXISTS "t_crm_orders_id_seq"; +DROP SEQUENCE IF EXISTS "t_crm_orderItems_id_seq"; + +CREATE SEQUENCE IF NOT EXISTS "t_crm_customer_id_seq"; CREATE SEQUENCE IF NOT EXISTS "t_crm_tags_id_seq"; -CREATE SEQUENCE IF NOT EXISTS "t_crm_spus_id_seq"; -CREATE SEQUENCE IF NOT EXISTS "t_crm_skus_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "t_crm_customerTags_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "t_crm_customerRecords_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "t_meta_spus_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "t_meta_skus_id_seq"; CREATE SEQUENCE IF NOT EXISTS "t_crm_orders_id_seq"; CREATE SEQUENCE IF NOT EXISTS "t_crm_orderItems_id_seq"; -CREATE SEQUENCE IF NOT EXISTS "t_crm_contactRecords_id_seq"; -- ========================================================= --- 2. Main tables (Audit columns placed immediately after id) +-- 2. Main tables (Audit columns placed immediately after _id) -- ========================================================= -CREATE TABLE IF NOT EXISTS "t_crm_contacts" ( - "id" bigint NOT NULL DEFAULT nextval('t_crm_contacts_id_seq'::regclass), +CREATE TABLE IF NOT EXISTS "t_crm_customer" ( + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customer_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CUST', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -36,49 +104,63 @@ CREATE TABLE IF NOT EXISTS "t_crm_contacts" ( "age" bigint, "gender" character varying(255), "state" character varying(255) DEFAULT 'sea', - CONSTRAINT "t_crm_contacts_pkey" PRIMARY KEY ("id") + "data1" text, + "data2" text, + CONSTRAINT "t_crm_customer_pkey" PRIMARY KEY ("_id") ); CREATE TABLE IF NOT EXISTS "t_crm_tags" ( - "id" bigint NOT NULL DEFAULT nextval('t_crm_tags_id_seq'::regclass), + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_tags_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('TAG', true, 5, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, "tag" character varying(255), "state" character varying(255) DEFAULT '0', - CONSTRAINT "t_crm_tags_pkey" PRIMARY KEY ("id") + "data1" text, + "data2" text, + CONSTRAINT "t_crm_tags_pkey" PRIMARY KEY ("_id") ); --- Many-to-Many Junction Table between t_crm_contacts and t_crm_tags -CREATE TABLE IF NOT EXISTS "t_crm_contactTags" ( +-- Many-to-Many Junction Table between t_crm_customer and t_crm_tags +CREATE TABLE IF NOT EXISTS "t_crm_customerTags" ( + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customerTags_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CTAG', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - "contact" bigint NOT NULL, + "customer" bigint NOT NULL, "tag" bigint NOT NULL, - CONSTRAINT "t_crm_contactTags_pkey" PRIMARY KEY ("contact", "tag"), - CONSTRAINT "t_crm_contactTags_contact_fkey" FOREIGN KEY ("contact") REFERENCES "t_crm_contacts"("id") ON DELETE CASCADE, - CONSTRAINT "t_crm_contactTags_tag_fkey" FOREIGN KEY ("tag") REFERENCES "t_crm_tags"("id") ON DELETE CASCADE + "data1" text, + "data2" text, + CONSTRAINT "t_crm_customerTags_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_crm_customerTags_customer_tag_uk" UNIQUE ("customer", "tag"), + CONSTRAINT "t_crm_customerTags_customer_fkey" FOREIGN KEY ("customer") REFERENCES "t_crm_customer"("_id") ON DELETE CASCADE, + CONSTRAINT "t_crm_customerTags_tag_fkey" FOREIGN KEY ("tag") REFERENCES "t_crm_tags"("_id") ON DELETE CASCADE ); --- One-to-Many Table for Contact Communication Records -CREATE TABLE IF NOT EXISTS "t_crm_contactRecords" ( - "id" bigint NOT NULL DEFAULT nextval('"t_crm_contactRecords_id_seq"'::regclass), +-- One-to-Many Table for Customer Communication Records +CREATE TABLE IF NOT EXISTS "t_crm_customerRecords" ( + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customerRecords_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CREC', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, - "contactId" bigint NOT NULL, + "customerId" bigint NOT NULL, "title" character varying(255), "type" character varying(255) DEFAULT 'call', "content" text, "recordTime" timestamp with time zone DEFAULT CURRENT_TIMESTAMP, - CONSTRAINT "t_crm_contactRecords_pkey" PRIMARY KEY ("id"), - CONSTRAINT "t_crm_contactRecords_contactId_fkey" FOREIGN KEY ("contactId") REFERENCES "t_crm_contacts"("id") ON DELETE CASCADE + "data1" text, + "data2" text, + CONSTRAINT "t_crm_customerRecords_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_crm_customerRecords_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("_id") ON DELETE CASCADE ); -CREATE TABLE IF NOT EXISTS "t_crm_spus" ( - "id" bigint NOT NULL DEFAULT nextval('t_crm_spus_id_seq'::regclass), +CREATE TABLE IF NOT EXISTS "t_meta_spus" ( + "_id" bigint NOT NULL DEFAULT nextval('"t_meta_spus_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SPU', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -89,11 +171,14 @@ CREATE TABLE IF NOT EXISTS "t_crm_spus" ( "unitMeasureValue" double precision NOT NULL, "unitMeasureUnit" character varying(255), "unitSpecDisplay" character varying(255), - CONSTRAINT "t_crm_spus_pkey" PRIMARY KEY ("id") + "data1" text, + "data2" text, + CONSTRAINT "t_meta_spus_pkey" PRIMARY KEY ("_id") ); -CREATE TABLE IF NOT EXISTS "t_crm_skus" ( - "id" bigint NOT NULL DEFAULT nextval('t_crm_skus_id_seq'::regclass), +CREATE TABLE IF NOT EXISTS "t_meta_skus" ( + "_id" bigint NOT NULL DEFAULT nextval('"t_meta_skus_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SKU', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -103,75 +188,102 @@ CREATE TABLE IF NOT EXISTS "t_crm_skus" ( "saleUnit" character varying(255), "packageSpecDisplay" text NOT NULL, "salePrice" double precision NOT NULL, - CONSTRAINT "t_crm_skus_pkey" PRIMARY KEY ("id"), - CONSTRAINT "t_crm_skus_spuId_fkey" FOREIGN KEY ("spuId") REFERENCES "t_crm_spus"("id") ON DELETE SET NULL + "data1" text, + "data2" text, + CONSTRAINT "t_meta_skus_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_meta_skus_spuId_fkey" FOREIGN KEY ("spuId") REFERENCES "t_meta_spus"("_id") ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS "t_crm_orders" ( - "id" bigint NOT NULL DEFAULT nextval('t_crm_orders_id_seq'::regclass), + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_orders_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('ORD', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, - "fk_orders" bigint, + "customerId" bigint, "total" double precision, - CONSTRAINT "t_crm_orders_pkey" PRIMARY KEY ("id"), - CONSTRAINT "t_crm_orders_fk_orders_fkey" FOREIGN KEY ("fk_orders") REFERENCES "t_crm_contacts"("id") ON DELETE SET NULL + "data1" text, + "data2" text, + CONSTRAINT "t_crm_orders_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_crm_orders_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("_id") ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS "t_crm_orderItems" ( - "id" bigint NOT NULL DEFAULT nextval('"t_crm_orderItems_id_seq"'::regclass), + "_id" bigint NOT NULL DEFAULT nextval('"t_crm_orderItems_id_seq"'::regclass), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('ITEM', true, 7, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, - "fk_sku" bigint, - "fk_order" bigint, + "skuId" bigint, + "orderId" bigint, "quantity" double precision NOT NULL, "unitPrice" double precision NOT NULL, - CONSTRAINT "t_crm_orderItems_pkey" PRIMARY KEY ("id"), - CONSTRAINT "t_crm_orderItems_fk_sku_fkey" FOREIGN KEY ("fk_sku") REFERENCES "t_crm_skus"("id") ON DELETE SET NULL, - CONSTRAINT "t_crm_orderItems_fk_order_fkey" FOREIGN KEY ("fk_order") REFERENCES "t_crm_orders"("id") ON DELETE CASCADE + "data1" text, + "data2" text, + CONSTRAINT "t_crm_orderItems_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_crm_orderItems_skuId_fkey" FOREIGN KEY ("skuId") REFERENCES "t_meta_skus"("_id") ON DELETE SET NULL, + CONSTRAINT "t_crm_orderItems_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "t_crm_orders"("_id") ON DELETE CASCADE ); -- ========================================================= -- 3. Bind sequence ownership & indexes -- ========================================================= -ALTER SEQUENCE "t_crm_contacts_id_seq" OWNED BY "t_crm_contacts"."id"; -ALTER SEQUENCE "t_crm_tags_id_seq" OWNED BY "t_crm_tags"."id"; -ALTER SEQUENCE "t_crm_spus_id_seq" OWNED BY "t_crm_spus"."id"; -ALTER SEQUENCE "t_crm_skus_id_seq" OWNED BY "t_crm_skus"."id"; -ALTER SEQUENCE "t_crm_orders_id_seq" OWNED BY "t_crm_orders"."id"; -ALTER SEQUENCE "t_crm_orderItems_id_seq" OWNED BY "t_crm_orderItems"."id"; -ALTER SEQUENCE "t_crm_contactRecords_id_seq" OWNED BY "t_crm_contactRecords"."id"; +ALTER SEQUENCE "t_crm_customer_id_seq" OWNED BY "t_crm_customer"."_id"; +ALTER SEQUENCE "t_crm_tags_id_seq" OWNED BY "t_crm_tags"."_id"; +ALTER SEQUENCE "t_crm_customerTags_id_seq" OWNED BY "t_crm_customerTags"."_id"; +ALTER SEQUENCE "t_crm_customerRecords_id_seq" OWNED BY "t_crm_customerRecords"."_id"; +ALTER SEQUENCE "t_meta_spus_id_seq" OWNED BY "t_meta_spus"."_id"; +ALTER SEQUENCE "t_meta_skus_id_seq" OWNED BY "t_meta_skus"."_id"; +ALTER SEQUENCE "t_crm_orders_id_seq" OWNED BY "t_crm_orders"."_id"; +ALTER SEQUENCE "t_crm_orderItems_id_seq" OWNED BY "t_crm_orderItems"."_id"; -CREATE INDEX IF NOT EXISTS "t_crm_contacts_assignee_id_idx" ON "t_crm_contacts" ("assigneeId"); -CREATE INDEX IF NOT EXISTS "t_crm_contactRecords_contact_id_idx" ON "t_crm_contactRecords" ("contactId"); +CREATE INDEX IF NOT EXISTS "t_crm_customer_assignee_id_idx" ON "t_crm_customer" ("assigneeId"); +CREATE INDEX IF NOT EXISTS "t_crm_customerRecords_customerId_idx" ON "t_crm_customerRecords" ("customerId"); +CREATE INDEX IF NOT EXISTS "t_crm_orders_customerId_idx" ON "t_crm_orders" ("customerId"); +CREATE INDEX IF NOT EXISTS "t_crm_orderItems_skuId_idx" ON "t_crm_orderItems" ("skuId"); +CREATE INDEX IF NOT EXISTS "t_crm_orderItems_orderId_idx" ON "t_crm_orderItems" ("orderId"); -- ========================================================= -- 4. NocoBase System Metadata Registration (Batch Operations) -- ========================================================= --- 4.1 Collection Category Registration ('CRM') +-- 4.1 Collection Category Registration ('CRM' and 'meta') INSERT INTO "collectionCategories" ("id", "name", "color", "sort", "createdAt", "updatedAt") SELECT (EXTRACT(EPOCH FROM NOW())::bigint * 1000), 'CRM', 'magenta', 1, NOW(), NOW() WHERE EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'collectionCategories') AND NOT EXISTS (SELECT 1 FROM "collectionCategories" WHERE "name" = 'CRM'); +INSERT INTO "collectionCategories" ("id", "name", "color", "sort", "createdAt", "updatedAt") +SELECT (EXTRACT(EPOCH FROM NOW())::bigint * 1000 + 1), 'meta', 'cyan', 2, NOW(), NOW() +WHERE EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'collectionCategories') + AND NOT EXISTS (SELECT 1 FROM "collectionCategories" WHERE "name" = 'meta'); + INSERT INTO "collectionCategory" ("categoryId", "collectionName", "createdAt", "updatedAt") SELECT c.id, col.name, NOW(), NOW() FROM "collectionCategories" c -CROSS JOIN (VALUES ('t_crm_contacts'), ('t_crm_tags'), ('t_crm_contactTags'), ('t_crm_contactRecords'), ('t_crm_spus'), ('t_crm_skus'), ('t_crm_orders'), ('t_crm_orderItems')) AS col(name) +CROSS JOIN (VALUES ('t_crm_customer'), ('t_crm_tags'), ('t_crm_customerTags'), ('t_crm_customerRecords'), ('t_meta_spus'), ('t_meta_skus'), ('t_crm_orders'), ('t_crm_orderItems')) AS col(name) WHERE c.name = 'CRM' AND EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'collectionCategory') AND NOT EXISTS ( SELECT 1 FROM "collectionCategory" cc WHERE cc."categoryId" = c.id AND cc."collectionName" = col.name ); +INSERT INTO "collectionCategory" ("categoryId", "collectionName", "createdAt", "updatedAt") +SELECT c.id, col.name, NOW(), NOW() +FROM "collectionCategories" c +CROSS JOIN (VALUES ('t_meta_spus'), ('t_meta_skus')) AS col(name) +WHERE c.name = 'meta' + AND EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'collectionCategory') + AND NOT EXISTS ( + SELECT 1 FROM "collectionCategory" cc WHERE cc."categoryId" = c.id AND cc."collectionName" = col.name + ); + -- 4.2 Collections Registration & Target Key Configuration (sort starting from 101) INSERT INTO "collections" ("key", "name", "title", "inherit", "hidden", "options", "sort") SELECT - 'crm_' || v.name, + v.name, v.name, v.title, false, @@ -179,14 +291,14 @@ SELECT v.opts::json, v.sort_val FROM (VALUES - ('t_crm_tags', '标签', false, 100, '{"template": "general", "tableName": "t_crm_tags", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "tag", "unavailableActions": []}'), - ('t_crm_contacts', '联系人', false, 110, '{"template": "general", "tableName": "t_crm_contacts", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "name", "unavailableActions": []}'), - ('t_crm_contactTags', '客户标签', true, 111, '{"template": "general", "timestamps": true, "autoGenId": false, "autoCreate": true, "isThrough": true, "sortable": false}'), - ('t_crm_contactRecords', '客户沟通记录', false, 112, '{"template": "general", "tableName": "t_crm_contactRecords", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "title", "unavailableActions": []}'), - ('t_crm_spus', '产品(SPU)', false, 121, '{"template": "general", "tableName": "t_crm_spus", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "productName", "unavailableActions": []}'), - ('t_crm_skus', '商品规格(SKU)', false, 122, '{"template": "general", "tableName": "t_crm_skus", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "packageSpecDisplay", "unavailableActions": []}'), - ('t_crm_orders', '订单', false, 131, '{"template": "general", "tableName": "t_crm_orders", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "id", "unavailableActions": []}'), - ('t_crm_orderItems', '订单明细', false, 132, '{"template": "general", "tableName": "t_crm_orderItems", "timestamps": false, "autoGenId": false, "from": "dbsync", "underscored": false, "titleField": "id", "unavailableActions": []}') + ('t_crm_tags', '标签', false, 100, '{"template": "general", "tableName": "t_crm_tags", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "tag", "unavailableActions": []}'), + ('t_crm_customer', '顾客', false, 110, '{"template": "general", "tableName": "t_crm_customer", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "name", "unavailableActions": []}'), + ('t_crm_customerTags', '顾客标签', true, 111, '{"template": "general", "timestamps": true, "autoGenId": true, "autoCreate": true, "isThrough": true, "sortable": false}'), + ('t_crm_customerRecords', '顾客沟通记录', false, 112, '{"template": "general", "tableName": "t_crm_customerRecords", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "title", "unavailableActions": []}'), + ('t_meta_spus', '产品(SPU)', false, 121, '{"template": "general", "tableName": "t_meta_spus", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "productName", "unavailableActions": []}'), + ('t_meta_skus', '商品规格(SKU)', false, 122, '{"template": "general", "tableName": "t_meta_skus", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "packageSpecDisplay", "unavailableActions": []}'), + ('t_crm_orders', '订单', false, 131, '{"template": "general", "tableName": "t_crm_orders", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "code", "unavailableActions": []}'), + ('t_crm_orderItems', '订单明细', false, 132, '{"template": "general", "tableName": "t_crm_orderItems", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "code", "unavailableActions": []}') ) AS v(name, title, hidden_val, sort_val, opts) WHERE EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'collections') ON CONFLICT ("name") DO UPDATE SET @@ -196,6 +308,10 @@ ON CONFLICT ("name") DO UPDATE SET "options" = EXCLUDED."options"; -- 4.3 Fields Registration & Display Titles (Including Foreign Key, M2M & O2M Association Fields) +DELETE FROM "fields" +WHERE EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'fields') + AND "collectionName" IN ('t_crm_customer', 't_crm_customerRecords', 't_crm_tags', 't_crm_customerTags', 't_meta_spus', 't_meta_skus', 't_crm_orders', 't_crm_orderItems'); + INSERT INTO "fields" ("key", "name", "type", "interface", "options", "collectionName", "sort") SELECT 'f_' || v.col_name || '_' || v.f_name, @@ -206,90 +322,117 @@ SELECT v.col_name, v.sort_val FROM (VALUES - -- t_crm_contacts - ('t_crm_contacts', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber"}}', 1), - ('t_crm_contacts', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_contacts', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_contacts', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_contacts', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_contacts', 'assignee', 'belongsTo', 'm2o', '{"target": "users", "foreignKey": "assigneeId", "targetKey": "id", "uiSchema": {"type": "object", "title": "负责人", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}}}', 6), - ('t_crm_contacts', 'name', 'string', 'input', '{"allowNull": true, "field": "name", "uiSchema": {"type": "string", "title": "姓名", "x-component": "Input"}}', 7), - ('t_crm_contacts', 'phone', 'string', 'input', '{"allowNull": true, "field": "phone", "uiSchema": {"type": "string", "title": "手机号码", "x-component": "Input"}}', 8), - ('t_crm_contacts', 'age', 'bigInt', 'integer', '{"allowNull": true, "field": "age", "uiSchema": {"type": "number", "title": "年龄", "x-component": "InputNumber"}}', 9), - ('t_crm_contacts', 'gender', 'string', 'radioGroup', '{"allowNull": true, "field": "gender", "uiSchema": {"type": "string", "title": "性别", "x-component": "Radio.Group", "enum": [{"value": "M", "label": "男", "color": "blue"}, {"value": "F", "label": "女", "color": "red"}, {"value": "Unknown", "label": "未知", "color": "default"}]}}', 10), - ('t_crm_contacts', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "sea", "uiSchema": {"type": "string", "title": "阶段状态", "x-component": "Select", "enum": [{"value": "sea", "label": "公海", "color": "blue"}, {"value": "assigned", "label": "已认领", "color": "magenta"}, {"value": "following", "label": "沟通中", "color": "green"}, {"value": "opportunity", "label": "高潜", "color": "lime"}, {"value": "customer", "label": "已购买", "color": "purple"}, {"value": "invalid", "label": "无效", "color": "default"}, {"value": "lost", "label": "流失", "color": "default"}]}}', 11), - ('t_crm_contacts', 'tags', 'belongsToMany', 'm2m', '{"target": "t_crm_tags", "through": "t_crm_contactTags", "foreignKey": "contact", "otherKey": "tag", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "联系人标签", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 12), - ('t_crm_contacts', 'records', 'hasMany', 'o2m', '{"target": "t_crm_contactRecords", "foreignKey": "contactId", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "沟通记录", "x-component": "AssociationField"}}', 13), - - -- t_crm_contactRecords - ('t_crm_contactRecords', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber"}}', 1), - ('t_crm_contactRecords', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_contactRecords', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_contactRecords', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_contactRecords', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_contactRecords', 'contact', 'belongsTo', 'm2o', '{"target": "t_crm_contacts", "foreignKey": "contactId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联客户(联系人)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "name"}}}}', 6), - ('t_crm_contactRecords', 'title', 'string', 'input', '{"allowNull": true, "field": "title", "uiSchema": {"type": "string", "title": "沟通主题", "x-component": "Input"}}', 7), - ('t_crm_contactRecords', 'type', 'string', 'select', '{"allowNull": true, "field": "type", "defaultValue": "call", "uiSchema": {"type": "string", "title": "沟通方式", "x-component": "Select", "enum": [{"value": "call", "label": "电话沟通", "color": "blue"}, {"value": "meeting", "label": "当面拜访", "color": "magenta"}, {"value": "wechat", "label": "微信沟通", "color": "green"}, {"value": "email", "label": "邮件往来", "color": "purple"}, {"value": "other", "label": "其他", "color": "default"}]}}', 8), - ('t_crm_contactRecords', 'content', 'text', 'textarea', '{"allowNull": true, "field": "content", "uiSchema": {"type": "string", "title": "沟通内容", "x-component": "Input.TextArea"}}', 9), - ('t_crm_contactRecords', 'recordTime', 'datetimeTz', 'datetime', '{"field": "recordTime", "uiSchema": {"type": "datetime", "title": "沟通时间", "x-component": "DatePicker", "x-component-props": {"showTime": true}}}', 10), + -- t_crm_customer + ('t_crm_customer', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customer', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_customer', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_customer', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_crm_customer', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_crm_customer', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_crm_customer', 'assignee', 'belongsTo', 'm2o', '{"target": "users", "foreignKey": "assigneeId", "targetKey": "id", "uiSchema": {"type": "object", "title": "负责人", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}}}', 7), + ('t_crm_customer', 'name', 'string', 'input', '{"allowNull": true, "field": "name", "uiSchema": {"type": "string", "title": "姓名", "x-component": "Input"}}', 8), + ('t_crm_customer', 'phone', 'string', 'input', '{"allowNull": true, "field": "phone", "uiSchema": {"type": "string", "title": "手机号码", "x-component": "Input"}}', 9), + ('t_crm_customer', 'age', 'bigInt', 'integer', '{"allowNull": true, "field": "age", "uiSchema": {"type": "number", "title": "年龄", "x-component": "InputNumber"}}', 10), + ('t_crm_customer', 'gender', 'string', 'radioGroup', '{"allowNull": true, "field": "gender", "uiSchema": {"type": "string", "title": "性别", "x-component": "Radio.Group", "enum": [{"value": "M", "label": "男", "color": "blue"}, {"value": "F", "label": "女", "color": "red"}, {"value": "Unknown", "label": "未知", "color": "default"}]}}', 11), + ('t_crm_customer', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "sea", "uiSchema": {"type": "string", "title": "阶段状态", "x-component": "Select", "enum": [{"value": "sea", "label": "公海", "color": "blue"}, {"value": "assigned", "label": "已认领", "color": "magenta"}, {"value": "following", "label": "沟通中", "color": "green"}, {"value": "opportunity", "label": "高潜", "color": "lime"}, {"value": "customer", "label": "已购买", "color": "purple"}, {"value": "invalid", "label": "无效", "color": "default"}, {"value": "lost", "label": "流失", "color": "default"}]}}', 12), + ('t_crm_customer', 'tags', 'belongsToMany', 'm2m', '{"target": "t_crm_tags", "through": "t_crm_customerTags", "foreignKey": "customer", "otherKey": "tag", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "顾客标签", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 13), + ('t_crm_customer', 'records', 'hasMany', 'o2m', '{"target": "t_crm_customerRecords", "foreignKey": "customerId", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "沟通记录", "x-component": "AssociationField"}}', 14), + ('t_crm_customer', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 15), + ('t_crm_customer', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 16), + + -- t_crm_customerRecords + ('t_crm_customerRecords', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customerRecords', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_customerRecords', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_customerRecords', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_crm_customerRecords', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_crm_customerRecords', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_crm_customerRecords', 'customer', 'belongsTo', 'm2o', '{"target": "t_crm_customer", "foreignKey": "customerId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联顾客", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "name"}}}}', 7), + ('t_crm_customerRecords', 'title', 'string', 'input', '{"allowNull": true, "field": "title", "uiSchema": {"type": "string", "title": "沟通主题", "x-component": "Input"}}', 8), + ('t_crm_customerRecords', 'type', 'string', 'select', '{"allowNull": true, "field": "type", "defaultValue": "call", "uiSchema": {"type": "string", "title": "沟通方式", "x-component": "Select", "enum": [{"value": "call", "label": "电话沟通", "color": "blue"}, {"value": "meeting", "label": "当面拜访", "color": "magenta"}, {"value": "wechat", "label": "微信沟通", "color": "green"}, {"value": "email", "label": "邮件往来", "color": "purple"}, {"value": "other", "label": "其他", "color": "default"}]}}', 9), + ('t_crm_customerRecords', 'content', 'text', 'textarea', '{"allowNull": true, "field": "content", "uiSchema": {"type": "string", "title": "沟通内容", "x-component": "Input.TextArea"}}', 10), + ('t_crm_customerRecords', 'recordTime', 'datetimeTz', 'datetime', '{"field": "recordTime", "uiSchema": {"type": "datetime", "title": "沟通时间", "x-component": "DatePicker", "x-component-props": {"showTime": true}}}', 11), + ('t_crm_customerRecords', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 12), + ('t_crm_customerRecords', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_tags - ('t_crm_tags', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber"}}', 1), - ('t_crm_tags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_tags', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_tags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_tags', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_tags', 'tag', 'string', 'input', '{"allowNull": true, "field": "tag", "uiSchema": {"type": "string", "title": "标签名称", "x-component": "Input"}}', 6), - ('t_crm_tags', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "0", "uiSchema": {"type": "string", "title": "标签状态", "x-component": "Select", "enum": [{"value": "0", "label": "正常", "color": "blue"}, {"value": "1", "label": "禁用", "color": "default"}]}}', 7), - - -- t_crm_contactTags (Through Collection with Composite Primary Key) - ('t_crm_contactTags', 'contact', 'bigInt', 'integer', '{"primaryKey": true, "isForeignKey": true, "uiSchema": {"type": "number", "title": "contact", "x-component": "InputNumber", "x-read-pretty": true}}', 1), - ('t_crm_contactTags', 'tag', 'bigInt', 'integer', '{"primaryKey": true, "isForeignKey": true, "uiSchema": {"type": "number", "title": "tag", "x-component": "InputNumber", "x-read-pretty": true}}', 2), - - -- t_crm_spus - ('t_crm_spus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber"}}', 1), - ('t_crm_spus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_spus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_spus', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_spus', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_spus', 'productName', 'string', 'input', '{"allowNull": false, "field": "productName", "uiSchema": {"type": "string", "title": "产品名", "x-component": "Input"}}', 6), - ('t_crm_spus', 'spec', 'string', 'input', '{"allowNull": true, "field": "spec", "uiSchema": {"type": "string", "title": "品规", "x-component": "Input"}}', 7), - ('t_crm_spus', 'baseUnit', 'string', 'input', '{"allowNull": true, "field": "baseUnit", "uiSchema": {"type": "string", "title": "基本单位", "x-component": "Input"}}', 8), - ('t_crm_spus', 'unitMeasureValue', 'float', 'number', '{"allowNull": false, "field": "unitMeasureValue", "uiSchema": {"type": "number", "title": "最小单元计量数量", "x-component": "InputNumber"}}', 9), - ('t_crm_spus', 'unitMeasureUnit', 'string', 'input', '{"allowNull": true, "field": "unitMeasureUnit", "uiSchema": {"type": "string", "title": "最小单元计量单位", "x-component": "Input"}}', 10), - ('t_crm_spus', 'unitSpecDisplay', 'string', 'input', '{"allowNull": true, "field": "unitSpecDisplay", "uiSchema": {"type": "string", "title": "规格显示名称", "x-component": "Input"}}', 11), - - -- t_crm_skus - ('t_crm_skus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber"}}', 1), - ('t_crm_skus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_skus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_skus', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_skus', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_skus', 'spu', 'belongsTo', 'm2o', '{"target": "t_crm_spus", "foreignKey": "spuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联产品(SPU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "productName"}}}}', 6), - ('t_crm_skus', 'packageQty', 'float', 'number', '{"allowNull": false, "field": "packageQty", "uiSchema": {"type": "number", "title": "包装内数量", "x-component": "InputNumber"}}', 7), - ('t_crm_skus', 'saleUnit', 'string', 'input', '{"allowNull": true, "field": "saleUnit", "uiSchema": {"type": "string", "title": "销售单位", "x-component": "Input"}}', 8), - ('t_crm_skus', 'packageSpecDisplay', 'text', 'textarea', '{"allowNull": false, "field": "packageSpecDisplay", "uiSchema": {"type": "string", "title": "包装规格说明", "x-component": "Input.TextArea"}}', 9), - ('t_crm_skus', 'salePrice', 'float', 'number', '{"allowNull": false, "field": "salePrice", "uiSchema": {"type": "number", "title": "销售单价", "x-component": "InputNumber"}}', 10), + ('t_crm_tags', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_tags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_tags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_tags', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_crm_tags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_crm_tags', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_crm_tags', 'tag', 'string', 'input', '{"allowNull": true, "field": "tag", "uiSchema": {"type": "string", "title": "标签名称", "x-component": "Input"}}', 7), + ('t_crm_tags', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "0", "uiSchema": {"type": "string", "title": "标签状态", "x-component": "Select", "enum": [{"value": "0", "label": "正常", "color": "blue"}, {"value": "1", "label": "禁用", "color": "default"}]}}', 8), + ('t_crm_tags', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 9), + ('t_crm_tags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), + + -- t_crm_customerTags (Through Collection with surrogate _id) + ('t_crm_customerTags', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customerTags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_customerTags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_customerTags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), + ('t_crm_customerTags', 'customer', 'bigInt', 'integer', '{"primaryKey": false, "isForeignKey": true, "uiSchema": {"type": "number", "title": "顾客", "x-component": "InputNumber", "x-read-pretty": true}}', 5), + ('t_crm_customerTags', 'tag', 'bigInt', 'integer', '{"primaryKey": false, "isForeignKey": true, "uiSchema": {"type": "number", "title": "标签", "x-component": "InputNumber", "x-read-pretty": true}}', 6), + ('t_crm_customerTags', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 7), + ('t_crm_customerTags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 8), + + -- t_meta_spus + ('t_meta_spus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_meta_spus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_meta_spus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_meta_spus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_meta_spus', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_meta_spus', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_meta_spus', 'productName', 'string', 'input', '{"allowNull": false, "field": "productName", "uiSchema": {"type": "string", "title": "产品名", "x-component": "Input"}}', 7), + ('t_meta_spus', 'spec', 'string', 'input', '{"allowNull": true, "field": "spec", "uiSchema": {"type": "string", "title": "规格/剂型", "x-component": "Input"}}', 8), + ('t_meta_spus', 'baseUnit', 'string', 'input', '{"allowNull": true, "field": "baseUnit", "uiSchema": {"type": "string", "title": "基础计量单位", "x-component": "Input"}}', 9), + ('t_meta_spus', 'unitMeasureValue', 'float', 'number', '{"allowNull": false, "field": "unitMeasureValue", "uiSchema": {"type": "number", "title": "最小单元计量数量", "x-component": "InputNumber"}}', 10), + ('t_meta_spus', 'unitMeasureUnit', 'string', 'input', '{"allowNull": true, "field": "unitMeasureUnit", "uiSchema": {"type": "string", "title": "最小单元计量单位", "x-component": "Input"}}', 11), + ('t_meta_spus', 'unitSpecDisplay', 'string', 'input', '{"allowNull": true, "field": "unitSpecDisplay", "uiSchema": {"type": "string", "title": "规格显示名称", "x-component": "Input"}}', 12), + ('t_meta_spus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 13), + ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), + + -- t_meta_skus + ('t_meta_skus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_meta_skus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_meta_skus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_meta_skus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_meta_skus', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_meta_skus', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_meta_skus', 'spu', 'belongsTo', 'm2o', '{"target": "t_meta_spus", "foreignKey": "spuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联产品(SPU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "productName"}}}}', 7), + ('t_meta_skus', 'packageQty', 'float', 'number', '{"allowNull": false, "field": "packageQty", "uiSchema": {"type": "number", "title": "包装内数量", "x-component": "InputNumber"}}', 8), + ('t_meta_skus', 'saleUnit', 'string', 'input', '{"allowNull": true, "field": "saleUnit", "uiSchema": {"type": "string", "title": "销售单位", "x-component": "Input"}}', 9), + ('t_meta_skus', 'packageSpecDisplay', 'text', 'textarea', '{"allowNull": false, "field": "packageSpecDisplay", "uiSchema": {"type": "string", "title": "包装规格说明", "x-component": "Input.TextArea"}}', 10), + ('t_meta_skus', 'salePrice', 'float', 'number', '{"allowNull": false, "field": "salePrice", "uiSchema": {"type": "number", "title": "销售单价", "x-component": "InputNumber"}}', 11), + ('t_meta_skus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 12), + ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_orders - ('t_crm_orders', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber"}}', 1), - ('t_crm_orders', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_orders', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_orders', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_orders', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_orders', 'contact', 'belongsTo', 'm2o', '{"target": "t_crm_contacts", "foreignKey": "fk_orders", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联客户(联系人)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "name"}}}}', 6), - ('t_crm_orders', 'total', 'float', 'number', '{"allowNull": true, "field": "total", "uiSchema": {"type": "number", "title": "订单总金额", "x-component": "InputNumber"}}', 7), + ('t_crm_orders', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_orders', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_orders', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_orders', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_crm_orders', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_crm_orders', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_crm_orders', 'customer', 'belongsTo', 'm2o', '{"target": "t_crm_customer", "foreignKey": "customerId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联顾客", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "name"}}}}', 7), + ('t_crm_orders', 'total', 'float', 'number', '{"allowNull": true, "field": "total", "uiSchema": {"type": "number", "title": "订单总金额", "x-component": "InputNumber"}}', 8), + ('t_crm_orders', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 9), + ('t_crm_orders', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), -- t_crm_orderItems - ('t_crm_orderItems', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": true, "field": "id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber"}}', 1), - ('t_crm_orderItems', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 2), - ('t_crm_orderItems', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 3), - ('t_crm_orderItems', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), - ('t_crm_orderItems', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 5), - ('t_crm_orderItems', 'sku', 'belongsTo', 'm2o', '{"target": "t_crm_skus", "foreignKey": "fk_sku", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联商品规格(SKU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "packageSpecDisplay"}}}}', 6), - ('t_crm_orderItems', 'order', 'belongsTo', 'm2o', '{"target": "t_crm_orders", "foreignKey": "fk_order", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联订单", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "id"}}}}', 7), - ('t_crm_orderItems', 'quantity', 'float', 'number', '{"allowNull": false, "field": "quantity", "uiSchema": {"type": "number", "title": "数量", "x-component": "InputNumber"}}', 8), - ('t_crm_orderItems', 'unitPrice', 'float', 'number', '{"allowNull": false, "field": "unitPrice", "uiSchema": {"type": "number", "title": "单价", "x-component": "InputNumber"}}', 9) + ('t_crm_orderItems', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_orderItems', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), + ('t_crm_orderItems', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), + ('t_crm_orderItems', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), + ('t_crm_orderItems', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), + ('t_crm_orderItems', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), + ('t_crm_orderItems', 'sku', 'belongsTo', 'm2o', '{"target": "t_meta_skus", "foreignKey": "skuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联商品规格(SKU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "packageSpecDisplay"}}}}', 7), + ('t_crm_orderItems', 'order', 'belongsTo', 'm2o', '{"target": "t_crm_orders", "foreignKey": "orderId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联订单", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "code"}}}}', 8), + ('t_crm_orderItems', 'quantity', 'float', 'number', '{"allowNull": false, "field": "quantity", "uiSchema": {"type": "number", "title": "数量", "x-component": "InputNumber"}}', 9), + ('t_crm_orderItems', 'unitPrice', 'float', 'number', '{"allowNull": false, "field": "unitPrice", "uiSchema": {"type": "number", "title": "单价", "x-component": "InputNumber"}}', 10), + ('t_crm_orderItems', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 11), + ('t_crm_orderItems', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 12) ) AS v(col_name, f_name, f_type, f_iface, opts, sort_val) WHERE EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'fields') ON CONFLICT ("collectionName", "name") DO UPDATE SET @@ -306,8 +449,8 @@ FROM ( ) sub WHERE "fields".key = sub.key AND "fields"."sort" IS NULL; --- Batch Update primaryKey: true for all CRM tables' primary key fields (including composite keys) +-- Batch update primaryKey: true for all CRM/meta tables' primary key fields UPDATE "fields" SET "options" = (COALESCE("options"::jsonb, '{}'::jsonb) || '{"primaryKey": true}'::jsonb)::json -WHERE ("collectionName" IN ('t_crm_contacts', 't_crm_contactRecords', 't_crm_tags', 't_crm_spus', 't_crm_skus', 't_crm_orders', 't_crm_orderItems') AND "name" = 'id') - OR ("collectionName" = 't_crm_contactTags' AND "name" IN ('contact', 'tag')); +WHERE ("collectionName" IN ('t_crm_customer', 't_crm_customerRecords', 't_crm_tags', 't_meta_spus', 't_meta_skus', 't_crm_orders', 't_crm_orderItems') AND "name" = 'id') + OR ("collectionName" = 't_crm_customerTags' AND "name" = 'id'); From 26879a543ab94e7f9f2ab5a24582a41e84c29b6e Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 08:18:02 +0000 Subject: [PATCH 3/7] update model --- docker_nocobase/demo/nocobase-crm.sql | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docker_nocobase/demo/nocobase-crm.sql b/docker_nocobase/demo/nocobase-crm.sql index a1085f4..ee4d355 100644 --- a/docker_nocobase/demo/nocobase-crm.sql +++ b/docker_nocobase/demo/nocobase-crm.sql @@ -323,7 +323,7 @@ SELECT v.sort_val FROM (VALUES -- t_crm_customer - ('t_crm_customer', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customer', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customer', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customer', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customer', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -341,7 +341,7 @@ FROM (VALUES ('t_crm_customer', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 16), -- t_crm_customerRecords - ('t_crm_customerRecords', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customerRecords', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customerRecords', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customerRecords', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customerRecords', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -356,7 +356,7 @@ FROM (VALUES ('t_crm_customerRecords', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_tags - ('t_crm_tags', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_tags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_tags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_tags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_tags', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -368,7 +368,7 @@ FROM (VALUES ('t_crm_tags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), -- t_crm_customerTags (Through Collection with surrogate _id) - ('t_crm_customerTags', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_customerTags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customerTags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customerTags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customerTags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), @@ -378,14 +378,14 @@ FROM (VALUES ('t_crm_customerTags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 8), -- t_meta_spus - ('t_meta_spus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_meta_spus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_meta_spus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_meta_spus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_meta_spus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), ('t_meta_spus', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), ('t_meta_spus', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), ('t_meta_spus', 'productName', 'string', 'input', '{"allowNull": false, "field": "productName", "uiSchema": {"type": "string", "title": "产品名", "x-component": "Input"}}', 7), - ('t_meta_spus', 'spec', 'string', 'input', '{"allowNull": true, "field": "spec", "uiSchema": {"type": "string", "title": "规格/剂型", "x-component": "Input"}}', 8), + ('t_meta_spus', 'spec', 'string', 'input', '{"allowNull": true, "field": "spec", "uiSchema": {"type": "string", "title": "规格", "x-component": "Input"}}', 8), ('t_meta_spus', 'baseUnit', 'string', 'input', '{"allowNull": true, "field": "baseUnit", "uiSchema": {"type": "string", "title": "基础计量单位", "x-component": "Input"}}', 9), ('t_meta_spus', 'unitMeasureValue', 'float', 'number', '{"allowNull": false, "field": "unitMeasureValue", "uiSchema": {"type": "number", "title": "最小单元计量数量", "x-component": "InputNumber"}}', 10), ('t_meta_spus', 'unitMeasureUnit', 'string', 'input', '{"allowNull": true, "field": "unitMeasureUnit", "uiSchema": {"type": "string", "title": "最小单元计量单位", "x-component": "Input"}}', 11), @@ -394,7 +394,7 @@ FROM (VALUES ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), -- t_meta_skus - ('t_meta_skus', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_meta_skus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_meta_skus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_meta_skus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_meta_skus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -409,7 +409,7 @@ FROM (VALUES ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_orders - ('t_crm_orders', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_orders', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_orders', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_orders', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_orders', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -421,7 +421,7 @@ FROM (VALUES ('t_crm_orders', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), -- t_crm_orderItems - ('t_crm_orderItems', 'id', 'bigInt', 'integer', '{"allowNull": true, "primaryKey": true, "autoIncrement": false, "snowflakeId": true, "field": "_id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber", "x-read-pretty": true}}', 1), + ('t_crm_orderItems', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_orderItems', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_orderItems', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_orderItems', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), From 4dcb144a3283e3626aa6151f56213e5bc0eaa67f Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 08:28:50 +0000 Subject: [PATCH 4/7] updates --- docker_nocobase/demo/nocobase-crm.sql | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docker_nocobase/demo/nocobase-crm.sql b/docker_nocobase/demo/nocobase-crm.sql index ee4d355..813b200 100644 --- a/docker_nocobase/demo/nocobase-crm.sql +++ b/docker_nocobase/demo/nocobase-crm.sql @@ -111,7 +111,7 @@ CREATE TABLE IF NOT EXISTS "t_crm_customer" ( CREATE TABLE IF NOT EXISTS "t_crm_tags" ( "_id" bigint NOT NULL DEFAULT nextval('"t_crm_tags_id_seq"'::regclass), - "code" character varying(64) NOT NULL DEFAULT generate_biz_code('TAG', true, 5, 'base32'), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('TAG', false, 5, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -126,7 +126,7 @@ CREATE TABLE IF NOT EXISTS "t_crm_tags" ( -- Many-to-Many Junction Table between t_crm_customer and t_crm_tags CREATE TABLE IF NOT EXISTS "t_crm_customerTags" ( "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customerTags_id_seq"'::regclass), - "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CTAG', true, 6, 'base32'), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CTAG', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "customer" bigint NOT NULL, @@ -160,7 +160,7 @@ CREATE TABLE IF NOT EXISTS "t_crm_customerRecords" ( CREATE TABLE IF NOT EXISTS "t_meta_spus" ( "_id" bigint NOT NULL DEFAULT nextval('"t_meta_spus_id_seq"'::regclass), - "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SPU', true, 6, 'base32'), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SPU', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -170,7 +170,7 @@ CREATE TABLE IF NOT EXISTS "t_meta_spus" ( "baseUnit" character varying(255), "unitMeasureValue" double precision NOT NULL, "unitMeasureUnit" character varying(255), - "unitSpecDisplay" character varying(255), + "spuDisplayName" character varying(255), "data1" text, "data2" text, CONSTRAINT "t_meta_spus_pkey" PRIMARY KEY ("_id") @@ -178,7 +178,7 @@ CREATE TABLE IF NOT EXISTS "t_meta_spus" ( CREATE TABLE IF NOT EXISTS "t_meta_skus" ( "_id" bigint NOT NULL DEFAULT nextval('"t_meta_skus_id_seq"'::regclass), - "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SKU', true, 6, 'base32'), + "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SKU', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -186,7 +186,7 @@ CREATE TABLE IF NOT EXISTS "t_meta_skus" ( "spuId" bigint, "packageQty" double precision NOT NULL, "saleUnit" character varying(255), - "packageSpecDisplay" text NOT NULL, + "skuDisplayName" text NOT NULL, "salePrice" double precision NOT NULL, "data1" text, "data2" text, @@ -296,7 +296,7 @@ FROM (VALUES ('t_crm_customerTags', '顾客标签', true, 111, '{"template": "general", "timestamps": true, "autoGenId": true, "autoCreate": true, "isThrough": true, "sortable": false}'), ('t_crm_customerRecords', '顾客沟通记录', false, 112, '{"template": "general", "tableName": "t_crm_customerRecords", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "title", "unavailableActions": []}'), ('t_meta_spus', '产品(SPU)', false, 121, '{"template": "general", "tableName": "t_meta_spus", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "productName", "unavailableActions": []}'), - ('t_meta_skus', '商品规格(SKU)', false, 122, '{"template": "general", "tableName": "t_meta_skus", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "packageSpecDisplay", "unavailableActions": []}'), + ('t_meta_skus', '商品规格(SKU)', false, 122, '{"template": "general", "tableName": "t_meta_skus", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "skuDisplayName", "unavailableActions": []}'), ('t_crm_orders', '订单', false, 131, '{"template": "general", "tableName": "t_crm_orders", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "code", "unavailableActions": []}'), ('t_crm_orderItems', '订单明细', false, 132, '{"template": "general", "tableName": "t_crm_orderItems", "timestamps": false, "autoGenId": true, "from": "dbsync", "underscored": false, "titleField": "code", "unavailableActions": []}') ) AS v(name, title, hidden_val, sort_val, opts) @@ -389,7 +389,7 @@ FROM (VALUES ('t_meta_spus', 'baseUnit', 'string', 'input', '{"allowNull": true, "field": "baseUnit", "uiSchema": {"type": "string", "title": "基础计量单位", "x-component": "Input"}}', 9), ('t_meta_spus', 'unitMeasureValue', 'float', 'number', '{"allowNull": false, "field": "unitMeasureValue", "uiSchema": {"type": "number", "title": "最小单元计量数量", "x-component": "InputNumber"}}', 10), ('t_meta_spus', 'unitMeasureUnit', 'string', 'input', '{"allowNull": true, "field": "unitMeasureUnit", "uiSchema": {"type": "string", "title": "最小单元计量单位", "x-component": "Input"}}', 11), - ('t_meta_spus', 'unitSpecDisplay', 'string', 'input', '{"allowNull": true, "field": "unitSpecDisplay", "uiSchema": {"type": "string", "title": "规格显示名称", "x-component": "Input"}}', 12), + ('t_meta_spus', 'spuDisplayName', 'string', 'input', '{"allowNull": true, "field": "spuDisplayName", "uiSchema": {"type": "string", "title": "SPU展示名", "x-component": "Input"}}', 12), ('t_meta_spus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 13), ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), @@ -403,7 +403,7 @@ FROM (VALUES ('t_meta_skus', 'spu', 'belongsTo', 'm2o', '{"target": "t_meta_spus", "foreignKey": "spuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联产品(SPU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "productName"}}}}', 7), ('t_meta_skus', 'packageQty', 'float', 'number', '{"allowNull": false, "field": "packageQty", "uiSchema": {"type": "number", "title": "包装内数量", "x-component": "InputNumber"}}', 8), ('t_meta_skus', 'saleUnit', 'string', 'input', '{"allowNull": true, "field": "saleUnit", "uiSchema": {"type": "string", "title": "销售单位", "x-component": "Input"}}', 9), - ('t_meta_skus', 'packageSpecDisplay', 'text', 'textarea', '{"allowNull": false, "field": "packageSpecDisplay", "uiSchema": {"type": "string", "title": "包装规格说明", "x-component": "Input.TextArea"}}', 10), + ('t_meta_skus', 'skuDisplayName', 'text', 'textarea', '{"allowNull": false, "field": "skuDisplayName", "uiSchema": {"type": "string", "title": "SKU展示名", "x-component": "Input.TextArea"}}', 10), ('t_meta_skus', 'salePrice', 'float', 'number', '{"allowNull": false, "field": "salePrice", "uiSchema": {"type": "number", "title": "销售单价", "x-component": "InputNumber"}}', 11), ('t_meta_skus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 12), ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), @@ -427,7 +427,7 @@ FROM (VALUES ('t_crm_orderItems', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), ('t_crm_orderItems', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), ('t_crm_orderItems', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), - ('t_crm_orderItems', 'sku', 'belongsTo', 'm2o', '{"target": "t_meta_skus", "foreignKey": "skuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联商品规格(SKU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "packageSpecDisplay"}}}}', 7), + ('t_crm_orderItems', 'sku', 'belongsTo', 'm2o', '{"target": "t_meta_skus", "foreignKey": "skuId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联商品规格(SKU)", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "skuDisplayName"}}}}', 7), ('t_crm_orderItems', 'order', 'belongsTo', 'm2o', '{"target": "t_crm_orders", "foreignKey": "orderId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联订单", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "code"}}}}', 8), ('t_crm_orderItems', 'quantity', 'float', 'number', '{"allowNull": false, "field": "quantity", "uiSchema": {"type": "number", "title": "数量", "x-component": "InputNumber"}}', 9), ('t_crm_orderItems', 'unitPrice', 'float', 'number', '{"allowNull": false, "field": "unitPrice", "uiSchema": {"type": "number", "title": "单价", "x-component": "InputNumber"}}', 10), From acba4cf294a1649f5e018112cecdb265de354951 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 11:12:04 +0000 Subject: [PATCH 5/7] update nocobase model --- docker_nocobase/demo/nocobase-crm.sql | 122 ++++++++++++++++---------- 1 file changed, 77 insertions(+), 45 deletions(-) diff --git a/docker_nocobase/demo/nocobase-crm.sql b/docker_nocobase/demo/nocobase-crm.sql index 813b200..5096e5b 100644 --- a/docker_nocobase/demo/nocobase-crm.sql +++ b/docker_nocobase/demo/nocobase-crm.sql @@ -6,7 +6,7 @@ - Built-in NocoBase metadata registration (categories, collections & fields) - Association metadata (m2o, m2m, o2m / belongsTo, belongsToMany, hasMany) - Collection sort numbers starting from 101 - - Snowflake ID style primary keys with _id suffix + - Snowflake ID style primary keys with id column */ -- ========================================================= @@ -88,11 +88,11 @@ CREATE SEQUENCE IF NOT EXISTS "t_crm_orders_id_seq"; CREATE SEQUENCE IF NOT EXISTS "t_crm_orderItems_id_seq"; -- ========================================================= --- 2. Main tables (Audit columns placed immediately after _id) +-- 2. Main tables (Audit columns placed immediately after id) -- ========================================================= CREATE TABLE IF NOT EXISTS "t_crm_customer" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customer_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_customer_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CUST', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -106,11 +106,11 @@ CREATE TABLE IF NOT EXISTS "t_crm_customer" ( "state" character varying(255) DEFAULT 'sea', "data1" text, "data2" text, - CONSTRAINT "t_crm_customer_pkey" PRIMARY KEY ("_id") + CONSTRAINT "t_crm_customer_pkey" PRIMARY KEY ("id") ); CREATE TABLE IF NOT EXISTS "t_crm_tags" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_tags_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_tags_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('TAG', false, 5, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -120,12 +120,12 @@ CREATE TABLE IF NOT EXISTS "t_crm_tags" ( "state" character varying(255) DEFAULT '0', "data1" text, "data2" text, - CONSTRAINT "t_crm_tags_pkey" PRIMARY KEY ("_id") + CONSTRAINT "t_crm_tags_pkey" PRIMARY KEY ("id") ); -- Many-to-Many Junction Table between t_crm_customer and t_crm_tags CREATE TABLE IF NOT EXISTS "t_crm_customerTags" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customerTags_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_customerTags_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CTAG', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -133,15 +133,15 @@ CREATE TABLE IF NOT EXISTS "t_crm_customerTags" ( "tag" bigint NOT NULL, "data1" text, "data2" text, - CONSTRAINT "t_crm_customerTags_pkey" PRIMARY KEY ("_id"), + CONSTRAINT "t_crm_customerTags_pkey" PRIMARY KEY ("id"), CONSTRAINT "t_crm_customerTags_customer_tag_uk" UNIQUE ("customer", "tag"), - CONSTRAINT "t_crm_customerTags_customer_fkey" FOREIGN KEY ("customer") REFERENCES "t_crm_customer"("_id") ON DELETE CASCADE, - CONSTRAINT "t_crm_customerTags_tag_fkey" FOREIGN KEY ("tag") REFERENCES "t_crm_tags"("_id") ON DELETE CASCADE + CONSTRAINT "t_crm_customerTags_customer_fkey" FOREIGN KEY ("customer") REFERENCES "t_crm_customer"("id") ON DELETE CASCADE, + CONSTRAINT "t_crm_customerTags_tag_fkey" FOREIGN KEY ("tag") REFERENCES "t_crm_tags"("id") ON DELETE CASCADE ); -- One-to-Many Table for Customer Communication Records CREATE TABLE IF NOT EXISTS "t_crm_customerRecords" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_customerRecords_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_customerRecords_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('CREC', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -154,12 +154,12 @@ CREATE TABLE IF NOT EXISTS "t_crm_customerRecords" ( "recordTime" timestamp with time zone DEFAULT CURRENT_TIMESTAMP, "data1" text, "data2" text, - CONSTRAINT "t_crm_customerRecords_pkey" PRIMARY KEY ("_id"), - CONSTRAINT "t_crm_customerRecords_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("_id") ON DELETE CASCADE + CONSTRAINT "t_crm_customerRecords_pkey" PRIMARY KEY ("id"), + CONSTRAINT "t_crm_customerRecords_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("id") ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS "t_meta_spus" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_meta_spus_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_meta_spus_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SPU', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -173,11 +173,11 @@ CREATE TABLE IF NOT EXISTS "t_meta_spus" ( "spuDisplayName" character varying(255), "data1" text, "data2" text, - CONSTRAINT "t_meta_spus_pkey" PRIMARY KEY ("_id") + CONSTRAINT "t_meta_spus_pkey" PRIMARY KEY ("id") ); CREATE TABLE IF NOT EXISTS "t_meta_skus" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_meta_skus_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_meta_skus_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('SKU', false, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -190,27 +190,28 @@ CREATE TABLE IF NOT EXISTS "t_meta_skus" ( "salePrice" double precision NOT NULL, "data1" text, "data2" text, - CONSTRAINT "t_meta_skus_pkey" PRIMARY KEY ("_id"), - CONSTRAINT "t_meta_skus_spuId_fkey" FOREIGN KEY ("spuId") REFERENCES "t_meta_spus"("_id") ON DELETE SET NULL + CONSTRAINT "t_meta_skus_pkey" PRIMARY KEY ("id"), + CONSTRAINT "t_meta_skus_spuId_fkey" FOREIGN KEY ("spuId") REFERENCES "t_meta_spus"("id") ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS "t_crm_orders" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_orders_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_orders_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('ORD', true, 6, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, "customerId" bigint, + "status" character varying(255) DEFAULT 'pending', "total" double precision, "data1" text, "data2" text, - CONSTRAINT "t_crm_orders_pkey" PRIMARY KEY ("_id"), - CONSTRAINT "t_crm_orders_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("_id") ON DELETE SET NULL + CONSTRAINT "t_crm_orders_pkey" PRIMARY KEY ("id"), + CONSTRAINT "t_crm_orders_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "t_crm_customer"("id") ON DELETE SET NULL ); CREATE TABLE IF NOT EXISTS "t_crm_orderItems" ( - "_id" bigint NOT NULL DEFAULT nextval('"t_crm_orderItems_id_seq"'::regclass), + "id" bigint NOT NULL DEFAULT nextval('"t_crm_orderItems_id_seq"'::regclass), "code" character varying(64) NOT NULL DEFAULT generate_biz_code('ITEM', true, 7, 'base32'), "createdAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdById" bigint, @@ -222,22 +223,22 @@ CREATE TABLE IF NOT EXISTS "t_crm_orderItems" ( "unitPrice" double precision NOT NULL, "data1" text, "data2" text, - CONSTRAINT "t_crm_orderItems_pkey" PRIMARY KEY ("_id"), - CONSTRAINT "t_crm_orderItems_skuId_fkey" FOREIGN KEY ("skuId") REFERENCES "t_meta_skus"("_id") ON DELETE SET NULL, - CONSTRAINT "t_crm_orderItems_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "t_crm_orders"("_id") ON DELETE CASCADE + CONSTRAINT "t_crm_orderItems_pkey" PRIMARY KEY ("id"), + CONSTRAINT "t_crm_orderItems_skuId_fkey" FOREIGN KEY ("skuId") REFERENCES "t_meta_skus"("id") ON DELETE SET NULL, + CONSTRAINT "t_crm_orderItems_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "t_crm_orders"("id") ON DELETE CASCADE ); -- ========================================================= -- 3. Bind sequence ownership & indexes -- ========================================================= -ALTER SEQUENCE "t_crm_customer_id_seq" OWNED BY "t_crm_customer"."_id"; -ALTER SEQUENCE "t_crm_tags_id_seq" OWNED BY "t_crm_tags"."_id"; -ALTER SEQUENCE "t_crm_customerTags_id_seq" OWNED BY "t_crm_customerTags"."_id"; -ALTER SEQUENCE "t_crm_customerRecords_id_seq" OWNED BY "t_crm_customerRecords"."_id"; -ALTER SEQUENCE "t_meta_spus_id_seq" OWNED BY "t_meta_spus"."_id"; -ALTER SEQUENCE "t_meta_skus_id_seq" OWNED BY "t_meta_skus"."_id"; -ALTER SEQUENCE "t_crm_orders_id_seq" OWNED BY "t_crm_orders"."_id"; -ALTER SEQUENCE "t_crm_orderItems_id_seq" OWNED BY "t_crm_orderItems"."_id"; +ALTER SEQUENCE "t_crm_customer_id_seq" OWNED BY "t_crm_customer"."id"; +ALTER SEQUENCE "t_crm_tags_id_seq" OWNED BY "t_crm_tags"."id"; +ALTER SEQUENCE "t_crm_customerTags_id_seq" OWNED BY "t_crm_customerTags"."id"; +ALTER SEQUENCE "t_crm_customerRecords_id_seq" OWNED BY "t_crm_customerRecords"."id"; +ALTER SEQUENCE "t_meta_spus_id_seq" OWNED BY "t_meta_spus"."id"; +ALTER SEQUENCE "t_meta_skus_id_seq" OWNED BY "t_meta_skus"."id"; +ALTER SEQUENCE "t_crm_orders_id_seq" OWNED BY "t_crm_orders"."id"; +ALTER SEQUENCE "t_crm_orderItems_id_seq" OWNED BY "t_crm_orderItems"."id"; CREATE INDEX IF NOT EXISTS "t_crm_customer_assignee_id_idx" ON "t_crm_customer" ("assigneeId"); CREATE INDEX IF NOT EXISTS "t_crm_customerRecords_customerId_idx" ON "t_crm_customerRecords" ("customerId"); @@ -323,7 +324,7 @@ SELECT v.sort_val FROM (VALUES -- t_crm_customer - ('t_crm_customer', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_crm_customer', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customer', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customer', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customer', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -341,7 +342,7 @@ FROM (VALUES ('t_crm_customer', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 16), -- t_crm_customerRecords - ('t_crm_customerRecords', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_crm_customerRecords', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customerRecords', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customerRecords', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customerRecords', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -356,7 +357,7 @@ FROM (VALUES ('t_crm_customerRecords', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_tags - ('t_crm_tags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_crm_tags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_tags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_tags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_tags', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -367,8 +368,8 @@ FROM (VALUES ('t_crm_tags', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 9), ('t_crm_tags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), - -- t_crm_customerTags (Through Collection with surrogate _id) - ('t_crm_customerTags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + -- t_crm_customerTags (Through Collection with surrogate id) + ('t_crm_customerTags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_customerTags', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_customerTags', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_customerTags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 4), @@ -378,7 +379,7 @@ FROM (VALUES ('t_crm_customerTags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 8), -- t_meta_spus - ('t_meta_spus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_meta_spus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_meta_spus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_meta_spus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_meta_spus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -394,7 +395,7 @@ FROM (VALUES ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), -- t_meta_skus - ('t_meta_skus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_meta_skus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_meta_skus', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_meta_skus', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_meta_skus', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -409,19 +410,21 @@ FROM (VALUES ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), -- t_crm_orders - ('t_crm_orders', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_crm_orders', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_orders', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_orders', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_orders', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), ('t_crm_orders', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), ('t_crm_orders', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), ('t_crm_orders', 'customer', 'belongsTo', 'm2o', '{"target": "t_crm_customer", "foreignKey": "customerId", "targetKey": "id", "uiSchema": {"type": "object", "title": "关联顾客", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "name"}}}}', 7), - ('t_crm_orders', 'total', 'float', 'number', '{"allowNull": true, "field": "total", "uiSchema": {"type": "number", "title": "订单总金额", "x-component": "InputNumber"}}', 8), - ('t_crm_orders', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 9), - ('t_crm_orders', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), + ('t_crm_orders', 'status', 'string', 'select', '{"allowNull": true, "field": "status", "defaultValue": "pending", "uiSchema": {"type": "string", "title": "订单状态", "x-component": "Select", "enum": [{"value": "pending", "label": "待支付", "color": "gold"}, {"value": "processing", "label": "处理中", "color": "blue"}, {"value": "shipped", "label": "已发货", "color": "purple"}, {"value": "completed", "label": "已完成", "color": "green"}, {"value": "cancelled", "label": "已取消", "color": "default"}]}}', 8), + ('t_crm_orders', 'total', 'float', 'number', '{"allowNull": true, "field": "total", "uiSchema": {"type": "number", "title": "订单总金额", "x-component": "InputNumber"}}', 9), + ('t_crm_orders', 'items', 'hasMany', 'o2m', '{"target": "t_crm_orderItems", "foreignKey": "orderId", "sourceKey": "id", "targetKey": "id", "onDelete": "SET NULL", "uiSchema": {"type": "array", "title": "订单明细", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 10), + ('t_crm_orders', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 11), + ('t_crm_orders', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 12), -- t_crm_orderItems - ('t_crm_orderItems', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "_id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), + ('t_crm_orderItems', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "明细ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), ('t_crm_orderItems', 'code', 'string', 'input', '{"allowNull": true, "field": "code", "uiSchema": {"type": "string", "title": "业务编码", "x-component": "Input", "x-read-pretty": true}}', 2), ('t_crm_orderItems', 'createdAt', 'datetimeTz', 'createdAt', '{"field": "createdAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Created at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 3), ('t_crm_orderItems', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), @@ -454,3 +457,32 @@ UPDATE "fields" SET "options" = (COALESCE("options"::jsonb, '{}'::jsonb) || '{"primaryKey": true}'::jsonb)::json WHERE ("collectionName" IN ('t_crm_customer', 't_crm_customerRecords', 't_crm_tags', 't_meta_spus', 't_meta_skus', 't_crm_orders', 't_crm_orderItems') AND "name" = 'id') OR ("collectionName" = 't_crm_customerTags' AND "name" = 'id'); + +-- ========================================================= +-- 5. Business Triggers (Auto calculate order.total from items) +-- ========================================================= +CREATE OR REPLACE FUNCTION fn_update_crm_order_total() +RETURNS TRIGGER AS $$ +DECLARE + v_order_id bigint; +BEGIN + v_order_id := COALESCE(NEW."orderId", OLD."orderId"); + + IF v_order_id IS NOT NULL THEN + UPDATE "t_crm_orders" + SET "total" = COALESCE(( + SELECT SUM("quantity" * "unitPrice") FROM "t_crm_orderItems" WHERE "orderId" = v_order_id + ), 0) + WHERE "id" = v_order_id; + END IF; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +DROP TRIGGER IF EXISTS trg_update_crm_order_total ON "t_crm_orderItems"; +CREATE TRIGGER trg_update_crm_order_total +AFTER INSERT OR UPDATE OF "quantity", "unitPrice", "orderId" OR DELETE +ON "t_crm_orderItems" +FOR EACH ROW +EXECUTE FUNCTION fn_update_crm_order_total(); From 81a1cddd07ce6a1d3ffe07a5569d9776c123662b Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Wed, 29 Jul 2026 11:43:18 +0000 Subject: [PATCH 6/7] update relateds records --- docker_nocobase/demo/nocobase-crm.sql | 39 ++++++++++++++++----------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/docker_nocobase/demo/nocobase-crm.sql b/docker_nocobase/demo/nocobase-crm.sql index 5096e5b..583ea57 100644 --- a/docker_nocobase/demo/nocobase-crm.sql +++ b/docker_nocobase/demo/nocobase-crm.sql @@ -101,6 +101,7 @@ CREATE TABLE IF NOT EXISTS "t_crm_customer" ( "assigneeId" bigint, "name" character varying(255), "phone" character varying(255), + "addr" text, "age" bigint, "gender" character varying(255), "state" character varying(255) DEFAULT 'sea', @@ -116,6 +117,7 @@ CREATE TABLE IF NOT EXISTS "t_crm_tags" ( "createdById" bigint, "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedById" bigint, + "dimension" character varying(255), "tag" character varying(255), "state" character varying(255) DEFAULT '0', "data1" text, @@ -245,6 +247,7 @@ CREATE INDEX IF NOT EXISTS "t_crm_customerRecords_customerId_idx" ON "t_crm_cust CREATE INDEX IF NOT EXISTS "t_crm_orders_customerId_idx" ON "t_crm_orders" ("customerId"); CREATE INDEX IF NOT EXISTS "t_crm_orderItems_skuId_idx" ON "t_crm_orderItems" ("skuId"); CREATE INDEX IF NOT EXISTS "t_crm_orderItems_orderId_idx" ON "t_crm_orderItems" ("orderId"); +CREATE INDEX IF NOT EXISTS "t_crm_tags_dimension_idx" ON "t_crm_tags" ("dimension"); -- ========================================================= -- 4. NocoBase System Metadata Registration (Batch Operations) @@ -333,13 +336,15 @@ FROM (VALUES ('t_crm_customer', 'assignee', 'belongsTo', 'm2o', '{"target": "users", "foreignKey": "assigneeId", "targetKey": "id", "uiSchema": {"type": "object", "title": "负责人", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}}}', 7), ('t_crm_customer', 'name', 'string', 'input', '{"allowNull": true, "field": "name", "uiSchema": {"type": "string", "title": "姓名", "x-component": "Input"}}', 8), ('t_crm_customer', 'phone', 'string', 'input', '{"allowNull": true, "field": "phone", "uiSchema": {"type": "string", "title": "手机号码", "x-component": "Input"}}', 9), - ('t_crm_customer', 'age', 'bigInt', 'integer', '{"allowNull": true, "field": "age", "uiSchema": {"type": "number", "title": "年龄", "x-component": "InputNumber"}}', 10), - ('t_crm_customer', 'gender', 'string', 'radioGroup', '{"allowNull": true, "field": "gender", "uiSchema": {"type": "string", "title": "性别", "x-component": "Radio.Group", "enum": [{"value": "M", "label": "男", "color": "blue"}, {"value": "F", "label": "女", "color": "red"}, {"value": "Unknown", "label": "未知", "color": "default"}]}}', 11), - ('t_crm_customer', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "sea", "uiSchema": {"type": "string", "title": "阶段状态", "x-component": "Select", "enum": [{"value": "sea", "label": "公海", "color": "blue"}, {"value": "assigned", "label": "已认领", "color": "magenta"}, {"value": "following", "label": "沟通中", "color": "green"}, {"value": "opportunity", "label": "高潜", "color": "lime"}, {"value": "customer", "label": "已购买", "color": "purple"}, {"value": "invalid", "label": "无效", "color": "default"}, {"value": "lost", "label": "流失", "color": "default"}]}}', 12), - ('t_crm_customer', 'tags', 'belongsToMany', 'm2m', '{"target": "t_crm_tags", "through": "t_crm_customerTags", "foreignKey": "customer", "otherKey": "tag", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "顾客标签", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 13), - ('t_crm_customer', 'records', 'hasMany', 'o2m', '{"target": "t_crm_customerRecords", "foreignKey": "customerId", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "沟通记录", "x-component": "AssociationField"}}', 14), - ('t_crm_customer', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 15), - ('t_crm_customer', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 16), + ('t_crm_customer', 'addr', 'text', 'textarea', '{"allowNull": true, "field": "addr", "uiSchema": {"type": "string", "title": "地址", "x-component": "Input.TextArea"}}', 10), + ('t_crm_customer', 'age', 'bigInt', 'integer', '{"allowNull": true, "field": "age", "uiSchema": {"type": "number", "title": "年龄", "x-component": "InputNumber"}}', 11), + ('t_crm_customer', 'gender', 'string', 'radioGroup', '{"allowNull": true, "field": "gender", "uiSchema": {"type": "string", "title": "性别", "x-component": "Radio.Group", "enum": [{"value": "M", "label": "男", "color": "blue"}, {"value": "F", "label": "女", "color": "red"}, {"value": "Unknown", "label": "未知", "color": "default"}]}}', 12), + ('t_crm_customer', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "sea", "uiSchema": {"type": "string", "title": "阶段状态", "x-component": "Select", "enum": [{"value": "sea", "label": "公海", "color": "blue"}, {"value": "assigned", "label": "已认领", "color": "magenta"}, {"value": "following", "label": "沟通中", "color": "green"}, {"value": "opportunity", "label": "高潜", "color": "lime"}, {"value": "customer", "label": "已购买", "color": "purple"}, {"value": "invalid", "label": "无效", "color": "default"}, {"value": "lost", "label": "流失", "color": "default"}]}}', 13), + ('t_crm_customer', 'tags', 'belongsToMany', 'm2m', '{"target": "t_crm_tags", "through": "t_crm_customerTags", "foreignKey": "customer", "otherKey": "tag", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "顾客标签", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 14), + ('t_crm_customer', 'records', 'hasMany', 'o2m', '{"target": "t_crm_customerRecords", "foreignKey": "customerId", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "沟通记录", "x-component": "AssociationField"}}', 15), + ('t_crm_customer', 'orders', 'hasMany', 'o2m', '{"target": "t_crm_orders", "foreignKey": "customerId", "sourceKey": "id", "targetKey": "id", "onDelete": "SET NULL", "uiSchema": {"type": "array", "title": "订单列表", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 16), + ('t_crm_customer', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 17), + ('t_crm_customer', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 18), -- t_crm_customerRecords ('t_crm_customerRecords', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "记录ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), @@ -363,10 +368,12 @@ FROM (VALUES ('t_crm_tags', 'createdBy', 'belongsTo', 'createdBy', '{"target": "users", "foreignKey": "createdById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Created by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 4), ('t_crm_tags', 'updatedAt', 'datetimeTz', 'updatedAt', '{"field": "updatedAt", "uiSchema": {"type": "datetime", "title": "{{t(\"Last updated at\")}}", "x-component": "DatePicker", "x-component-props": {"showTime": true}, "x-read-pretty": true}}', 5), ('t_crm_tags', 'updatedBy', 'belongsTo', 'updatedBy', '{"target": "users", "foreignKey": "updatedById", "targetKey": "id", "uiSchema": {"type": "object", "title": "{{t(\"Last updated by\")}}", "x-component": "AssociationField", "x-component-props": {"fieldNames": {"value": "id", "label": "nickname"}}, "x-read-pretty": true}}', 6), - ('t_crm_tags', 'tag', 'string', 'input', '{"allowNull": true, "field": "tag", "uiSchema": {"type": "string", "title": "标签名称", "x-component": "Input"}}', 7), - ('t_crm_tags', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "0", "uiSchema": {"type": "string", "title": "标签状态", "x-component": "Select", "enum": [{"value": "0", "label": "正常", "color": "blue"}, {"value": "1", "label": "禁用", "color": "default"}]}}', 8), - ('t_crm_tags', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 9), - ('t_crm_tags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 10), + ('t_crm_tags', 'dimension', 'string', 'input', '{"allowNull": true, "field": "dimension", "uiSchema": {"type": "string", "title": "标签维度", "x-component": "Input"}}', 7), + ('t_crm_tags', 'tag', 'string', 'input', '{"allowNull": true, "field": "tag", "uiSchema": {"type": "string", "title": "标签名称", "x-component": "Input"}}', 8), + ('t_crm_tags', 'state', 'string', 'select', '{"allowNull": true, "field": "state", "defaultValue": "0", "uiSchema": {"type": "string", "title": "标签状态", "x-component": "Select", "enum": [{"value": "0", "label": "正常", "color": "blue"}, {"value": "1", "label": "禁用", "color": "default"}]}}', 9), + ('t_crm_tags', 'customers', 'belongsToMany', 'm2m', '{"target": "t_crm_customer", "through": "t_crm_customerTags", "foreignKey": "tag", "otherKey": "customer", "sourceKey": "id", "targetKey": "id", "uiSchema": {"type": "array", "title": "关联顾客", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 10), + ('t_crm_tags', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 11), + ('t_crm_tags', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 12), -- t_crm_customerTags (Through Collection with surrogate id) ('t_crm_customerTags', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), @@ -391,8 +398,9 @@ FROM (VALUES ('t_meta_spus', 'unitMeasureValue', 'float', 'number', '{"allowNull": false, "field": "unitMeasureValue", "uiSchema": {"type": "number", "title": "最小单元计量数量", "x-component": "InputNumber"}}', 10), ('t_meta_spus', 'unitMeasureUnit', 'string', 'input', '{"allowNull": true, "field": "unitMeasureUnit", "uiSchema": {"type": "string", "title": "最小单元计量单位", "x-component": "Input"}}', 11), ('t_meta_spus', 'spuDisplayName', 'string', 'input', '{"allowNull": true, "field": "spuDisplayName", "uiSchema": {"type": "string", "title": "SPU展示名", "x-component": "Input"}}', 12), - ('t_meta_spus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 13), - ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), + ('t_meta_spus', 'skus', 'hasMany', 'o2m', '{"target": "t_meta_skus", "foreignKey": "spuId", "sourceKey": "id", "targetKey": "id", "onDelete": "SET NULL", "uiSchema": {"type": "array", "title": "规格列表(SKU)", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 13), + ('t_meta_spus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 14), + ('t_meta_spus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 15), -- t_meta_skus ('t_meta_skus', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), @@ -406,8 +414,9 @@ FROM (VALUES ('t_meta_skus', 'saleUnit', 'string', 'input', '{"allowNull": true, "field": "saleUnit", "uiSchema": {"type": "string", "title": "销售单位", "x-component": "Input"}}', 9), ('t_meta_skus', 'skuDisplayName', 'text', 'textarea', '{"allowNull": false, "field": "skuDisplayName", "uiSchema": {"type": "string", "title": "SKU展示名", "x-component": "Input.TextArea"}}', 10), ('t_meta_skus', 'salePrice', 'float', 'number', '{"allowNull": false, "field": "salePrice", "uiSchema": {"type": "number", "title": "销售单价", "x-component": "InputNumber"}}', 11), - ('t_meta_skus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 12), - ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 13), + ('t_meta_skus', 'orderItems', 'hasMany', 'o2m', '{"target": "t_crm_orderItems", "foreignKey": "skuId", "sourceKey": "id", "targetKey": "id", "onDelete": "SET NULL", "uiSchema": {"type": "array", "title": "销售明细", "x-component": "AssociationField", "x-component-props": {"multiple": true}}}', 12), + ('t_meta_skus', 'data1', 'text', 'textarea', '{"allowNull": true, "field": "data1", "uiSchema": {"type": "string", "title": "备注", "x-component": "Input.TextArea"}}', 13), + ('t_meta_skus', 'data2', 'text', 'textarea', '{"allowNull": true, "field": "data2", "uiSchema": {"type": "string", "title": "其他", "x-component": "Input.TextArea"}}', 14), -- t_crm_orders ('t_crm_orders', 'id', 'snowflakeId', 'snowflakeId', '{"autoIncrement": false, "primaryKey": true, "allowNull": false, "field": "id", "uiSchema": {"type": "number", "title": "订单ID", "x-component": "InputNumber", "x-component-props": {"stringMode": true, "separator": "0.00", "step": "1"}, "x-validator": "integer"}}', 1), From ed4edc35710c57083bbeb2b1a71f856cbfa39749 Mon Sep 17 00:00:00 2001 From: Bibo Hao Date: Thu, 30 Jul 2026 21:00:03 +0800 Subject: [PATCH 7/7] update clash restart --- docker_clash/demo/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_clash/demo/docker-compose.yml b/docker_clash/demo/docker-compose.yml index fd5d68d..c8b9202 100644 --- a/docker_clash/demo/docker-compose.yml +++ b/docker_clash/demo/docker-compose.yml @@ -20,7 +20,7 @@ services: image: quay.io/labnow/clash:latest container_name: svc-proxy-clash hostname: svc-proxy-clash - restart: unless-stopped + restart: always network_mode: host init: true cap_add: