diff --git a/data/magic-api/api/大屏数据/交易中心实时服务信息.ms b/data/magic-api/api/大屏数据/交易中心实时服务信息.ms index 96f2813..4cca8a3 100644 --- a/data/magic-api/api/大屏数据/交易中心实时服务信息.ms +++ b/data/magic-api/api/大屏数据/交易中心实时服务信息.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "交易中心实时服务信息", "createTime" : 1780877300000, - "updateTime" : null, + "updateTime" : 1781373000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,62 +17,63 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "交易中心实时服务信息:牦牛供应/待售/已售、剩余车位、进场车辆、供应商数量(只读)。牦牛=yak_trade_ear_tag_inventory;车位=yak_car_parking_zone;车辆=yak_car_record+yak_trade_entry_record;供应商=yak_sn_customer(SELLER)。", + "description" : "交易中心实时服务信息:gov_count_real_info,group_item=jygy,source_system=yzt。key=mngyzl/dsmn/ysmn/sycw/jccl/gyssl。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 +// gov_count_real_info(group_item=jygy, source_system=yzt) +// mngyzl 牦牛供应总量 +// dsmn 待售牦牛 +// ysmn 已售牦牛 +// sycw 剩余车位 +// jccl 进场车辆 +// gyssl 供应商数量 var sql = """ -SELECT - (SELECT COUNT(*) - FROM yak_trade_ear_tag_inventory) AS total_supply, - (SELECT COUNT(*) - FROM yak_trade_ear_tag_inventory - WHERE status IN ('AVAILABLE', 'LOCKED')) AS for_sale_yaks, - (SELECT COUNT(*) - FROM yak_trade_ear_tag_inventory - WHERE status = 'SOLD') AS sold_yaks, - (SELECT COALESCE(SUM(total_capacity - current_count), 0) - FROM yak_car_parking_zone - WHERE status = 'NORMAL') AS remaining_parking, - (SELECT COUNT(*) - FROM ( - SELECT plate_no AS vehicle_no - FROM yak_car_record - WHERE del_flag = '0' - AND entry_time >= CURRENT_DATE - UNION - SELECT vehicle_no - FROM yak_trade_entry_record - WHERE entered_at >= CURRENT_DATE - ) v) AS entering_vehicles, - (SELECT COUNT(*) - FROM yak_sn_customer - WHERE del_flag = '0' - AND customer_type = 'SELLER') AS supplier_count +SELECT key, name, value, tag, unit +FROM gov_count_real_info +WHERE group_item = 'jygy' + AND source_system = 'yzt' """ var rows = db.select(sql) -var row = rows && rows.length > 0 ? rows[0] : null -if (!row) { - return { - totalSupply: 0, - forSaleYaks: 0, - soldYaks: 0, - remainingParking: 0, - enteringVehicles: 0, - supplierCount: 0 +var valueMap = {} +var tagMap = {} +var unitMap = {} + +for (row in rows) { + valueMap[row.key] = row.value != null ? row.value : 0 + if (row.tag) { + tagMap[row.key] = row.tag + } + if (row.unit) { + unitMap[row.key] = row.unit } } +var pick = (key) => valueMap[key] != null ? valueMap[key] : 0 +var pickTag = (key) => tagMap[key] +var pickUnit = (key) => unitMap[key] + return { - totalSupply: row.totalSupply ? row.totalSupply : 0, - forSaleYaks: row.forSaleYaks ? row.forSaleYaks : 0, - soldYaks: row.soldYaks ? row.soldYaks : 0, - remainingParking: row.remainingParking ? row.remainingParking : 0, - enteringVehicles: row.enteringVehicles ? row.enteringVehicles : 0, - supplierCount: row.supplierCount ? row.supplierCount : 0 + totalSupply: pick('mngyzl'), + forSaleYaks: pick('dsmn'), + soldYaks: pick('ysmn'), + remainingParking: pick('sycw'), + enteringVehicles: pick('jccl'), + supplierCount: pick('gyssl'), + totalSupplyTag: pickTag('mngyzl'), + forSaleYaksTag: pickTag('dsmn'), + soldYaksTag: pickTag('ysmn'), + remainingParkingTag: pickTag('sycw'), + enteringVehiclesTag: pickTag('jccl'), + supplierCountTag: pickTag('gyssl'), + totalSupplyUnit: pickUnit('mngyzl'), + forSaleYaksUnit: pickUnit('dsmn'), + soldYaksUnit: pickUnit('ysmn'), + remainingParkingUnit: pickUnit('sycw'), + enteringVehiclesUnit: pickUnit('jccl'), + supplierCountUnit: pickUnit('gyssl') } diff --git a/data/magic-api/api/大屏数据/交易所牦牛成交数据.ms b/data/magic-api/api/大屏数据/交易所牦牛成交数据.ms index 33195b4..6d977cc 100644 --- a/data/magic-api/api/大屏数据/交易所牦牛成交数据.ms +++ b/data/magic-api/api/大屏数据/交易所牦牛成交数据.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "交易所牦牛成交数据", "createTime" : 1780877000000, - "updateTime" : 1780817847278, + "updateTime" : 1781369000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -28,27 +28,31 @@ "requestBody" : "", "headers" : [ ], "paths" : [ ], - "responseBody" : "{\n \"code\": -1,\n \"message\": \"系统内部出现错误\",\n \"data\": null,\n \"timestamp\": 1780817836665,\n \"executeTime\": 4\n}", - "description" : "交易所牦牛成交数据:近6个时间段的牦牛交易数量(头)与成交订单数量(单)趋势,数据源 yak_sn_order 已完成订单(只读查询)", + "responseBody" : null, + "description" : "交易所牦牛成交数据:gov_count_order_total,一条记录一单,SUM(yak_number) 为成交头数,COUNT(*) 为订单数。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ +// gov_count_order_total:一条记录 = 一笔订单 +// 牦牛成交头数:SUM(yak_number) +// 成交订单数:COUNT(*) +// 时间维度按 update_time 分桶(count_date 多为空) var buildSeries = (rows) => { var labels = [] - var yakTradingVolume = [] + var yakNumber = [] var orderCount = [] for (row in rows) { labels.push(row.label) - yakTradingVolume.push(row.yakVolume ? row.yakVolume : 0) - orderCount.push(row.orderCount ? row.orderCount : 0) + yakNumber.push(row.yakNumber != null ? row.yakNumber : 0) + orderCount.push(row.orderCount != null ? row.orderCount : 0) } return { labels: labels, - yakTradingVolume: yakTradingVolume, + yakNumber: yakNumber, orderCount: orderCount } } @@ -56,17 +60,15 @@ var buildSeries = (rows) => { var daySql = """ SELECT TO_CHAR(d.bucket_date, 'FMMM/FMDD') AS label, - COALESCE(SUM(o.quantity), 0) AS yak_volume, + COALESCE(SUM(o.yak_number), 0) AS yak_number, COUNT(o.id) AS order_count FROM ( SELECT (CURRENT_DATE - offs)::date AS bucket_date, offs FROM generate_series(5, 0, -1) AS offs ) d -LEFT JOIN yak_sn_order o - ON o.del_flag = '0' - AND o.status = 'COMPLETED' - AND o.transaction_time >= d.bucket_date - AND o.transaction_time < d.bucket_date + INTERVAL '1 day' +LEFT JOIN gov_count_order_total o + ON o.update_time >= d.bucket_date + AND o.update_time < d.bucket_date + INTERVAL '1 day' GROUP BY d.bucket_date, d.offs ORDER BY d.offs DESC """ @@ -74,17 +76,15 @@ ORDER BY d.offs DESC var weekSql = """ SELECT TO_CHAR(d.anchor_date, 'FMMM/FMDD') || '-' || TO_CHAR(d.anchor_date + 6, 'FMMM/FMDD') AS label, - COALESCE(SUM(o.quantity), 0) AS yak_volume, + COALESCE(SUM(o.yak_number), 0) AS yak_number, COUNT(o.id) AS order_count FROM ( SELECT (CURRENT_DATE - offs * 7)::date AS anchor_date, offs FROM generate_series(5, 0, -1) AS offs ) d -LEFT JOIN yak_sn_order o - ON o.del_flag = '0' - AND o.status = 'COMPLETED' - AND o.transaction_time >= d.anchor_date - AND o.transaction_time < d.anchor_date + INTERVAL '7 days' +LEFT JOIN gov_count_order_total o + ON o.update_time >= d.anchor_date + AND o.update_time < d.anchor_date + INTERVAL '7 days' GROUP BY d.anchor_date, d.offs ORDER BY d.offs DESC """ @@ -92,17 +92,15 @@ ORDER BY d.offs DESC var monthSql = """ SELECT TO_CHAR(d.month_start, 'YYYY/FMMM') AS label, - COALESCE(SUM(o.quantity), 0) AS yak_volume, + COALESCE(SUM(o.yak_number), 0) AS yak_number, COUNT(o.id) AS order_count FROM ( SELECT (date_trunc('month', CURRENT_DATE) - (offs || ' months')::interval)::date AS month_start, offs FROM generate_series(5, 0, -1) AS offs ) d -LEFT JOIN yak_sn_order o - ON o.del_flag = '0' - AND o.status = 'COMPLETED' - AND o.transaction_time >= d.month_start - AND o.transaction_time < d.month_start + INTERVAL '1 month' +LEFT JOIN gov_count_order_total o + ON o.update_time >= d.month_start + AND o.update_time < d.month_start + INTERVAL '1 month' GROUP BY d.month_start, d.offs ORDER BY d.offs DESC """ diff --git a/data/magic-api/api/大屏数据/地图迁徙数据.ms b/data/magic-api/api/大屏数据/地图迁徙数据.ms index 24ae4d5..329ebc7 100644 --- a/data/magic-api/api/大屏数据/地图迁徙数据.ms +++ b/data/magic-api/api/大屏数据/地图迁徙数据.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "地图迁徙数据", "createTime" : 1780882000000, - "updateTime" : 1781360000000, + "updateTime" : 1781377000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,12 +17,16 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "中央地图迁徙数据:销售网络/源地供应/红原本地出栏,数据源 yak_sn_order + yak_sn_customer(只读)。枢纽名称需与系统配置 mapHub.name 一致。", + "description" : "中央地图迁徙数据:gov_count_order_total。销售网络=origin_place含红原;源地供应=destination_place含红原;红原出栏=起终点均含红原。头数SUM(yak_number)。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读统计已完成订单;hubName 需与系统配置 mapHub.name 保持一致 +// gov_count_order_total:一条记录 = 一笔订单,头数 SUM(yak_number) +// outflow 销售网络:origin_place 含「红原」,按 destination_place 聚合 +// inflow 源地供应:destination_place 含「红原」,按 origin_place 聚合 +// local 红原出栏:destination_place 含「红原」且 origin_place 含「红原」,按 origin_place 乡镇聚合 +// hubName 需与系统配置 mapHub.name 保持一致 var hubName = '红原县' @@ -140,51 +144,55 @@ var buildDirectionalFlows = (rows, direction) => { var outflowSql = """ SELECT - COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.destination_place), ''), '未知') AS place_name, - COALESCE(SUM(o.quantity), 0) AS value, - MAX(COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.destination_place), ''), '未知')) AS sample_place -FROM yak_sn_order o -LEFT JOIN yak_sn_customer c ON c.id = o.buyer_id AND c.del_flag = '0' -WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' -GROUP BY COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.destination_place), ''), '未知') -HAVING COALESCE(SUM(o.quantity), 0) > 0 + COALESCE(NULLIF(TRIM(destination_place), ''), '未知') AS place_name, + COALESCE(SUM(yak_number), 0) AS value, + MAX(destination_place) AS sample_place +FROM gov_count_order_total +WHERE origin_place IS NOT NULL + AND position('红原' in origin_place) > 0 + AND destination_place IS NOT NULL + AND TRIM(destination_place) <> '' +GROUP BY COALESCE(NULLIF(TRIM(destination_place), ''), '未知') +HAVING COALESCE(SUM(yak_number), 0) > 0 ORDER BY value DESC, place_name """ var inflowSql = """ SELECT - COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.origin_place), ''), '未知') AS place_name, - COALESCE(SUM(o.quantity), 0) AS value, - MAX(COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.origin_place), ''), '未知')) AS sample_place -FROM yak_sn_order o -LEFT JOIN yak_sn_customer c ON c.id = o.seller_id AND c.del_flag = '0' -WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' -GROUP BY COALESCE(NULLIF(TRIM(c.region_name), ''), NULLIF(TRIM(o.origin_place), ''), '未知') -HAVING COALESCE(SUM(o.quantity), 0) > 0 + COALESCE(NULLIF(TRIM(origin_place), ''), '未知') AS place_name, + COALESCE(SUM(yak_number), 0) AS value, + MAX(origin_place) AS sample_place +FROM gov_count_order_total +WHERE destination_place IS NOT NULL + AND position('红原' in destination_place) > 0 + AND origin_place IS NOT NULL + AND TRIM(origin_place) <> '' +GROUP BY COALESCE(NULLIF(TRIM(origin_place), ''), '未知') +HAVING COALESCE(SUM(yak_number), 0) > 0 ORDER BY value DESC, place_name """ var localSql = """ SELECT COALESCE( - NULLIF((regexp_match(o.origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), - NULLIF(TRIM(o.origin_place), ''), + NULLIF((regexp_match(origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), + NULLIF(TRIM(origin_place), ''), '未知' ) AS place_name, - COALESCE(SUM(o.quantity), 0) AS value, - MAX(o.origin_place) AS sample_place -FROM yak_sn_order o -WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' - AND position('红原' in o.origin_place) > 0 + COALESCE(SUM(yak_number), 0) AS value, + MAX(origin_place) AS sample_place +FROM gov_count_order_total +WHERE destination_place IS NOT NULL + AND position('红原' in destination_place) > 0 + AND origin_place IS NOT NULL + AND position('红原' in origin_place) > 0 + AND TRIM(origin_place) <> '' GROUP BY COALESCE( - NULLIF((regexp_match(o.origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), - NULLIF(TRIM(o.origin_place), ''), + NULLIF((regexp_match(origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), + NULLIF(TRIM(origin_place), ''), '未知' ) -HAVING COALESCE(SUM(o.quantity), 0) > 0 +HAVING COALESCE(SUM(yak_number), 0) > 0 ORDER BY value DESC, place_name """ diff --git a/data/magic-api/api/大屏数据/实时交易统计.ms b/data/magic-api/api/大屏数据/实时交易统计.ms index 0a26799..5fcd976 100644 --- a/data/magic-api/api/大屏数据/实时交易统计.ms +++ b/data/magic-api/api/大屏数据/实时交易统计.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "实时交易统计", "createTime" : 1780876800000, - "updateTime" : 1780803706100, + "updateTime" : 1781365000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -14,7 +14,7 @@ "parameters" : [ { "name" : "dimension", "value" : null, - "description" : "时间维度:day(当天)/week(近一周)/month(近一月)/year(当年),不传则返回全部", + "description" : "时间维度:day(最新统计日)/week(近7天)/month(近30天),不传则返回全部", "required" : false, "dataType" : "String", "type" : null, @@ -29,82 +29,97 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "实时交易统计:牦牛交易总量、订单交易总量、销售商户数量、采购商户数量,按当天/近一周/近一月/当年统计(只读查询)", + "description" : "实时交易统计:数据源 gov_count_item(只读)。key=mnjyzl/jdjyzl/xsshsl/cgshsl,按 count_date 汇总。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读统计已完成订单,不修改任何数据 -var sql = """ -SELECT - dim, - COALESCE(SUM(quantity), 0) AS yak_total_volume, - COUNT(*) AS order_total_volume, - COUNT(DISTINCT seller_id) AS seller_count, - COUNT(DISTINCT buyer_id) AS buyer_count -FROM ( - SELECT 'day' AS dim, quantity, seller_id, buyer_id - FROM yak_sn_order - WHERE del_flag = '0' - AND status = 'COMPLETED' - AND transaction_time >= CURRENT_DATE - AND transaction_time < CURRENT_DATE + INTERVAL '1 day' - - UNION ALL - - SELECT 'week' AS dim, quantity, seller_id, buyer_id - FROM yak_sn_order - WHERE del_flag = '0' - AND status = 'COMPLETED' - AND transaction_time >= CURRENT_DATE - INTERVAL '6 days' - AND transaction_time < CURRENT_DATE + INTERVAL '1 day' - - UNION ALL +// gov_count_item 指标 key: +// mnjyzl 牦牛交易总量 +// jdjyzl 订单交易总量 +// xsshsl 销售商户数量 +// cgshsl 采购商户数量 +// 同一 key + count_date 可能有多条,取 MAX(value); +// 交易量类(mnjyzl/jdjyzl)在 week/month 内按日求和,商户数类取区间内最大值。 - SELECT 'month' AS dim, quantity, seller_id, buyer_id - FROM yak_sn_order - WHERE del_flag = '0' - AND status = 'COMPLETED' - AND transaction_time >= CURRENT_DATE - INTERVAL '29 days' - AND transaction_time < CURRENT_DATE + INTERVAL '1 day' - - UNION ALL - - SELECT 'year' AS dim, quantity, seller_id, buyer_id - FROM yak_sn_order - WHERE del_flag = '0' - AND status = 'COMPLETED' - AND transaction_time >= DATE_TRUNC('year', CURRENT_DATE) - AND transaction_time < CURRENT_DATE + INTERVAL '1 day' -) t -GROUP BY dim -ORDER BY dim +var sql = """ +WITH daily AS ( + SELECT + key, + count_date, + MAX(value) AS value + FROM gov_count_item + WHERE TRIM(name) IN ( + '牦牛交易总量', + '订单交易总量', + '销售商户数量', + '采购商户数量' + ) + GROUP BY key, count_date +), +anchor AS ( + SELECT MAX(count_date) AS latest_date FROM daily +), +day_stats AS ( + SELECT d.key, d.value + FROM daily d + CROSS JOIN anchor a + WHERE d.count_date = a.latest_date +), +week_stats AS ( + SELECT + d.key, + CASE + WHEN d.key IN ('mnjyzl', 'jdjyzl') THEN SUM(d.value) + ELSE MAX(d.value) + END AS value + FROM daily d + CROSS JOIN anchor a + WHERE d.count_date >= a.latest_date - INTERVAL '6 days' + GROUP BY d.key +), +month_stats AS ( + SELECT + d.key, + CASE + WHEN d.key IN ('mnjyzl', 'jdjyzl') THEN SUM(d.value) + ELSE MAX(d.value) + END AS value + FROM daily d + CROSS JOIN anchor a + WHERE d.count_date >= a.latest_date - INTERVAL '29 days' + GROUP BY d.key +) +SELECT 'day' AS dim, key, value FROM day_stats +UNION ALL +SELECT 'week' AS dim, key, value FROM week_stats +UNION ALL +SELECT 'month' AS dim, key, value FROM month_stats +ORDER BY dim, key """ var rows = db.select(sql) var createEmptyStats = () => { return { - yakTotalVolume: 0, - orderTotalVolume: 0, - sellerCount: 0, - buyerCount: 0 + mnjyzl: 0, + jdjyzl: 0, + xsshsl: 0, + cgshsl: 0 } } var result = { day: createEmptyStats(), week: createEmptyStats(), - month: createEmptyStats(), - year: createEmptyStats() + month: createEmptyStats() } for (row in rows) { - result[row.dim] = { - yakTotalVolume: row.yakTotalVolume, - orderTotalVolume: row.orderTotalVolume, - sellerCount: row.sellerCount, - buyerCount: row.buyerCount + var dim = row.dim + var metricKey = row.key + if (result[dim]) { + result[dim][metricKey] = row.value != null ? row.value : 0 } } diff --git a/data/magic-api/api/大屏数据/市场实时监控.ms b/data/magic-api/api/大屏数据/市场实时监控.ms index d16ff20..fb9cc10 100644 --- a/data/magic-api/api/大屏数据/市场实时监控.ms +++ b/data/magic-api/api/大屏数据/市场实时监控.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "市场实时监控", "createTime" : 1781199600000, - "updateTime" : null, + "updateTime" : 1781378000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,12 +17,14 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "市场实时监控:视频监控设备列表,数据源 iot_device_video + iot_device_video_data 最新一条(只读)。", + "description" : "市场实时监控:iot_device_video + iot_video_account,萤石 ezopen 播放地址与 accessToken。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 +// iot_device_video + iot_video_account(萤石云) +// play_url / hd_play_url:ezopen://open.ys7.com/{serial}/{channel}.live +// accessToken:iot_video_account.token var sql = """ SELECT @@ -32,31 +34,21 @@ SELECT v.location, v.address, v.status, + v.serial_number, + v.channel_number, v.play_url, v.hd_play_url, v.preview_img_url, v.img, - v.channel_number, + v.video_account_id, v."index" AS sort_index, v.last_capture_time, - d.stream_url AS latest_stream_url, - d.snapshot_url AS latest_snapshot_url, - d.online_status AS latest_online_status, - d.stream_status AS latest_stream_status, - d.fault_code AS latest_fault_code + a.app_key, + a.token AS access_token FROM iot_device_video v -LEFT JOIN LATERAL ( - SELECT - stream_url, - snapshot_url, - online_status, - stream_status, - fault_code - FROM iot_device_video_data - WHERE device_id = v.id - ORDER BY collect_time DESC NULLS LAST - LIMIT 1 -) d ON true +LEFT JOIN iot_video_account a + ON a.id::text = v.video_account_id + AND COALESCE(a.del_flag, '0') = '0' WHERE COALESCE(v.del_flag, '0') = '0' AND COALESCE(v.is_show, true) = true ORDER BY v."index" NULLS LAST, v.name @@ -87,8 +79,6 @@ var toUpperText = (text) => { var mapStatus = (row) => { var deviceStatus = pickText(row, 'status', 'status') - var onlineStatus = pickText(row, 'latestOnlineStatus', 'latest_online_status') - var faultCode = pickText(row, 'latestFaultCode', 'latest_fault_code') var deviceUpper = toUpperText(deviceStatus) if (deviceUpper === 'OFFLINE') { @@ -97,22 +87,10 @@ var mapStatus = (row) => { if (deviceUpper === 'ERROR' || deviceUpper === 'FAULT') { return 'error' } - if (faultCode) { - return 'error' - } - if (onlineStatus) { - var onlineUpper = toUpperText(onlineStatus) - if (onlineUpper === 'OFFLINE') { - return 'offline' - } - if (onlineUpper === 'ERROR' || onlineUpper === 'FAULT') { - return 'error' - } - } return 'online' } -var pickStreamUrl = (row) => { +var pickEzopenUrl = (row) => { var hd = pickText(row, 'hdPlayUrl', 'hd_play_url') if (hd) { return hd @@ -121,15 +99,16 @@ var pickStreamUrl = (row) => { if (play) { return play } - return pickText(row, 'latestStreamUrl', 'latest_stream_url') -} -var pickHdStreamUrl = (row) => { - return pickText(row, 'hdPlayUrl', 'hd_play_url') -} - -var pickPlayUrl = (row) => { - return pickText(row, 'playUrl', 'play_url') + var serial = pickText(row, 'serialNumber', 'serial_number') + var channel = row.channelNumber != null ? row.channelNumber : row.channel_number + if (channel == null) { + channel = 1 + } + if (serial) { + return 'ezopen://open.ys7.com/' + serial + '/' + channel + '.hd.live' + } + return '' } var pickPreviewUrl = (row) => { @@ -137,11 +116,7 @@ var pickPreviewUrl = (row) => { if (preview) { return preview } - var img = pickText(row, 'img', 'img') - if (img) { - return img - } - return pickText(row, 'latestSnapshotUrl', 'latest_snapshot_url') + return pickText(row, 'img', 'img') } if (rows && rows.length > 0) { @@ -152,14 +127,19 @@ if (rows && rows.length > 0) { number: pickText(row, 'number', 'number'), location: pickText(row, 'location', 'location'), address: pickText(row, 'address', 'address'), + serialNumber: pickText(row, 'serialNumber', 'serial_number'), channelNumber: row.channelNumber != null ? row.channelNumber : row.channel_number, + videoAccountId: pickText(row, 'videoAccountId', 'video_account_id'), sortIndex: row.sortIndex != null ? row.sortIndex : row.sort_index, status: mapStatus(row), resolution: '1920x1080', + url: pickPreviewUrl(row), preview: pickPreviewUrl(row), - hdStreamUrl: pickHdStreamUrl(row), - playUrl: pickPlayUrl(row), - streamUrl: pickStreamUrl(row) + playUrl: pickText(row, 'playUrl', 'play_url'), + hdPlayUrl: pickText(row, 'hdPlayUrl', 'hd_play_url'), + ezopenUrl: pickEzopenUrl(row), + accessToken: pickText(row, 'accessToken', 'access_token'), + appKey: pickText(row, 'appKey', 'app_key') }) } } diff --git a/data/magic-api/api/大屏数据/市场实时监控播放配置.ms b/data/magic-api/api/大屏数据/市场实时监控播放配置.ms index 171c7be..7ad7e39 100644 --- a/data/magic-api/api/大屏数据/市场实时监控播放配置.ms +++ b/data/magic-api/api/大屏数据/市场实时监控播放配置.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "市场实时监控播放配置", "createTime" : 1781203200000, - "updateTime" : null, + "updateTime" : 1781378000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,61 +17,21 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "市场实时监控播放配置:直播流格式识别规则与播放器参数(HLS/FLV/MP4 等)。", + "description" : "市场实时监控播放配置:萤石云 EZUIKit 播放器参数。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 直播流地址格式配置,供前端 hls.js / flv.js 自动选型 +// 萤石云 EZUIKit 播放器配置 return { - defaultProtocol: 'hls', - urlPriority: ['hdStreamUrl', 'streamUrl', 'playUrl'], - formatRules: [ - { - type: 'hls', - match: '.m3u8', - library: 'hls.js', - description: 'HLS 直播(萤石 open.ys7.com 等)' - }, - { - type: 'flv', - match: '.flv', - library: 'flv.js', - description: 'HTTP-FLV 直播(萤石 rtmp*open.ys7.com 等)' - }, - { - type: 'mp4', - match: '.mp4', - library: 'native', - description: 'MP4 点播/回放' - }, - { - type: 'webm', - match: '.webm', - library: 'native', - description: 'WebM 点播' - } - ], - playerOptions: { - hls: { - enableWorker: true, - lowLatencyMode: true - }, - flv: { - isLive: true, - hasAudio: true, - hasVideo: true - }, - flvMedia: { - enableWorker: true, - enableStashBuffer: false - } - }, - ys7Templates: { - hdHls: 'https://open.ys7.com/v3/openlive/{deviceSerial}_{channelNo}_1.m3u8', - hls: 'https://open.ys7.com/v3/openlive/{deviceSerial}_{channelNo}_2.m3u8', - hdFlv: 'https://rtmp12open.ys7.com:9188/v3/openlive/{deviceSerial}_{channelNo}_1.flv', - flv: 'https://rtmp12open.ys7.com:9188/v3/openlive/{deviceSerial}_{channelNo}_2.flv' + playerType: 'ezviz', + staticPath: '/ezuikit_static', + urlPriority: ['hdPlayUrl', 'playUrl', 'ezopenUrl'], + ezviz: { + template: 'simple', + scaleMode: 1, + audio: false, + defaultQuality: 'hd.live' } } diff --git a/data/magic-api/api/大屏数据/市场环境监控.ms b/data/magic-api/api/大屏数据/市场环境监控.ms index 0baedcd..b0bb633 100644 --- a/data/magic-api/api/大屏数据/市场环境监控.ms +++ b/data/magic-api/api/大屏数据/市场环境监控.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "市场环境监控", "createTime" : 1781196000000, - "updateTime" : null, + "updateTime" : 1781374000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,79 +17,71 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "市场环境监控:温湿度(iot_device_env_data)+ 气象(iot_device_weather_data)最新一条,只读。", + "description" : "市场环境监控:gov_count_real_info,group_item=env-monitor,source_system=yzt。温湿度/气象八项指标及 tag、unit。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 +// gov_count_real_info(group_item=env-monitor, source_system=yzt) +// temperature 温度 +// humidity 湿度 +// aqi 空气质量 +// pressure 大气压强 +// uv 紫外线 +// rainfall 降雨量 +// wind_direction 风向(value=角度,tag=风向名) +// wind_power 风力(value=级数) -var envSql = """ -SELECT - temperature, - humidity, - to_char(collect_time, 'YYYY-MM-DD HH24:MI:SS') AS collect_time -FROM iot_device_env_data -ORDER BY collect_time DESC NULLS LAST -LIMIT 1 +var sql = """ +SELECT key, name, value, tag, unit +FROM gov_count_real_info +WHERE group_item = 'env-monitor' + AND source_system = 'yzt' """ -var weatherSql = """ -SELECT - air_pressure, - pm25, - pm10, - uv_index, - rainfall, - wind_speed, - wind_direction, - to_char(collect_time, 'YYYY-MM-DD HH24:MI:SS') AS collect_time -FROM iot_device_weather_data -ORDER BY collect_time DESC NULLS LAST -LIMIT 1 -""" +var rows = db.select(sql) -var envRows = db.select(envSql) -var weatherRows = db.select(weatherSql) -var env = envRows && envRows.length > 0 ? envRows[0] : null -var weather = weatherRows && weatherRows.length > 0 ? weatherRows[0] : null +var valueMap = {} +var tagMap = {} +var unitMap = {} -var pickNum = (row, camelKey, snakeKey) => { - if (!row) { - return null - } - if (row[camelKey] != null) { - return row[camelKey] +for (row in rows) { + valueMap[row.key] = row.value != null ? row.value : null + if (row.tag) { + tagMap[row.key] = row.tag } - if (row[snakeKey] != null) { - return row[snakeKey] + if (row.unit) { + unitMap[row.key] = row.unit } - return null } -var pickText = (row, camelKey, snakeKey) => { - if (!row) { - return '' - } - if (row[camelKey]) { - return row[camelKey] - } - if (row[snakeKey]) { - return row[snakeKey] - } - return '' -} +var pick = (key) => valueMap[key] != null ? valueMap[key] : null +var pickTag = (key) => tagMap[key] +var pickUnit = (key) => unitMap[key] return { - temperature: pickNum(env, 'temperature', 'temperature'), - humidity: pickNum(env, 'humidity', 'humidity'), - envCollectTime: pickText(env, 'collectTime', 'collect_time'), - airPressure: pickNum(weather, 'airPressure', 'air_pressure'), - pm25: pickNum(weather, 'pm25', 'pm25'), - pm10: pickNum(weather, 'pm10', 'pm10'), - uvIndex: pickNum(weather, 'uvIndex', 'uv_index'), - rainfall: pickNum(weather, 'rainfall', 'rainfall'), - windSpeed: pickNum(weather, 'windSpeed', 'wind_speed'), - windDirection: pickNum(weather, 'windDirection', 'wind_direction'), - weatherCollectTime: pickText(weather, 'collectTime', 'collect_time') + temperature: pick('temperature'), + humidity: pick('humidity'), + aqi: pick('aqi'), + airPressure: pick('pressure'), + uvIndex: pick('uv'), + rainfall: pick('rainfall'), + windDirection: pick('wind_direction'), + windPower: pick('wind_power'), + temperatureTag: pickTag('temperature'), + humidityTag: pickTag('humidity'), + aqiTag: pickTag('aqi'), + airPressureTag: pickTag('pressure'), + uvIndexTag: pickTag('uv'), + rainfallTag: pickTag('rainfall'), + windDirectionTag: pickTag('wind_direction'), + windPowerTag: pickTag('wind_power'), + temperatureUnit: pickUnit('temperature'), + humidityUnit: pickUnit('humidity'), + aqiUnit: pickUnit('aqi'), + airPressureUnit: pickUnit('pressure'), + uvIndexUnit: pickUnit('uv'), + rainfallUnit: pickUnit('rainfall'), + windDirectionUnit: pickUnit('wind_direction'), + windPowerUnit: pickUnit('wind_power') } diff --git a/data/magic-api/api/大屏数据/活牛鲜肉价格趋势.ms b/data/magic-api/api/大屏数据/活牛鲜肉价格趋势.ms index 6c5ecb0..8357016 100644 --- a/data/magic-api/api/大屏数据/活牛鲜肉价格趋势.ms +++ b/data/magic-api/api/大屏数据/活牛鲜肉价格趋势.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "活牛鲜肉价格趋势", "createTime" : 1780877200000, - "updateTime" : null, + "updateTime" : 1781372000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,17 +17,20 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "活牛/鲜肉价格趋势:近8个月市场采集均价。数据源 yak_trade_market_price,活牛=LIVE_YAK,鲜肉=FRESH_MEAT,直接使用 price 字段及 unit 单位,不做重量折算。", + "description" : "活牛/鲜肉价格趋势:近8个月采集均价。数据源 gov_count_price,活牛=price_key hx,鲜肉=mnr/mnt/mnp 月均,直接使用 value 与 unit,不做重量折算。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 -// 数据源:yak_trade_market_price(市场采集价格,已含 price + unit) -// price_type: LIVE_YAK=活牛, FRESH_MEAT=鲜肉/牛肉 +// gov_count_price 价格指标 price_key: +// hx 活畜(活牛) +// mnr/mnt/mnp 鲜肉(牦牛肉/腿/排) +// 按 year + month 对各区域采集价取 AVG(value);无数据月份返回 null var monthBucketSql = """ SELECT + EXTRACT(YEAR FROM d.month_start)::int AS year, + EXTRACT(MONTH FROM d.month_start)::int AS month, d.month_start, d.offs, TO_CHAR(d.month_start, 'FMMM') || '月' AS label @@ -42,30 +45,30 @@ ORDER BY d.offs DESC var livePriceSql = """ SELECT - date_trunc('month', p.price_date)::date AS month_start, - ROUND(AVG(p.price)::numeric, 2) AS live_cattle_price -FROM yak_trade_market_price p -WHERE p.price_type = 'LIVE_YAK' - AND p.price_date >= date_trunc('month', CURRENT_DATE) - INTERVAL '7 months' -GROUP BY date_trunc('month', p.price_date)::date + year, + month, + ROUND(AVG(value)::numeric, 2) AS live_cattle_price +FROM gov_count_price +WHERE price_key = 'hx' +GROUP BY year, month """ var beefPriceSql = """ SELECT - date_trunc('month', p.price_date)::date AS month_start, - ROUND(AVG(p.price)::numeric, 2) AS beef_price -FROM yak_trade_market_price p -WHERE p.price_type = 'FRESH_MEAT' - AND p.price_date >= date_trunc('month', CURRENT_DATE) - INTERVAL '7 months' -GROUP BY date_trunc('month', p.price_date)::date + year, + month, + ROUND(AVG(value)::numeric, 2) AS beef_price +FROM gov_count_price +WHERE price_key IN ('mnr', 'mnt', 'mnp') +GROUP BY year, month """ var unitSql = """ SELECT - MAX(CASE WHEN price_type = 'LIVE_YAK' THEN unit END) AS live_unit, - MAX(CASE WHEN price_type = 'FRESH_MEAT' THEN unit END) AS beef_unit -FROM yak_trade_market_price -WHERE price_type IN ('LIVE_YAK', 'FRESH_MEAT') + MAX(CASE WHEN price_key = 'hx' THEN unit END) AS live_unit, + MAX(CASE WHEN price_key IN ('mnr', 'mnt', 'mnp') THEN unit END) AS beef_unit +FROM gov_count_price +WHERE price_key IN ('hx', 'mnr', 'mnt', 'mnp') """ var buckets = db.select(monthBucketSql) @@ -77,15 +80,17 @@ var liveMap = {} var beefMap = {} for (row in liveRows) { - liveMap[row.monthStart] = row.liveCattlePrice + var key = row.year + '-' + row.month + liveMap[key] = row.liveCattlePrice } for (row in beefRows) { - beefMap[row.monthStart] = row.beefPrice + var key = row.year + '-' + row.month + beefMap[key] = row.beefPrice } -var liveUnit = '元/公斤' -var beefUnit = '元/公斤' +var liveUnit = '元/kg' +var beefUnit = '元/kg' if (unitRows && unitRows.length > 0) { if (unitRows[0].liveUnit) { liveUnit = unitRows[0].liveUnit @@ -100,7 +105,7 @@ var liveCattlePrice = [] var beefPrice = [] for (bucket in buckets) { - var monthKey = bucket.monthStart + var monthKey = bucket.year + '-' + bucket.month labels.push(bucket.label) liveCattlePrice.push(liveMap[monthKey] != null ? liveMap[monthKey] : null) beefPrice.push(beefMap[monthKey] != null ? beefMap[monthKey] : null) diff --git a/data/magic-api/api/大屏数据/牦牛销售类型统计.ms b/data/magic-api/api/大屏数据/牦牛销售类型统计.ms index cc43759..ebadfec 100644 --- a/data/magic-api/api/大屏数据/牦牛销售类型统计.ms +++ b/data/magic-api/api/大屏数据/牦牛销售类型统计.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "牦牛销售类型统计", "createTime" : 1780880400000, - "updateTime" : null, + "updateTime" : 1781375000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,54 +17,41 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "牦牛销售类型统计:按订单 purpose 归类为屠宰/养殖/其他,统计已完成订单牦牛头数与占比(只读)。", + "description" : "牦牛销售类型统计:gov_count_order_total 按 purpose 分组,SUM(yak_number) 为成交头数,一条记录一单。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 -// 数据源 yak_sn_order.purpose,按用途关键词归类 +// gov_count_order_total:一条记录 = 一笔订单 +// 成交头数:SUM(yak_number) +// 销售类型:purpose(屠宰 / 养殖 / 其他 等) var sql = """ -SELECT category AS name, COALESCE(SUM(quantity), 0) AS value -FROM ( - SELECT - o.quantity, - CASE - WHEN TRIM(COALESCE(o.purpose, '')) ~* '(屠宰|餐饮|肉食|宰杀)' THEN '屠宰用途' - WHEN TRIM(COALESCE(o.purpose, '')) ~* '(养殖|繁育|种|批发|转售)' THEN '养殖用途' - ELSE '其他用途' - END AS category - FROM yak_sn_order o - WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' -) t -GROUP BY category +SELECT + COALESCE(NULLIF(TRIM(purpose), ''), '其他') AS name, + COALESCE(SUM(yak_number), 0) AS value +FROM gov_count_order_total +GROUP BY COALESCE(NULLIF(TRIM(purpose), ''), '其他') +ORDER BY value DESC """ var rows = db.select(sql) -var categories = ['屠宰用途', '养殖用途', '其他用途'] -var valueMap = {} - -for (row in rows) { - valueMap[row.name] = row.value ? row.value : 0 -} var total = 0 -for (cat in categories) { - var count = valueMap[cat] ? valueMap[cat] : 0 +for (row in rows) { + var count = row.value != null ? row.value : 0 total = total + count } var result = [] -for (cat in categories) { - var count = valueMap[cat] ? valueMap[cat] : 0 +for (row in rows) { + var count = row.value != null ? row.value : 0 var percent = 0 if (total > 0) { percent = (count * 100.0) / total } result.push({ - name: cat, + name: row.name, value: count, percent: percent }) diff --git a/data/magic-api/api/大屏数据/综合销售统计.ms b/data/magic-api/api/大屏数据/综合销售统计.ms index 98a8b96..96168b9 100644 --- a/data/magic-api/api/大屏数据/综合销售统计.ms +++ b/data/magic-api/api/大屏数据/综合销售统计.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "综合销售统计", "createTime" : 1780877100000, - "updateTime" : null, + "updateTime" : 1781368000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -29,31 +29,58 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "综合销售统计:本月销售/总体销售/采购地区三维饼图数据,数据源 yak_sn_order 已完成订单(只读)", + "description" : "综合销售统计:数据源 gov_count_order_total(只读)。销售按 origin_place,采购地区按 buyer_place,头数 yak_number。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 数据源 yak_sn_order + yak_sn_customer -// value = 牦牛交易头数 quantity +// gov_count_order_total +// 本月/总体销售:origin_place + SUM(yak_number) +// 采购地区:buyer_place + SUM(yak_number)(库表字段 buyer_place) -var mapRows = (rows) => { +var mapOriginRows = (rows) => { var total = 0 var result = [] for (row in rows) { - total = total + (row.value ? row.value : 0) + var qty = row.yakNumber != null ? row.yakNumber : 0 + total = total + qty } for (row in rows) { - var value = row.value ? row.value : 0 + var qty = row.yakNumber != null ? row.yakNumber : 0 var percent = 0 if (total > 0) { - percent = (value * 100) / total + percent = (qty * 100) / total } result.push({ - name: row.name, - value: value, + originPlace: row.originPlace ? row.originPlace : '未知地区', + yakNumber: qty, + percent: percent + }) + } + + return result +} + +var mapBuyerRows = (rows) => { + var total = 0 + var result = [] + + for (row in rows) { + var qty = row.yakNumber != null ? row.yakNumber : 0 + total = total + qty + } + + for (row in rows) { + var qty = row.yakNumber != null ? row.yakNumber : 0 + var percent = 0 + if (total > 0) { + percent = (qty * 100) / total + } + result.push({ + buyerPlace: row.buyerPlace ? row.buyerPlace : '未知地区', + yakNumber: qty, percent: percent }) } @@ -62,80 +89,48 @@ var mapRows = (rows) => { } var monthlySql = """ -SELECT town AS name, COALESCE(SUM(quantity), 0) AS value -FROM ( - SELECT - o.quantity, - COALESCE( - NULLIF((regexp_match(o.origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), - NULLIF(TRIM(o.origin_place), ''), - '未知地区' - ) AS town - FROM yak_sn_order o - CROSS JOIN ( - SELECT CASE - WHEN EXISTS ( - SELECT 1 FROM yak_sn_order x - WHERE x.del_flag = '0' - AND x.status = 'COMPLETED' - AND x.transaction_time >= date_trunc('month', CURRENT_DATE) - AND x.transaction_time < date_trunc('month', CURRENT_DATE) + INTERVAL '1 month' - ) THEN date_trunc('month', CURRENT_DATE) - ELSE date_trunc('month', ( - SELECT MAX(transaction_time) FROM yak_sn_order - WHERE del_flag = '0' AND status = 'COMPLETED' - )) - END AS month_start - ) m - WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' - AND o.transaction_time >= m.month_start - AND o.transaction_time < m.month_start + INTERVAL '1 month' -) t -GROUP BY town -ORDER BY value DESC +WITH anchor AS ( + SELECT year, month + FROM gov_count_order_total + WHERE year IS NOT NULL AND month IS NOT NULL + ORDER BY year DESC, month DESC + LIMIT 1 +) +SELECT + TRIM(o.origin_place) AS origin_place, + COALESCE(SUM(o.yak_number), 0) AS yak_number +FROM gov_count_order_total o +CROSS JOIN anchor a +WHERE o.year = a.year + AND o.month = a.month + AND o.origin_place IS NOT NULL + AND TRIM(o.origin_place) <> '' +GROUP BY TRIM(o.origin_place) +ORDER BY yak_number DESC, origin_place LIMIT 5 """ var overallSql = """ -SELECT town AS name, COALESCE(SUM(quantity), 0) AS value -FROM ( - SELECT - o.quantity, - COALESCE( - NULLIF((regexp_match(o.origin_place, '([^省市区县]+(?:镇|乡|街道))'))[1], ''), - NULLIF(TRIM(o.origin_place), ''), - '未知地区' - ) AS town - FROM yak_sn_order o - WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' -) t -GROUP BY town -ORDER BY value DESC +SELECT + TRIM(origin_place) AS origin_place, + COALESCE(SUM(yak_number), 0) AS yak_number +FROM gov_count_order_total +WHERE origin_place IS NOT NULL + AND TRIM(origin_place) <> '' +GROUP BY TRIM(origin_place) +ORDER BY yak_number DESC, origin_place LIMIT 5 """ var purchaseSql = """ -SELECT region AS name, COALESCE(SUM(quantity), 0) AS value -FROM ( - SELECT - o.quantity, - COALESCE( - NULLIF(TRIM(b.region_name), ''), - NULLIF((regexp_match(o.destination_place, '([^省市区县]+(?:市|州|盟|县|区))'))[1], ''), - NULLIF(TRIM(o.destination_place), ''), - '未知地区' - ) AS region - FROM yak_sn_order o - LEFT JOIN yak_sn_customer b - ON b.id = o.buyer_id - AND b.del_flag = '0' - WHERE o.del_flag = '0' - AND o.status = 'COMPLETED' -) t -GROUP BY region -ORDER BY value DESC +SELECT + TRIM(buyer_place) AS buyer_place, + COALESCE(SUM(yak_number), 0) AS yak_number +FROM gov_count_order_total +WHERE buyer_place IS NOT NULL + AND TRIM(buyer_place) <> '' +GROUP BY TRIM(buyer_place) +ORDER BY yak_number DESC, buyer_place LIMIT 5 """ @@ -144,9 +139,9 @@ var overallRows = db.select(overallSql) var purchaseRows = db.select(purchaseSql) var result = { - monthlySales: mapRows(monthlyRows), - overallSalesDistribution: mapRows(overallRows), - purchaseRegionDistribution: mapRows(purchaseRows) + monthlySales: mapOriginRows(monthlyRows), + overallSalesDistribution: mapOriginRows(overallRows), + purchaseRegionDistribution: mapBuyerRows(purchaseRows) } var t = type diff --git a/data/magic-api/api/大屏数据/采购商户来源分析.ms b/data/magic-api/api/大屏数据/采购商户来源分析.ms index 228819a..9a6cf44 100644 --- a/data/magic-api/api/大屏数据/采购商户来源分析.ms +++ b/data/magic-api/api/大屏数据/采购商户来源分析.ms @@ -5,7 +5,7 @@ "groupId" : "f8e3d2c1b0a94e5f8a7b6c5d4e3f2a1", "name" : "采购商户来源分析", "createTime" : 1780881000000, - "updateTime" : null, + "updateTime" : 1781376000000, "lock" : null, "createBy" : "admin", "updateBy" : "admin", @@ -17,26 +17,26 @@ "headers" : [ ], "paths" : [ ], "responseBody" : null, - "description" : "采购商户来源分析:按地区统计采购商户(BUYER)数量 Top9,数据源 yak_sn_customer(只读)。", + "description" : "采购商户来源分析:gov_count_order_total 按 buyer_place 统计采购商户数 Top9,一条记录一单。", "requestBodyDefinition" : null, "responseBodyDefinition" : null } ================================ -// 只读查询,不修改任何数据 +// gov_count_order_total:一条记录 = 一笔订单 +// 采购地区:buyer_place +// 采购商户数:COUNT(DISTINCT buyer_name),buyer_name 为空时按 id 计 1 户 var sql = """ SELECT - region_name AS name, - region_name AS full_name, - COUNT(*) AS value, - region_name || '采购商户' AS description -FROM yak_sn_customer c -WHERE c.del_flag = '0' - AND c.customer_type = 'BUYER' - AND c.region_name IS NOT NULL - AND TRIM(c.region_name) <> '' -GROUP BY region_name -ORDER BY value DESC, region_name + buyer_place AS name, + buyer_place AS full_name, + COUNT(DISTINCT COALESCE(NULLIF(TRIM(buyer_name), ''), id)) AS value, + buyer_place || '采购商户' AS description +FROM gov_count_order_total +WHERE buyer_place IS NOT NULL + AND TRIM(buyer_place) <> '' +GROUP BY buyer_place +ORDER BY value DESC, buyer_place LIMIT 9 """ @@ -46,7 +46,7 @@ var result = [] for (row in rows) { result.push({ name: row.name, - value: row.value ? row.value : 0, + value: row.value != null ? row.value : 0, fullName: row.fullName ? row.fullName : (row.full_name ? row.full_name : ''), description: row.description ? row.description : '采购商户' }) diff --git a/magic-api-dashboard-interfaces.txt b/magic-api-dashboard-interfaces.txt index 53cee84..61aecf5 100644 --- a/magic-api-dashboard-interfaces.txt +++ b/magic-api-dashboard-interfaces.txt @@ -23,13 +23,13 @@ GET /dashboard/system-config GET /dashboard/real-time-stats 文件:实时交易统计.ms | 前端:RealTimeStats.vue -业务:按时间维度统计交易所已完成订单的交易量、订单数、买卖商户数。 +业务:按日/周/月读取政务统计指标(牦牛交易量、订单量、买卖商户数)。 -参数:dimension(可选)day / week / month / year,不传返回全部 +参数:dimension(可选)day / week / month,不传返回全部 -表:yak_sn_order -字段:quantity, seller_id, buyer_id, transaction_time, status, del_flag -条件:del_flag='0',status='COMPLETED' +表:gov_count_item +字段:key(mnjyzl/jdjyzl/xsshsl/cgshsl), name, value, count_date +口径:day=最新 count_date;week=近7天;month=近30天;mnjyzl/jdjyzl 按日求和,xsshsl/cgshsl 取区间内最大值 -------------------------------------------------------------------------------- @@ -38,13 +38,14 @@ GET /dashboard/real-time-stats GET /dashboard/yak-trading-data 文件:交易所牦牛成交数据.ms | 前端:YakTradingData.vue -业务:近 6 个日/周/月时间桶的牦牛头数与订单数趋势。 +业务:近 6 个日/周/月时间桶的牦牛成交头数与订单数趋势(一条记录 = 一单)。 参数:period(可选)day / week / month,不传返回全部 -表:yak_sn_order -字段:id, quantity, transaction_time, status, del_flag -条件:del_flag='0',status='COMPLETED' +表:gov_count_order_total +字段:id, yak_number, update_time +口径:SUM(yak_number) 为成交头数,COUNT(*) 为订单数;按 update_time 分桶 +返回:labels, yakNumber, orderCount -------------------------------------------------------------------------------- @@ -53,15 +54,12 @@ GET /dashboard/yak-trading-data GET /dashboard/comprehensive-sales-stats 文件:综合销售统计.ms | 前端:ComprehensiveSalesStats.vue -业务:三个饼图——本月销售、总体销售(按产地乡镇 Top5)、采购地区(Top5)。 +业务:三个饼图——本月销售、总体销售(按 origin_place Top5)、采购地区(按 buyer_place Top5)。 参数:type(可选)monthlySales / overallSalesDistribution / purchaseRegionDistribution -表:yak_sn_order;采购地区 LEFT JOIN yak_sn_customer -字段: - yak_sn_order — quantity, origin_place, destination_place, buyer_id, transaction_time, status, del_flag - yak_sn_customer — id, region_name, del_flag -条件:del_flag='0',status='COMPLETED' +表:gov_count_order_total +字段:origin_place, buyer_place, yak_number, year, month -------------------------------------------------------------------------------- @@ -70,10 +68,14 @@ GET /dashboard/comprehensive-sales-stats GET /dashboard/price-trend 文件:活牛鲜肉价格趋势.ms | 前端:YakPriceTrend.vue -业务:近 8 个月活牛、鲜肉市场采集均价(不做重量折算)。 +业务:近 8 个月活牛、鲜肉采集均价(不做重量折算)。 -表:yak_trade_market_price -字段:price_date, price_type(LIVE_YAK / FRESH_MEAT), price, unit +表:gov_count_price +字段:year, month, price_key, value, unit +口径: + 活牛 — price_key = hx(活畜),各区域 AVG(value) + 鲜肉 — price_key IN (mnr, mnt, mnp)(牦牛肉/腿/排),各区域 AVG(value) +返回:labels, liveCattlePrice, beefPrice, liveUnit, beefUnit -------------------------------------------------------------------------------- @@ -82,14 +84,19 @@ GET /dashboard/price-trend GET /dashboard/exchange-service-info 文件:交易中心实时服务信息.ms | 前端:ExchangeMonitor.vue -业务:交易中心实时概览——供应/待售/已售头数、剩余车位、今日进场车辆、供应商数。 +业务:交易中心实时概览——供应/待售/已售头数、剩余车位、进场车辆、供应商数。 -表及字段: - yak_trade_ear_tag_inventory — status(计总供应/待售/已售) - yak_car_parking_zone — total_capacity, current_count, status - yak_car_record — plate_no, entry_time, del_flag - yak_trade_entry_record — vehicle_no, entered_at - yak_sn_customer — customer_type='SELLER', del_flag +表:gov_count_real_info +条件:group_item = jygy,source_system = yzt +字段:key, name, value, tag, unit +key 映射: + mngyzl → totalSupply(牦牛供应总量) + dsmn → forSaleYaks(待售牦牛) + ysmn → soldYaks(已售牦牛) + sycw → remainingParking(剩余车位) + jccl → enteringVehicles(进场车辆) + gyssl → supplierCount(供应商数量) +返回:上述 value + Tag + Unit -------------------------------------------------------------------------------- @@ -98,11 +105,12 @@ GET /dashboard/exchange-service-info GET /dashboard/yak-sales-type-stats 文件:牦牛销售类型统计.ms | 前端:YakSalesTypeStats.vue -业务:按订单用途归类为屠宰/养殖/其他,统计头数与占比。 +业务:按 purpose 统计成交头数与占比(一条记录 = 一单)。 -表:yak_sn_order -字段:quantity, purpose, status, del_flag -条件:del_flag='0',status='COMPLETED' +表:gov_count_order_total +字段:purpose, yak_number +口径:GROUP BY purpose,SUM(yak_number);空 purpose 归为「其他」 +返回:name(屠宰/养殖/其他等), value, percent -------------------------------------------------------------------------------- @@ -111,11 +119,12 @@ GET /dashboard/yak-sales-type-stats GET /dashboard/buyer-source-analysis 文件:采购商户来源分析.ms | 前端:PurchaserAnalysis.vue -业务:按地区统计采购商户(BUYER)数量 Top9。 +业务:按 buyer_place 统计采购商户数量 Top9(一条记录 = 一单)。 -表:yak_sn_customer -字段:region_name, customer_type, del_flag -条件:customer_type='BUYER',del_flag='0',region_name 非空 +表:gov_count_order_total +字段:buyer_place, buyer_name, id +口径:GROUP BY buyer_place,COUNT(DISTINCT buyer_name);buyer_name 为空时按 id 计 1 户 +返回:name, value, fullName, description -------------------------------------------------------------------------------- @@ -164,11 +173,21 @@ GET /dashboard/yak-supply-detail GET /dashboard/market-environment 文件:市场环境监控.ms | 前端:MarketEnvironmentMonitor.vue -业务:环境温湿度 + 气象数据各取最新一条。 +业务:环境温湿度 + 气象八项实时指标。 -表及字段: - iot_device_env_data — temperature, humidity, collect_time - iot_device_weather_data — air_pressure, pm25, pm10, uv_index, rainfall, wind_speed, wind_direction, collect_time +表:gov_count_real_info +条件:group_item = env-monitor,source_system = yzt +字段:key, name, value, tag, unit +key 映射: + temperature 温度 + humidity 湿度 + aqi 空气质量 + pressure 大气压强 + uv 紫外线 + rainfall 降雨量 + wind_direction 风向(value=角度,tag=风向名) + wind_power 风力(value=级数) +返回:上述 value + Tag + Unit -------------------------------------------------------------------------------- @@ -177,21 +196,23 @@ GET /dashboard/market-environment GET /dashboard/market-realtime-monitor 文件:市场实时监控.ms | 前端:MarketRealtimeMonitor.vue -业务:视频监控设备列表及播放/预览地址。 +业务:萤石云视频监控设备列表,EZUIKit 播放 ezopen 地址。 表及字段: - iot_device_video — id, name, number, location, address, status, play_url, hd_play_url, preview_img_url, channel_number, index, del_flag, is_show - iot_device_video_data — device_id, stream_url, snapshot_url, online_status, stream_status, fault_code, collect_time + iot_device_video — id, name, serial_number, channel_number, status, play_url, hd_play_url, preview_img_url, video_account_id, index, del_flag, is_show + iot_video_account — id, app_key, token +关联:v.video_account_id = a.id 条件:del_flag='0',is_show=true +返回:ezopenUrl, accessToken, preview 等 -------------------------------------------------------------------------------- 13. 市场实时监控播放配置 -------------------------------------------------------------------------------- GET /dashboard/market-realtime-player-config -文件:市场实时监控播放配置.ms | 前端:MarketRealtimeMonitor.vue(liveStreamPlayer.js) +文件:市场实时监控播放配置.ms | 前端:MarketRealtimeMonitor.vue(ezvizPlayer.js) -业务:直播流协议识别规则与 hls.js / flv.js 播放器参数(静态配置)。 +业务:萤石云 EZUIKit 播放器参数(staticPath、template、scaleMode 等)。 数据表:无 @@ -202,22 +223,25 @@ GET /dashboard/market-realtime-player-config GET /dashboard/map-trading-network 文件:地图迁徙数据.ms | 前端:ChinaMap.vue -业务:中央地图三种模式流向——销售网络(红原→全国)、源地供应(全国→红原)、红原出栏(乡镇→红原)。 +业务:中央地图三种模式流向,头数 SUM(yak_number),一条记录一单。 -表:yak_sn_order;outflow/inflow LEFT JOIN yak_sn_customer -字段: - yak_sn_order — quantity, origin_place, destination_place, buyer_id, seller_id, status, del_flag - yak_sn_customer — id, region_name, del_flag -条件:del_flag='0',status='COMPLETED';local 模式另要求 origin_place 含「红原」 +表:gov_count_order_total +字段:origin_place, destination_place, yak_number +口径: + outflow 销售网络 — origin_place 含「红原」,按 destination_place 聚合,红原→全国 + inflow 源地供应 — destination_place 含「红原」,按 origin_place 聚合,全国→红原 + local 红原出栏 — destination_place 含「红原」且 origin_place 含「红原」,按 origin_place 乡镇聚合,县内乡镇→红原 关联:系统配置 mapHub.name 与脚本 hubName 需一致(默认「红原县」) ================================================================================ 表 → 接口索引 ================================================================================ -yak_sn_order 2, 3, 4, 7, 14 -yak_sn_customer 4, 6, 8, 9, 10, 14 -yak_trade_market_price 5 +gov_count_real_info 6, 11 +gov_count_price 5 +gov_count_order_total 3, 4, 7, 8, 14 +gov_count_item 2 +yak_sn_customer 4, 6, 9, 10 yak_trade_ear_tag_inventory 6, 9, 10 yak_trade_entry_record 6, 9, 10 yak_trade_entry_record_ear_tag 9, 10 @@ -227,8 +251,6 @@ yak_trade_quarantine_certificate 10 yak_car_parking_zone 6 yak_car_record 6, 10 sys_oss 10 -iot_device_env_data 11 -iot_device_weather_data 11 +iot_video_account 12 iot_device_video 12 -iot_device_video_data 12 (无表) 1, 13