From ec6b59b4fa145d8ba789a138aee04776627d4cb2 Mon Sep 17 00:00:00 2001 From: XuJiacheng Date: Thu, 9 Apr 2026 14:49:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=B4=AD=E7=89=A9?= =?UTF-8?q?=E8=BD=A6=E7=9B=B8=E5=85=B3=E8=BF=81=E7=A7=BB=E5=92=8C=E7=B4=A2?= =?UTF-8?q?=E5=BC=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 package.json 中添加迁移脚本 `migrate:cart-active-unique-index`。 - 修改 `pocketbase.cart-order.js` 文件,更新 `cart_id` 和 `cart_product_id` 字段的必填属性,并添加唯一索引 `idx_tbl_cart_owner_product_active_unique`。 - 在 `pocketbase.ensure-cart-order-autogen-id.js` 中,调整 `cart_id` 字段的必填属性为可选,并确保 `order_id` 字段为必填。 - 在 `pocketbase.product-list.js` 中,新增 `prod_list_barcode` 字段。 - 新增 `make-openapi-standalone.cjs` 脚本,用于处理 OpenAPI 文档。 - 新增 `pocketbase.cart-active-unique-index.js` 脚本,处理购物车的唯一索引和去重逻辑。 --- .../make-openapi-standalone.cjs | 132 ++ docs/pb_tbl_product_list.md | 4 +- docs/pb_tbl_scheme_template.md | 8 +- .../middlewares/requestGuards.js | 3 +- .../services/cartOrderService.js | 4 + .../bai_api_shared/services/productService.js | 4 + .../bai_api_shared/services/schemeService.js | 21 +- .../views/cart-order-manage.html | 4 +- .../views/product-manage.html | 41 +- .../bai_web_pb_hooks/views/scheme-manage.html | 431 +++- pocket-base/spec/openapi-manage.yaml | 1811 ---------------- pocket-base/spec/openapi-manage/cart.yaml | 30 +- pocket-base/spec/openapi-manage/openapi.yaml | 74 +- pocket-base/spec/openapi-manage/order.yaml | 22 +- pocket-base/spec/openapi-miniapp-company.yaml | 571 ----- pocket-base/spec/openapi-wx.yaml | 44 - pocket-base/spec/openapi-wx/attachments.yaml | 26 +- pocket-base/spec/openapi-wx/cart.yaml | 1153 ++-------- pocket-base/spec/openapi-wx/company.yaml | 56 +- pocket-base/spec/openapi-wx/documents.yaml | 38 +- pocket-base/spec/openapi-wx/openapi.yaml | 30 +- pocket-base/spec/openapi-wx/order.yaml | 1085 +--------- pocket-base/spec/openapi-wx/products.yaml | 50 +- pocket-base/spec/openapi.yaml | 1891 ----------------- script/package.json | 1 + script/pocketbase.cart-active-unique-index.js | 145 ++ script/pocketbase.cart-order.js | 5 +- ...pocketbase.ensure-cart-order-autogen-id.js | 4 +- script/pocketbase.product-list.js | 1 + 29 files changed, 1240 insertions(+), 6449 deletions(-) create mode 100644 .tmp-openapi-validate/make-openapi-standalone.cjs delete mode 100644 pocket-base/spec/openapi-manage.yaml delete mode 100644 pocket-base/spec/openapi-miniapp-company.yaml delete mode 100644 pocket-base/spec/openapi-wx.yaml delete mode 100644 pocket-base/spec/openapi.yaml create mode 100644 script/pocketbase.cart-active-unique-index.js diff --git a/.tmp-openapi-validate/make-openapi-standalone.cjs b/.tmp-openapi-validate/make-openapi-standalone.cjs new file mode 100644 index 0000000..64b92b7 --- /dev/null +++ b/.tmp-openapi-validate/make-openapi-standalone.cjs @@ -0,0 +1,132 @@ +const fs = require('fs'); +const path = require('path'); +const YAML = require('yaml'); + +const repoRoot = path.resolve(process.cwd(), '..'); +const specRoot = path.join(repoRoot, 'pocket-base', 'spec'); +const folders = ['openapi-wx', 'openapi-manage']; + +const allFiles = []; +for (const folder of folders) { + const dir = path.join(specRoot, folder); + for (const name of fs.readdirSync(dir)) { + if (name.endsWith('.yaml')) allFiles.push(path.join(dir, name)); + } +} + +const docCache = new Map(); +function loadDoc(filePath) { + if (!docCache.has(filePath)) { + const text = fs.readFileSync(filePath, 'utf8'); + docCache.set(filePath, YAML.parse(text)); + } + return docCache.get(filePath); +} + +function deepClone(v) { + return v == null ? v : JSON.parse(JSON.stringify(v)); +} + +function decodePointer(seg) { + return seg.replace(/~1/g, '/').replace(/~0/g, '~'); +} + +function getByPointer(doc, pointer) { + if (!pointer || pointer === '#' || pointer === '') return doc; + const parts = pointer.replace(/^#/, '').split('/').filter(Boolean).map(decodePointer); + let cur = doc; + for (const p of parts) { + if (cur == null) return undefined; + cur = cur[p]; + } + return cur; +} + +function mergeObjects(base, extra) { + if (base && typeof base === 'object' && !Array.isArray(base) && extra && typeof extra === 'object' && !Array.isArray(extra)) { + return { ...base, ...extra }; + } + return base; +} + +function isExternalRef(ref) { + if (typeof ref !== 'string') return false; + if (ref.startsWith('#')) return false; + if (/^https?:\/\//i.test(ref)) return false; + const [filePart] = ref.split('#'); + return !!filePart; +} + +function resolveExternalRef(ref, baseFile) { + const [filePart, hashPart = ''] = ref.split('#'); + const targetFile = path.resolve(path.dirname(baseFile), filePart); + const targetDoc = loadDoc(targetFile); + const pointer = hashPart ? `#${hashPart}` : '#'; + const targetNode = getByPointer(targetDoc, pointer); + return { targetFile, targetNode: deepClone(targetNode) }; +} + +function derefExternals(node, baseFile, seen = new Set()) { + if (Array.isArray(node)) { + return node.map((item) => derefExternals(item, baseFile, seen)); + } + if (!node || typeof node !== 'object') { + return node; + } + + if (typeof node.$ref === 'string' && isExternalRef(node.$ref)) { + const key = `${baseFile}::${node.$ref}`; + if (seen.has(key)) { + return node; + } + seen.add(key); + + const { targetFile, targetNode } = resolveExternalRef(node.$ref, baseFile); + let inlined = derefExternals(targetNode, targetFile, seen); + + const siblings = { ...node }; + delete siblings.$ref; + if (Object.keys(siblings).length > 0) { + inlined = mergeObjects(inlined, derefExternals(siblings, baseFile, seen)); + } + return inlined; + } + + const out = {}; + for (const [k, v] of Object.entries(node)) { + out[k] = derefExternals(v, baseFile, seen); + } + return out; +} + +function ensureTopLevel(doc, filePath) { + if (!doc.openapi) doc.openapi = '3.1.0'; + if (!doc.info || typeof doc.info !== 'object') { + const base = path.basename(filePath, '.yaml'); + const group = filePath.includes('openapi-wx') ? 'WX Native' : 'Manage Hooks'; + doc.info = { + title: `BAI ${group} API - ${base}`, + version: '1.0.0' + }; + } else { + if (!doc.info.title) doc.info.title = `BAI API - ${path.basename(filePath, '.yaml')}`; + if (!doc.info.version) doc.info.version = '1.0.0'; + } + if (!Array.isArray(doc.servers)) { + doc.servers = [ + { url: 'https://bai-api.blv-oa.com', description: '生产环境' }, + { url: 'http://localhost:8090', description: 'PocketBase 本地环境' } + ]; + } +} + +for (const filePath of allFiles) { + const original = loadDoc(filePath); + const transformed = derefExternals(deepClone(original), filePath); + ensureTopLevel(transformed, filePath); + const outText = YAML.stringify(transformed, { lineWidth: 0 }); + fs.writeFileSync(filePath, outText, 'utf8'); + docCache.set(filePath, transformed); +} + +console.log(`Processed ${allFiles.length} yaml files under openapi-wx/openapi-manage.`); diff --git a/docs/pb_tbl_product_list.md b/docs/pb_tbl_product_list.md index 165bc6a..2ef0e86 100644 --- a/docs/pb_tbl_product_list.md +++ b/docs/pb_tbl_product_list.md @@ -16,6 +16,7 @@ | `prod_list_id` | `text` | 是 | 产品列表业务 ID,唯一标识 | | `prod_list_name` | `text` | 是 | 产品名称 | | `prod_list_modelnumber` | `text` | 否 | 产品型号 | +| `prod_list_barcode` | `text` | 否 | 产品料号 | | `prod_list_icon` | `text` | 否 | 产品图标,保存 `tbl_attachments.attachments_id`,多图时以 `|` 分隔 | | `prod_list_description` | `text` | 否 | 产品说明(editor 内容,建议保存 Markdown 或已净化 HTML) | | `prod_list_feature` | `text` | 否 | 产品特色 | @@ -50,6 +51,7 @@ ## 补充约定 - `prod_list_icon` 仅保存附件业务 ID,真实文件统一在 `tbl_attachments`;多图时按上传顺序使用 `|` 聚合。 +- `prod_list_barcode` 为可空文本字段,用于保存产品料号;当前已接入产品管理页录入、产品列表模糊检索以及方案模板中的产品快照展示。 - `is_delete` 用于软删除控制,产品停用/删除时建议优先标记为 `1`。 - 集合默认查询规则已内置 `is_delete = 0`,产品列表默认不返回已软删除记录。 - 当前预构建脚本中已将 `listRule` 与 `viewRule` 设置为空字符串(`""`),对应 PocketBase 的“任何人可查看”。 @@ -61,4 +63,4 @@ - 前端渲染 `prod_list_description` 时应保持和存储格式一致(Markdown 渲染器或受控 HTML 渲染),避免直接注入未净化内容。 - `prod_list_basic_price` 使用 `number`,如需货币精度策略建议后续统一为“分”或固定小数位。 - PocketBase 系统字段 `created`、`updated` 仍然存在,只是不在 collection 字段清单里单独声明。 -- 本文档为预构建结构说明,尚未执行线上建表。 +- 本文档已同步当前产品表建表脚本;若已执行脚本,则以 PocketBase 实际结构为准。 diff --git a/docs/pb_tbl_scheme_template.md b/docs/pb_tbl_scheme_template.md index 687f949..8998949 100644 --- a/docs/pb_tbl_scheme_template.md +++ b/docs/pb_tbl_scheme_template.md @@ -22,7 +22,7 @@ | `scheme_template_status` | `text` | 否 | 模板状态,如有效 / 主推 / 过期 | | `scheme_template_solution_type` | `text` | 否 | 适用方案类型 | | `scheme_template_solution_feature` | `text` | 否 | 适用方案特点 | -| `scheme_template_product_list` | `json` | 否 | 产品清单,建议格式:`[{"product_id":"PROD-xxx","qty":5,"note":"客厅使用"}]` | +| `scheme_template_product_list` | `json` | 否 | 产品清单,支持保存精简结构或完整产品快照数组 | | `scheme_template_description` | `text` | 否 | 模板说明 | | `scheme_template_remark` | `text` | 否 | 备注 | | `is_delete` | `number` | 否 | 软删除标记,`0` 表示未删除,`1` 表示已删除,默认 `0` | @@ -53,7 +53,11 @@ ## 补充约定 - `scheme_template_icon` 建议延续现有项目做法,仅保存 `attachments_id`,真实文件统一走 `tbl_attachments`。 -- `scheme_template_product_list` 建议使用 `json` 数组,单项推荐结构:`product_id`、`qty`、`note`;不要保存自由格式长字符串。 +- `scheme_template_product_list` 建议使用 `json` 数组。 +- 兼容两种结构: +- 精简结构:`{"product_id":"PROD-xxx","qty":5,"note":"客厅使用"}` +- 完整快照结构:直接保存 `tbl_product_list` 导出的整行产品对象,至少应包含 `prod_list_id`,如存在产品型号 / 产品料号也建议一并保留(如 `prod_list_modelnumber`、`prod_list_barcode`)。 +- 页面 `/manage/scheme` 当前优先通过产品选择器保存完整产品快照,便于后续直接展示产品摘要与排序。 - 若模板将来需要“官方模板 + 用户私有模板”并存,则需要额外引入发布状态字段或放宽公共模板读取规则;当前文档严格按 owner 私有模板设计。 - `is_delete` 用于软删除控制,模板删除时建议优先标记为 `1`。 - PocketBase 系统字段 `created`、`updated` 仍然存在,只是不在 collection 字段清单里单独声明。 diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js index 06a781c..42460bc 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/middlewares/requestGuards.js @@ -525,6 +525,7 @@ function validateProductMutationBody(e, isUpdate) { prod_list_id: payload.prod_list_id || '', prod_list_name: payload.prod_list_name || '', prod_list_modelnumber: payload.prod_list_modelnumber || '', + prod_list_barcode: payload.prod_list_barcode || '', prod_list_icon: normalizeAttachmentIdList(payload.prod_list_icon, 'prod_list_icon').join('|'), prod_list_description: payload.prod_list_description || '', prod_list_feature: payload.prod_list_feature || '', @@ -698,7 +699,7 @@ function validateCartMutationBody(e, isUpdate) { if (!isUpdate) { if (!payload.cart_product_id) { - throw createAppError(400, 'cart_product_id 为必填项') + throw createAppError(400, 'cart_product_id 为必填项,且必须传 tbl_product_list 的 recordId') } if (typeof payload.cart_product_quantity === 'undefined') { throw createAppError(400, 'cart_product_quantity 为必填项') diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/cartOrderService.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/cartOrderService.js index ac9b865..391ce2b 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/cartOrderService.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/cartOrderService.js @@ -227,6 +227,7 @@ function buildProductInfo(record) { prod_list_id: '', prod_list_name: '', prod_list_modelnumber: '', + prod_list_barcode: '', prod_list_basic_price: null, } } @@ -235,6 +236,7 @@ function buildProductInfo(record) { prod_list_id: record.getString('prod_list_id'), prod_list_name: record.getString('prod_list_name'), prod_list_modelnumber: record.getString('prod_list_modelnumber'), + prod_list_barcode: record.getString('prod_list_barcode'), prod_list_basic_price: record.get('prod_list_basic_price'), } } @@ -295,6 +297,7 @@ function exportCartRecord(record, productRecord) { cart_remark: record.getString('cart_remark'), product_name: productInfo.prod_list_name, product_modelnumber: productInfo.prod_list_modelnumber, + product_barcode: productInfo.prod_list_barcode, product_basic_price: productInfo.prod_list_basic_price, created: String(record.created || ''), updated: String(record.updated || ''), @@ -340,6 +343,7 @@ function exportAdminCartRecord(record) { cart_remark: record && typeof record.getString === 'function' ? record.getString('cart_remark') : String(record && record.cart_remark || ''), product_name: productInfo.prod_list_name, product_modelnumber: productInfo.prod_list_modelnumber, + product_barcode: productInfo.prod_list_barcode, product_basic_price: productInfo.prod_list_basic_price, created: String(record && record.created || ''), updated: String(record && record.updated || ''), diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/productService.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/productService.js index c6bd8ad..ff85726 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/productService.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/productService.js @@ -580,6 +580,7 @@ function exportProductRecord(record, extra) { prod_list_id: record.getString('prod_list_id'), prod_list_name: record.getString('prod_list_name'), prod_list_modelnumber: record.getString('prod_list_modelnumber'), + prod_list_barcode: record.getString('prod_list_barcode'), prod_list_icon: iconIds.join('|'), prod_list_icon_ids: iconIds, prod_list_icon_attachments: iconAttachments, @@ -639,6 +640,7 @@ function listProducts(payload) { || item.prod_list_id.toLowerCase().indexOf(keyword) !== -1 || item.prod_list_name.toLowerCase().indexOf(keyword) !== -1 || item.prod_list_modelnumber.toLowerCase().indexOf(keyword) !== -1 + || item.prod_list_barcode.toLowerCase().indexOf(keyword) !== -1 || item.prod_list_tags.toLowerCase().indexOf(keyword) !== -1 const matchedStatus = !status || item.prod_list_status === status const matchedCategory = !category || item.prod_list_category === category @@ -695,6 +697,7 @@ function createProduct(_userOpenid, payload) { record.set('prod_list_id', targetProductId) record.set('prod_list_name', normalizeText(payload.prod_list_name)) record.set('prod_list_modelnumber', normalizeText(payload.prod_list_modelnumber)) + record.set('prod_list_barcode', normalizeText(payload.prod_list_barcode)) record.set('prod_list_icon', joinUniquePipeValues(payload.prod_list_icon)) record.set('prod_list_description', normalizeText(payload.prod_list_description)) record.set('prod_list_feature', normalizeText(payload.prod_list_feature)) @@ -746,6 +749,7 @@ function updateProduct(_userOpenid, payload) { record.set('prod_list_name', normalizeText(payload.prod_list_name)) record.set('prod_list_modelnumber', normalizeText(payload.prod_list_modelnumber)) + record.set('prod_list_barcode', normalizeText(payload.prod_list_barcode)) record.set('prod_list_icon', joinUniquePipeValues(payload.prod_list_icon)) record.set('prod_list_description', normalizeText(payload.prod_list_description)) record.set('prod_list_feature', normalizeText(payload.prod_list_feature)) diff --git a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/schemeService.js b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/schemeService.js index 16722e5..8f70d48 100644 --- a/pocket-base/bai_api_pb_hooks/bai_api_shared/services/schemeService.js +++ b/pocket-base/bai_api_pb_hooks/bai_api_shared/services/schemeService.js @@ -237,12 +237,29 @@ function normalizeTemplateProductList(value) { continue } - const productId = normalizeText(item.product_id) + const productId = normalizeText(item.prod_list_id || item.product_id) if (!productId) { - throw createAppError(400, 'scheme_template_product_list 第 ' + (i + 1) + ' 项 product_id 为必填项') + throw createAppError(400, 'scheme_template_product_list 第 ' + (i + 1) + ' 项必须包含 product_id 或 prod_list_id') } ensureProductExists(productId, 'scheme_template_product_list.product_id') + const hasProductSnapshot = Object.keys(item).some(function (key) { + return key.indexOf('prod_list_') === 0 || key === 'pb_id' + }) + + if (hasProductSnapshot) { + let snapshot = null + try { + snapshot = JSON.parse(JSON.stringify(item)) + } catch (_error) { + throw createAppError(400, 'scheme_template_product_list 第 ' + (i + 1) + ' 项必须为可序列化的产品对象') + } + + snapshot.prod_list_id = productId + result.push(snapshot) + continue + } + const qty = Number(item.qty) if (!Number.isFinite(qty) || qty <= 0) { throw createAppError(400, 'scheme_template_product_list 第 ' + (i + 1) + ' 项 qty 必须为正数') diff --git a/pocket-base/bai_web_pb_hooks/views/cart-order-manage.html b/pocket-base/bai_web_pb_hooks/views/cart-order-manage.html index 70557d3..8a199da 100644 --- a/pocket-base/bai_web_pb_hooks/views/cart-order-manage.html +++ b/pocket-base/bai_web_pb_hooks/views/cart-order-manage.html @@ -574,12 +574,12 @@ } return '
' - + '' + + '' + '' + items.map(function (item) { return '' + '' - + '' + + '' + '' + '' + '' diff --git a/pocket-base/bai_web_pb_hooks/views/product-manage.html b/pocket-base/bai_web_pb_hooks/views/product-manage.html index e8248e2..07ec8f3 100644 --- a/pocket-base/bai_web_pb_hooks/views/product-manage.html +++ b/pocket-base/bai_web_pb_hooks/views/product-manage.html @@ -122,7 +122,7 @@
- + @@ -135,13 +135,19 @@
当前模式:新建
-
+
+
-
-
+
+
+ + +
+
+
@@ -344,6 +350,10 @@
+
+ + +
' - + '' + + '' + '' + '' + '' @@ -1863,12 +1879,13 @@ }).join('') } - function buildCopyPayload(source, nextName, nextModel) { + function buildCopyPayload(source, nextName, nextModel, nextBarcode) { return { id: generatePocketBaseRecordId(), prod_list_id: '', prod_list_name: normalizeText(nextName), prod_list_modelnumber: normalizeText(nextModel), + prod_list_barcode: normalizeText(nextBarcode), prod_list_icon: source && source.prod_list_icon ? normalizeText(source.prod_list_icon) : '', prod_list_description: source && source.prod_list_description ? normalizeText(source.prod_list_description) : '', prod_list_feature: source && source.prod_list_feature ? normalizeText(source.prod_list_feature) : '', @@ -1894,9 +1911,11 @@ state.copySourceProductId = source ? normalizeText(source.prod_list_id) : '' const defaultName = normalizeText(source && source.prod_list_name) const defaultModel = normalizeText(source && source.prod_list_modelnumber) + const defaultBarcode = normalizeText(source && source.prod_list_barcode) copyNameInputEl.value = defaultName ? (defaultName + '-副本') : '' copyModelInputEl.value = defaultModel + copyBarcodeInputEl.value = defaultBarcode copyModalEl.classList.add('show') setTimeout(function () { @@ -1910,6 +1929,7 @@ copyModalEl.classList.remove('show') copyNameInputEl.value = '' copyModelInputEl.value = '' + copyBarcodeInputEl.value = '' } async function copyProduct(productId) { @@ -1949,7 +1969,7 @@ return } - const payload = buildCopyPayload(source, normalizedName, copyModelInputEl.value) + const payload = buildCopyPayload(source, normalizedName, copyModelInputEl.value, copyBarcodeInputEl.value) setStatus('正在复制产品...', '') showLoading('正在复制产品,请稍候...') @@ -2126,6 +2146,7 @@ prod_list_id: state.mode === 'edit' ? state.editingId : '', prod_list_name: normalizeText(fields.name.value), prod_list_modelnumber: normalizeText(fields.model.value), + prod_list_barcode: normalizeText(fields.barcode.value), prod_list_icon: joinPipe(finalIconIds), prod_list_description: normalizeText(fields.description.value), prod_list_feature: normalizeText(fields.feature.value), @@ -2497,6 +2518,12 @@ } }) + copyBarcodeInputEl.addEventListener('keydown', function (event) { + if (event.key === 'Enter') { + confirmCopyProduct() + } + }) + document.getElementById('submitBtn').addEventListener('click', function () { submitProduct() }) diff --git a/pocket-base/bai_web_pb_hooks/views/scheme-manage.html b/pocket-base/bai_web_pb_hooks/views/scheme-manage.html index 7d7e423..fe1d0d0 100644 --- a/pocket-base/bai_web_pb_hooks/views/scheme-manage.html +++ b/pocket-base/bai_web_pb_hooks/views/scheme-manage.html @@ -17,10 +17,10 @@ * { box-sizing: border-box; } body { margin: 0; font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background: linear-gradient(180deg, #edf6ff 0%, #f8fafc 100%); color: #0f172a; } .container { max-width: 1520px; margin: 0 auto; padding: 24px 14px 42px; } + .topbar { background: rgba(255,255,255,0.96); border: 1px solid #dbe3f0; border-radius: 20px; box-shadow: 0 18px 50px rgba(15, 23, 42, 0.08); padding: 18px; margin-bottom: 14px; } .panel { background: rgba(255,255,255,0.96); border: 1px solid #dbe3f0; border-radius: 20px; box-shadow: 0 18px 50px rgba(15, 23, 42, 0.08); padding: 18px; } .panel + .panel { margin-top: 14px; } - .header-row, .actions, .toolbar, .form-actions, .upload-row, .summary { display: flex; flex-wrap: wrap; gap: 10px; } - .header-row { justify-content: space-between; align-items: center; } + .actions, .toolbar, .form-actions, .upload-row, .summary, .product-picker-actions { display: flex; flex-wrap: wrap; gap: 10px; } .toolbar { display: grid; grid-template-columns: 1.2fr 1fr 1fr 1fr auto; gap: 10px; } .toolbar.simple { grid-template-columns: 1.5fr 1fr 1fr auto; } .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; } @@ -60,6 +60,20 @@ .thumb { width: 120px; height: 120px; border-radius: 16px; border: 1px solid #dbe3f0; object-fit: cover; background: #f8fafc; } .thumb-empty { display: flex; align-items: center; justify-content: center; color: #94a3b8; font-size: 13px; } .section-title { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; } + .product-picker-box { border: 1px solid #dbe3f0; border-radius: 16px; background: linear-gradient(180deg, #f8fbff 0%, #ffffff 100%); padding: 14px; } + .product-picker-grid { display: grid; grid-template-columns: 1fr 1.2fr auto auto; gap: 10px; align-items: end; } + .product-picker-actions { justify-content: flex-end; } + .product-list-summary { margin-top: 12px; border: 1px solid #dbe3f0; border-radius: 14px; background: #fff; overflow: hidden; } + .product-list-summary:empty { display: none; } + .product-list-empty { padding: 16px; color: #64748b; font-size: 13px; text-align: center; } + .product-summary-row { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; padding: 12px 14px; border-bottom: 1px solid #e5e7eb; } + .product-summary-row:last-child { border-bottom: none; } + .product-summary-order { width: 28px; height: 28px; border-radius: 999px; background: #eff6ff; color: #1d4ed8; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; } + .product-summary-main { min-width: 0; } + .product-summary-title { font-weight: 700; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .product-summary-meta { margin-top: 4px; color: #64748b; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .product-summary-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; } + .product-summary-actions .btn { padding: 8px 12px; font-size: 13px; } .loading-mask { position: fixed; inset: 0; display: none; align-items: center; justify-content: center; padding: 24px; background: rgba(15, 23, 42, 0.42); z-index: 9999; } .loading-mask.show { display: flex; } .loading-card { min-width: min(92vw, 320px); padding: 24px 20px; border-radius: 20px; background: rgba(255,255,255,0.98); border: 1px solid #dbe3f0; text-align: center; box-shadow: 0 28px 70px rgba(15, 23, 42, 0.2); } @@ -67,7 +81,7 @@ .muted-block { padding: 12px 14px; border-radius: 14px; background: #f8fafc; border: 1px solid #e2e8f0; color: #475569; font-size: 13px; line-height: 1.7; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @media (max-width: 1080px) { - .grid, .toolbar, .toolbar.simple, .thumb-box { grid-template-columns: 1fr; } + .grid, .toolbar, .toolbar.simple, .thumb-box, .product-picker-grid { grid-template-columns: 1fr; } } @media (max-width: 920px) { table, thead, tbody, th, td, tr { display: block; } @@ -75,22 +89,20 @@ tr { margin-bottom: 12px; border-bottom: 1px solid #e5e7eb; } td { display: flex; justify-content: space-between; gap: 10px; } td::before { content: attr(data-label); font-weight: 700; color: #475569; } + .product-summary-row { grid-template-columns: 1fr; } + .product-summary-actions { justify-content: flex-start; } } {{ template "theme_head" . }}
-
-
-
-

方案预设管理

-
页面负责管理 `tbl_scheme_template` 与 `tbl_scheme`。模板图标上传会写入附件表,再把附件 ID 回填到模板记录。
-
-
- 返回主页 - -
+
+

方案预设管理

+
页面负责管理 `tbl_scheme_template` 与 `tbl_scheme`。模板图标上传会写入附件表,再把附件 ID 回填到模板记录。
+
+ 返回主页 +
@@ -113,7 +125,7 @@

方案模板

-
录入和管理 `tbl_scheme_template`。`scheme_template_product_list` 使用 JSON 数组编辑。
+
录入和管理 `tbl_scheme_template`。产品清单支持按分类挑选产品,并自动同步为 JSON 数组。
@@ -202,10 +214,39 @@
+
+ +
+
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
选择逻辑与产品管理页一致:先选分类,再选产品。加入后会把该产品整行数据写入下方 JSON 数组。
+
+
暂无已选产品,请先选择分类和产品后加入。
+
+
+
- -
必须是数组,每项至少包含 `product_id` 与正数 `qty`。
+ +
默认由上方构建器自动同步。你也可以直接手动编辑 JSON,失去焦点后页面会尝试重新渲染简要清单。
@@ -373,6 +414,11 @@ const currentModeEl = document.getElementById('currentMode') const templateCountEl = document.getElementById('templateCount') const schemeCountEl = document.getElementById('schemeCount') + const templateProductSummaryEl = document.getElementById('templateProductSummary') + + const productDictNameMap = { + category: '产品-产品分类', + } const state = { templateMode: 'idle', @@ -382,6 +428,9 @@ templates: [], schemes: [], lastUploadedTemplateIcon: null, + productDictionariesByName: {}, + selectableProducts: [], + templateProductItems: [], } const templateFields = { @@ -394,6 +443,9 @@ solutionFeature: document.getElementById('templateSolutionFeature'), iconId: document.getElementById('templateIconId'), iconFile: document.getElementById('templateIconFile'), + productCategoryFilter: document.getElementById('templateProductCategoryFilter'), + productSelect: document.getElementById('templateProductSelect'), + productSummary: templateProductSummaryEl, productList: document.getElementById('templateProductList'), description: document.getElementById('templateDescription'), remark: document.getElementById('templateRemark'), @@ -583,6 +635,290 @@ } } + function cloneJsonValue(value) { + try { + return JSON.parse(JSON.stringify(value)) + } catch (_error) { + return null + } + } + + function findProductDictByName(name) { + return state.productDictionariesByName[name] || null + } + + function getProductDictItems(dictName) { + const dict = findProductDictByName(dictName) + if (!dict || !Array.isArray(dict.items)) { + return [] + } + return dict.items + } + + function fillSelectByDict(selectEl, dictName, defaultLabel) { + if (!selectEl) { + return + } + + const items = getProductDictItems(dictName) + const currentValue = selectEl.value || '' + let html = '' + + for (let i = 0; i < items.length; i += 1) { + const value = normalizeText(items[i].enum || '') + const label = normalizeText(items[i].description || value) + html += '' + } + + selectEl.innerHTML = html + if (currentValue) { + selectEl.value = currentValue + } + } + + function getTemplateProductId(item) { + return normalizeText(item && (item.prod_list_id || item.product_id)) + } + + function getProductSourceById(productId) { + const targetId = normalizeText(productId) + if (!targetId) { + return null + } + + for (let i = 0; i < state.selectableProducts.length; i += 1) { + if (normalizeText(state.selectableProducts[i].prod_list_id) === targetId) { + return state.selectableProducts[i] + } + } + + return null + } + + function buildTemplateProductSummary(item) { + const current = item && typeof item === 'object' ? item : {} + const productId = getTemplateProductId(current) + const source = getProductSourceById(productId) || current + const title = normalizeText(source.prod_list_name || source.product_name || productId || '未命名产品') + const model = normalizeText(source.prod_list_modelnumber) + const barcode = normalizeText(source.prod_list_barcode || source.product_barcode) + const category = normalizeText(source.prod_list_category) + const status = normalizeText(source.prod_list_status) + const price = source && (source.prod_list_basic_price || source.prod_list_basic_price === 0) + ? ('¥' + source.prod_list_basic_price) + : '' + const qty = current && (current.qty || current.qty === 0) ? ('数量 ' + current.qty) : '' + const note = normalizeText(current && current.note) + + return { + productId: productId, + title: title, + meta: [productId, model, barcode, category, status, price, qty, note].filter(Boolean).join(' / '), + } + } + + function syncTemplateProductListTextarea() { + templateFields.productList.value = toJsonText(state.templateProductItems) + } + + function renderTemplateProductSummary() { + if (!templateFields.productSummary) { + return + } + + if (!state.templateProductItems.length) { + templateFields.productSummary.innerHTML = '
暂无已选产品,请先选择分类和产品后加入。
' + return + } + + const rows = [] + for (let i = 0; i < state.templateProductItems.length; i += 1) { + const summary = buildTemplateProductSummary(state.templateProductItems[i]) + rows.push( + '
' + + '
' + (i + 1) + '
' + + '
' + + '
' + escapeHtml(summary.title) + '
' + + '
' + escapeHtml(summary.meta || '未补充摘要信息') + '
' + + '
' + + '
' + + '' + + '' + + '' + + '
' + + '
' + ) + } + + templateFields.productSummary.innerHTML = rows.join('') + } + + function setTemplateProductItems(items, options) { + const safeItems = Array.isArray(items) ? items : [] + const nextItems = [] + + for (let i = 0; i < safeItems.length; i += 1) { + const cloned = cloneJsonValue(safeItems[i]) + if (cloned && typeof cloned === 'object') { + nextItems.push(cloned) + } + } + + state.templateProductItems = nextItems + if (!options || !options.skipTextareaSync) { + syncTemplateProductListTextarea() + } + renderTemplateProductSummary() + } + + function hydrateTemplateProductItemsFromTextarea() { + try { + const parsed = parseJsonTextarea(templateFields.productList.value, 'scheme_template_product_list') + setTemplateProductItems(parsed) + setStatus(templateStatusEl, '产品清单 JSON 已同步为简要列表。', 'success') + return parsed + } catch (error) { + setStatus(templateStatusEl, error.message || '产品清单 JSON 解析失败', 'error') + throw error + } + } + + function renderTemplateProductCategoryOptions() { + fillSelectByDict(templateFields.productCategoryFilter, productDictNameMap.category, '全部分类') + } + + function renderTemplateProductOptions() { + const category = normalizeText(templateFields.productCategoryFilter.value) + const options = [''] + const items = [] + + for (let i = 0; i < state.selectableProducts.length; i += 1) { + const item = state.selectableProducts[i] + if (category && normalizeText(item.prod_list_category) !== category) { + continue + } + items.push(item) + } + + items.sort(function (a, b) { + const sortDiff = Number(a.prod_list_sort || 0) - Number(b.prod_list_sort || 0) + if (sortDiff !== 0) { + return sortDiff + } + return String(a.prod_list_name || '').localeCompare(String(b.prod_list_name || '')) + }) + + for (let i = 0; i < items.length; i += 1) { + const item = items[i] + const value = normalizeText(item.prod_list_id) + const label = [ + normalizeText(item.prod_list_name), + normalizeText(item.prod_list_modelnumber), + normalizeText(item.prod_list_barcode), + normalizeText(item.prod_list_category), + ].filter(Boolean).join(' / ') + options.push('') + } + + templateFields.productSelect.innerHTML = options.join('') + } + + async function loadTemplateProductResources(skipStatus) { + if (!skipStatus) { + showLoading('正在加载产品分类与产品库...') + } + try { + const dictionaries = await requestJson('/dictionary/list', {}) + const dictItems = Array.isArray(dictionaries && dictionaries.items) ? dictionaries.items : [] + state.productDictionariesByName = {} + for (let i = 0; i < dictItems.length; i += 1) { + state.productDictionariesByName[dictItems[i].dict_name] = dictItems[i] + } + + const products = await requestJson('/product/list', { + keyword: '', + status: '', + prod_list_category: '', + }) + state.selectableProducts = Array.isArray(products && products.items) ? products.items : [] + renderTemplateProductCategoryOptions() + renderTemplateProductOptions() + renderTemplateTable() + renderTemplateProductSummary() + + if (!skipStatus) { + setStatus(pageStatusEl, '模板可选产品数据已刷新。', 'success') + } + } catch (error) { + if (!skipStatus) { + setStatus(pageStatusEl, error.message || '加载模板可选产品失败', 'error') + } + throw error + } finally { + if (!skipStatus) { + hideLoading() + } + } + } + + async function addSelectedTemplateProduct() { + const productId = normalizeText(templateFields.productSelect.value) + if (!productId) { + setStatus(templateStatusEl, '请先选择要加入模板的产品。', 'error') + return + } + + for (let i = 0; i < state.templateProductItems.length; i += 1) { + if (getTemplateProductId(state.templateProductItems[i]) === productId) { + setStatus(templateStatusEl, '该产品已在清单中,可直接调整顺序。', 'error') + return + } + } + + showLoading('正在读取产品详情...') + try { + const detail = await requestJson('/product/detail', { prod_list_id: productId }) + const nextItems = state.templateProductItems.slice() + nextItems.push(detail) + setTemplateProductItems(nextItems) + setStatus(templateStatusEl, '产品已加入模板清单。', 'success') + } catch (error) { + setStatus(templateStatusEl, error.message || '加入产品失败', 'error') + } finally { + hideLoading() + } + } + + function moveTemplateProductItem(index, offset) { + const currentIndex = Number(index) + const targetIndex = currentIndex + Number(offset) + if (!Number.isInteger(currentIndex) || currentIndex < 0 || currentIndex >= state.templateProductItems.length) { + return + } + if (!Number.isInteger(targetIndex) || targetIndex < 0 || targetIndex >= state.templateProductItems.length) { + return + } + + const nextItems = state.templateProductItems.slice() + const currentItem = nextItems[currentIndex] + nextItems[currentIndex] = nextItems[targetIndex] + nextItems[targetIndex] = currentItem + setTemplateProductItems(nextItems) + setStatus(templateStatusEl, '产品顺序已调整。', 'success') + } + + function removeTemplateProductItem(index) { + const currentIndex = Number(index) + if (!Number.isInteger(currentIndex) || currentIndex < 0 || currentIndex >= state.templateProductItems.length) { + return + } + + const nextItems = state.templateProductItems.slice() + nextItems.splice(currentIndex, 1) + setTemplateProductItems(nextItems) + setStatus(templateStatusEl, '产品已从模板清单移除。', 'success') + } + function formatDateTimeInput(value) { const text = normalizeText(value) if (!text) { @@ -633,6 +969,12 @@ for (let i = 0; i < state.templates.length; i += 1) { const item = state.templates[i] const productList = Array.isArray(item.scheme_template_product_list) ? item.scheme_template_product_list : [] + const productSummary = productList.length + ? productList.map(function (productItem, index) { + const summary = buildTemplateProductSummary(productItem) + return (index + 1) + '. ' + summary.title + (summary.meta ? (' / ' + summary.meta) : '') + }).join('\n') + : '-' rows.push( '
' + '' @@ -640,7 +982,7 @@ + '' + '' + '' - + '' + + '' + '
商品名称型号数量单价状态加入时间购物车名商品名称型号/料号数量单价状态加入时间购物车名
' + escapeHtml(item.product_name || item.cart_product_business_id || item.cart_product_id || '-') + '
recordId:' + escapeHtml(item.cart_product_id || '-') + '
业务ID:' + escapeHtml(item.cart_product_business_id || '-') + '
' + escapeHtml(item.product_modelnumber || '-') + '
' + escapeHtml(item.product_modelnumber || '-') + '
料号:' + escapeHtml(item.product_barcode || '-') + '
' + escapeHtml(item.cart_product_quantity || 0) + '¥' + escapeHtml(item.cart_at_price || 0) + '' + escapeHtml(item.cart_status || '-') + '
' + escapeHtml(item.prod_list_name || '') + '
' + escapeHtml(item.prod_list_modelnumber || '') + '
' + escapeHtml(item.prod_list_name || '') + '
型号:' + escapeHtml(item.prod_list_modelnumber || '-') + '
料号:' + escapeHtml(item.prod_list_barcode || '-') + '
' + escapeHtml(item.prod_list_category || '-') + '
方案:' + escapeHtml(item.prod_list_plantype || '-') + ' / 系列:' + escapeHtml(item.prod_list_series || '-') + '
分类排序: ' + escapeHtml(item.prod_list_sort === null || typeof item.prod_list_sort === 'undefined' ? '-' : item.prod_list_sort) + '(第 ' + escapeHtml(item.prod_list_category_rank || '-') + ' 位)
' + escapeHtml(item.prod_list_tags || '-') + '
' + escapeHtml(item.prod_list_status || '-') + '
¥' + escapeHtml(item.prod_list_basic_price === null || typeof item.prod_list_basic_price === 'undefined' ? '-' : item.prod_list_basic_price) + '
' + escapeHtml(item.scheme_template_id) + '
' + escapeHtml(item.scheme_template_owner) + '
' + escapeHtml(item.scheme_template_label || '-') + '
' + escapeHtml(item.scheme_template_status || '-') + '
' + escapeHtml(item.scheme_template_solution_type || '-') + '
' + escapeHtml(item.scheme_template_solution_feature || '-') + '
' + escapeHtml(toJsonText(productList)) + '
' + escapeHtml(productSummary) + '
' + '' + '' @@ -698,11 +1040,14 @@ templateFields.solutionFeature.value = '' templateFields.iconId.value = '' templateFields.iconFile.value = '' - templateFields.productList.value = '[]' + templateFields.productCategoryFilter.value = '' + templateFields.productSelect.innerHTML = '' templateFields.description.value = '' templateFields.remark.value = '' state.lastUploadedTemplateIcon = null + setTemplateProductItems([]) renderTemplateIcon('') + renderTemplateProductOptions() } function resetSchemeForm() { @@ -796,8 +1141,11 @@ async function refreshAll() { showLoading('正在刷新模板与方案数据...') try { - await loadTemplates() - await loadSchemes() + await Promise.all([ + loadTemplates(), + loadSchemes(), + loadTemplateProductResources(true), + ]) setStatus(pageStatusEl, '数据刷新完成。', 'success') } catch (error) { setStatus(pageStatusEl, error.message || '刷新失败', 'error') @@ -824,7 +1172,7 @@ templateFields.solutionType.value = detail.scheme_template_solution_type || '' templateFields.solutionFeature.value = detail.scheme_template_solution_feature || '' templateFields.iconId.value = detail.scheme_template_icon || '' - templateFields.productList.value = toJsonText(detail.scheme_template_product_list || []) + setTemplateProductItems(detail.scheme_template_product_list || []) templateFields.description.value = detail.scheme_template_description || '' templateFields.remark.value = detail.scheme_template_remark || '' state.lastUploadedTemplateIcon = detail.scheme_template_icon_attachment || null @@ -877,6 +1225,8 @@ } function buildTemplatePayload() { + const productList = parseJsonTextarea(templateFields.productList.value, 'scheme_template_product_list') + setTemplateProductItems(productList) return { scheme_template_id: normalizeText(templateFields.id.value), scheme_template_name: normalizeText(templateFields.name.value), @@ -886,7 +1236,7 @@ scheme_template_status: normalizeText(templateFields.status.value), scheme_template_solution_type: normalizeText(templateFields.solutionType.value), scheme_template_solution_feature: normalizeText(templateFields.solutionFeature.value), - scheme_template_product_list: parseJsonTextarea(templateFields.productList.value, 'scheme_template_product_list'), + scheme_template_product_list: productList, scheme_template_description: templateFields.description.value || '', scheme_template_remark: templateFields.remark.value || '', } @@ -1066,12 +1416,31 @@ document.getElementById('uploadTemplateIconBtn').addEventListener('click', function () { handleTemplateIconUpload() }) + document.getElementById('addTemplateProductBtn').addEventListener('click', function () { + addSelectedTemplateProduct() + }) + document.getElementById('reloadTemplateProductsBtn').addEventListener('click', function () { + loadTemplateProductResources() + }) document.getElementById('clearTemplateIconBtn').addEventListener('click', function () { templateFields.iconId.value = '' templateFields.iconFile.value = '' state.lastUploadedTemplateIcon = null renderTemplateIcon('') }) + templateFields.productCategoryFilter.addEventListener('change', function () { + renderTemplateProductOptions() + }) + templateFields.productList.addEventListener('blur', function () { + if (!normalizeText(templateFields.productList.value)) { + setTemplateProductItems([]) + return + } + + try { + hydrateTemplateProductItemsFromTextarea() + } catch (_error) {} + }) templateFields.iconId.addEventListener('input', function () { if (!normalizeText(templateFields.iconId.value)) { @@ -1101,6 +1470,24 @@ return } + const templateProductUpIndex = target.getAttribute('data-template-product-up') + if (templateProductUpIndex !== null) { + moveTemplateProductItem(templateProductUpIndex, -1) + return + } + + const templateProductDownIndex = target.getAttribute('data-template-product-down') + if (templateProductDownIndex !== null) { + moveTemplateProductItem(templateProductDownIndex, 1) + return + } + + const templateProductRemoveIndex = target.getAttribute('data-template-product-remove') + if (templateProductRemoveIndex !== null) { + removeTemplateProductItem(templateProductRemoveIndex) + return + } + const schemeEditId = target.getAttribute('data-scheme-edit') if (schemeEditId) { editScheme(schemeEditId) diff --git a/pocket-base/spec/openapi-manage.yaml b/pocket-base/spec/openapi-manage.yaml deleted file mode 100644 index 29ad05a..0000000 --- a/pocket-base/spec/openapi-manage.yaml +++ /dev/null @@ -1,1811 +0,0 @@ -openapi: 3.1.0 -info: - title: BAI PocketBase Manage API - description: | - 基于 PocketBase `bai_api_pb_hooks` 的对外接口文档,可直接导入 Postman。 - 当前 `tbl_auth_users.openid` 已被定义为全平台统一身份锚点: - - 微信用户:`openid = 微信 openid` - - 平台用户:`openid = 服务端生成的 GUID` - 请在 Apifox 环境中统一设置全局 Header:`Authorization: Bearer {{token}}`。 - version: 1.0.0-manage - license: - name: Proprietary - identifier: LicenseRef-Proprietary -servers: - - url: https://bai-api.blv-oa.com - description: "生产环境" - - url: http://localhost:8090 - description: "PocketBase 本地环境" -tags: - - name: 系统 - description: "基础检查接口" - - name: 平台认证 - description: "面向平台用户的认证接口;平台用户会生成 GUID 并写入统一 `openid` 字段。" - - name: 字典管理 - description: "字典读接口公开;字典写接口面向 ManagePlatform 用户。" - - name: 附件管理 - description: "面向 ManagePlatform 用户的附件上传、查询与删除接口。" - - name: 文档管理 - description: "面向 ManagePlatform 用户的文档新增、查询、修改、删除接口;查询时会自动返回关联附件的 PocketBase 文件流链接。" - - name: 文档历史 - description: "面向 ManagePlatform 用户的文档操作历史查询接口。" -components: - schemas: - ApiResponse: - type: object - required: [statusCode, errMsg, data] - properties: - statusCode: - type: integer - description: "业务状态码" - example: 200 - errMsg: - type: string - description: "业务提示信息" - example: 操作成功 - data: - description: "业务响应数据" - type: object - additionalProperties: true - HealthData: - type: object - properties: - status: - type: string - example: healthy - version: - type: string - description: "当前已部署 hooks 版本号,用于确认发布是否生效" - example: 2026.03.26-health-probe.1 - timestamp: - type: string - format: date-time - UsersCountData: - type: object - properties: - total_users: - type: integer - description: "tbl_auth_users 表中的用户总数" - example: 128 - HelloWorldData: - type: object - properties: - message: - type: string - example: Hello, World! - timestamp: - type: string - format: date-time - status: - type: string - example: success - build_time: - type: - - string - - 'null' - format: date-time - CompanyInfo: - anyOf: - - type: object - description: 用户所属公司信息;当用户尚未绑定公司时返回 `null` - properties: - pb_id: - type: string - description: PocketBase 记录主键 id - company_id: - type: string - description: 公司业务 id,由数据库自动生成 - company_name: - type: string - description: 公司名称 - company_type: - type: string - description: 公司类型 - company_entity: - type: string - description: 公司法人 - company_usci: - type: string - description: 统一社会信用代码 - company_nationality: - type: string - description: 国家名称 - company_nationality_code: - type: string - description: 国家编码 - company_province: - type: string - description: 省份名称 - company_province_code: - type: string - description: 省份编码 - company_city: - type: string - description: 城市名称 - company_city_code: - type: string - description: 城市编码 - company_district: - type: string - description: 区/县名称 - company_district_code: - type: string - description: 区/县编码 - company_postalcode: - type: string - description: 邮政编码 - company_add: - type: string - description: 公司地址 - company_status: - type: string - description: 公司状态 - company_level: - type: string - description: 公司等级 - company_owner_openid: - type: string - description: 公司所有者 openid - company_remark: - type: string - description: 备注 - created: - type: string - description: 记录创建时间 - updated: - type: string - description: 记录更新时间 - example: - pb_id: PocketBase记录主键id | string - company_id: 公司业务id,由数据库自动生成 | string - company_name: 公司名称 | string - company_type: 公司类型 | string - company_entity: 公司法人 | string - company_usci: 统一社会信用代码 | string - company_nationality: 国家名称 | string - company_nationality_code: 国家编码 | string - company_province: 省份名称 | string - company_province_code: 省份编码 | string - company_city: 城市名称 | string - company_city_code: 城市编码 | string - company_district: 区县名称 | string - company_district_code: 区县编码 | string - company_postalcode: 邮政编码 | string - company_add: 公司地址 | string - company_status: 公司状态 | string - company_level: 公司等级 | string - company_owner_openid: 公司所有者openid | string - company_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - - type: 'null' - UserInfo: - type: object - description: | - 统一用户视图。 - 其中 `openid` 为全平台统一身份标识:微信用户使用微信 openid,平台用户使用服务端生成 GUID。 - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - users_convers_id: - description: "会话侧用户 ID" - type: string - users_id: - description: "用户业务 ID" - type: string - users_idtype: - description: "用户身份来源类型" - anyOf: - - type: string - enum: [WeChat, ManagePlatform] - - type: string - users_id_number: - description: "证件号" - type: string - users_status: - description: "用户状态" - type: string - users_rank_level: - description: "用户星级数值" - type: [number, string] - users_auth_type: - description: "账户类型" - type: [number, string] - users_type: - description: "用户类型" - anyOf: - - type: string - enum: [游客, 注册用户] - - type: string - users_name: - description: "用户姓名 / 昵称" - type: string - users_phone: - description: "手机号" - type: string - users_phone_masked: - type: string - users_level: - type: string - description: "用户等级" - users_level_name: - type: string - description: "用户等级名称,按 `users_level -> 数据-会员等级` 字典描述实时解析" - users_tag: - type: string - description: "用户标签" - users_picture: - type: string - description: "用户头像附件的 `attachments_id`" - users_picture_url: - type: string - description: "根据 `users_picture -> tbl_attachments` 自动解析出的头像文件流链接" - users_id_pic_a: - type: string - description: "证件正面附件的 `attachments_id`" - users_id_pic_a_url: - type: string - description: "根据 `users_id_pic_a -> tbl_attachments` 自动解析出的文件流链接" - users_id_pic_b: - type: string - description: "证件反面附件的 `attachments_id`" - users_id_pic_b_url: - type: string - description: "根据 `users_id_pic_b -> tbl_attachments` 自动解析出的文件流链接" - users_title_picture: - type: string - description: "资质附件的 `attachments_id`" - users_title_picture_url: - type: string - description: "根据 `users_title_picture -> tbl_attachments` 自动解析出的文件流链接" - openid: - type: string - description: "全平台统一身份标识;微信用户为微信 openid,平台用户为服务端生成的 GUID" - company_id: - type: string - description: "公司业务 id,存储 `tbl_company.company_id`" - users_parent_id: - type: string - description: "上级用户业务 id" - users_promo_code: - type: string - description: "推广码" - usergroups_id: - type: string - description: "用户组业务 id" - company: - $ref: '#/components/schemas/CompanyInfo' - created: - type: string - description: "用户创建时间" - updated: - type: string - description: "用户更新时间" - example: - pb_id: PocketBase记录主键id | string - users_convers_id: 会话侧用户ID | string - users_id: 用户业务ID | string - users_idtype: 用户身份来源类型 | string - users_id_number: 证件号 | string - users_type: 用户类型 | string - users_name: 用户姓名或昵称 | string - users_status: 用户状态 | string - users_rank_level: 用户星级数值 | number - users_auth_type: 账户类型 | number - users_phone: 手机号 | string - users_phone_masked: 手机号脱敏值 | string - users_level: 用户等级 | string - users_level_name: 用户等级名称 | string - users_tag: 用户标签 | string - users_picture: 用户头像附件ID | string - users_picture_url: 用户头像文件流链接 | string - users_id_pic_a: 证件正面附件ID | string - users_id_pic_a_url: 证件正面文件流链接 | string - users_id_pic_b: 证件反面附件ID | string - users_id_pic_b_url: 证件反面文件流链接 | string - users_title_picture: 资质附件ID | string - users_title_picture_url: 资质附件文件流链接 | string - openid: 全平台统一身份标识 | string - company_id: 公司业务id | string - users_parent_id: 上级用户业务id | string - users_promo_code: 推广码 | string - usergroups_id: 用户组业务id | string - company: - pb_id: PocketBase记录主键id | string - company_id: 公司业务id,由数据库自动生成 | string - company_name: 公司名称 | string - company_type: 公司类型 | string - company_entity: 公司法人 | string - company_usci: 统一社会信用代码 | string - company_nationality: 国家名称 | string - company_nationality_code: 国家编码 | string - company_province: 省份名称 | string - company_province_code: 省份编码 | string - company_city: 城市名称 | string - company_city_code: 城市编码 | string - company_district: 区县名称 | string - company_district_code: 区县编码 | string - company_postalcode: 邮政编码 | string - company_add: 公司地址 | string - company_status: 公司状态 | string - company_level: 公司等级 | string - company_owner_openid: 公司所有者openid | string - company_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - created: 用户创建时间 | string - updated: 用户更新时间 | string - PocketBaseAuthResponse: - type: object - description: | - 项目统一认证响应。 - 所有对外接口统一返回 `statusCode`、`errMsg`、`data`,认证成功时额外返回顶层 `token`。 - properties: - statusCode: - type: integer - description: "业务状态码" - example: 200 - errMsg: - type: string - description: "业务提示信息" - example: 登录成功 - data: - description: "业务响应数据" - type: object - properties: - status: - anyOf: - - type: string - enum: [register_success, login_success] - - type: string - is_info_complete: - type: [boolean, string] - user: - $ref: '#/components/schemas/UserInfo' - token: - type: string - description: "PocketBase 原生 auth token;仅认证类接口在成功时额外返回" - example: - statusCode: 200 - errMsg: 登录成功 - data: - status: 登录或注册状态 | string - is_info_complete: 资料是否完整 | boolean - user: - pb_id: PocketBase记录主键id | string - users_id: 用户业务ID | string - users_idtype: 用户身份来源类型 | string - users_name: 用户姓名或昵称 | string - users_phone: 手机号 | string - users_phone_masked: 手机号脱敏值 | string - users_status: 用户状态 | string - users_rank_level: 用户星级数值 | number - users_auth_type: 账户类型 | number - users_type: 用户类型 | string - users_picture: 用户头像附件ID | string - users_picture_url: 用户头像文件流链接 | string - users_id_pic_a: 证件正面附件ID | string - users_id_pic_a_url: 证件正面文件流链接 | string - users_id_pic_b: 证件反面附件ID | string - users_id_pic_b_url: 证件反面文件流链接 | string - users_title_picture: 资质附件ID | string - users_title_picture_url: 资质附件文件流链接 | string - openid: 全平台统一身份标识 | string - company_id: 公司业务id | string - users_parent_id: 上级用户业务id | string - users_promo_code: 推广码 | string - usergroups_id: 用户组业务id | string - company: - pb_id: PocketBase记录主键id | string - company_id: 公司业务id,由数据库自动生成 | string - company_name: 公司名称 | string - company_type: 公司类型 | string - company_entity: 公司法人 | string - company_usci: 统一社会信用代码 | string - company_nationality: 国家名称 | string - company_nationality_code: 国家编码 | string - company_province: 省份名称 | string - company_province_code: 省份编码 | string - company_city: 城市名称 | string - company_city_code: 城市编码 | string - company_district: 区县名称 | string - company_district_code: 区县编码 | string - company_postalcode: 邮政编码 | string - company_add: 公司地址 | string - company_status: 公司状态 | string - company_level: 公司等级 | string - company_owner_openid: 公司所有者openid | string - company_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - created: 用户创建时间 | string - updated: 用户更新时间 | string - token: PocketBase原生认证token | string - WechatLoginRequest: - type: object - required: [users_wx_code] - description: "微信小程序登录/注册请求体。" - properties: - users_wx_code: - type: string - description: "微信小程序登录临时凭证 code" - example: 0a1b2c3d4e5f6g - WechatProfileRequest: - type: object - description: "微信用户资料完善请求体。" - properties: - users_name: - type: string - description: "用户姓名 / 昵称" - example: 张三 - users_phone_code: - type: string - description: "可选。若传入,服务端优先通过微信接口换取真实手机号并写入数据库" - example: 2b7d9f2e3c4a5b6d7e8f - users_phone: - type: string - description: "可选。未传 `users_phone_code` 时,可直接写入手机号" - example: '13800138000' - users_type: - type: string - description: "可选。用户类型;仅在传入非空值时更新" - example: 服务商 - company_id: - type: string - description: "可选。公司业务 id;仅在传入非空值时更新" - example: WX-COMPANY-10001 - users_tag: - type: string - description: "可选。用户标签;非空时才更新" - example: 核心客户 - users_picture: - type: string - description: "可选。用户头像附件的 `attachments_id`" - example: ATT-1743123456789-abc123 - users_id_pic_a: - type: string - description: "可选。证件正面附件的 `attachments_id`" - users_id_pic_b: - type: string - description: "可选。证件反面附件的 `attachments_id`" - users_title_picture: - type: string - description: "可选。资质附件的 `attachments_id`" - WechatProfileResponseData: - type: object - properties: - status: - type: string - enum: [update_success] - user: - $ref: '#/components/schemas/UserInfo' - PlatformRegisterRequest: - type: object - required: [users_name, users_phone, password, passwordConfirm, users_picture] - description: "平台用户注册请求体;注册成功后将生成 GUID 并写入统一 `openid` 字段。" - properties: - users_name: - type: string - description: "用户姓名 / 昵称" - example: 张三 - users_phone: - type: string - description: "手机号" - example: 13800138000 - password: - type: string - description: "PocketBase 认证密码" - example: 12345678 - passwordConfirm: - type: string - example: 12345678 - users_picture: - type: string - description: "用户头像附件的 `attachments_id`" - example: ATT-1743123456789-abc123 - users_id_number: - description: "证件号" - type: string - users_id_pic_a: - type: string - description: "可选。证件正面附件的 `attachments_id`" - users_id_pic_b: - type: string - description: "可选。证件反面附件的 `attachments_id`" - users_title_picture: - type: string - description: "可选。资质附件的 `attachments_id`" - users_level: - description: "用户等级文本" - type: string - users_tag: - description: "用户标签" - type: string - users_type: - description: "用户类型" - type: string - company_id: - description: "所属公司业务 ID" - type: string - users_parent_id: - description: "上级用户业务 ID" - type: string - users_promo_code: - description: "推广码" - type: string - usergroups_id: - description: "用户组 / 角色 ID" - type: string - PlatformLoginRequest: - type: object - required: [login_account, password] - description: "平台用户登录请求体;前端使用邮箱或手机号 + 密码提交,服务端内部转换为 PocketBase 原生 password auth。" - properties: - login_account: - type: string - description: "支持邮箱或手机号" - example: admin@example.com - password: - type: string - description: "PocketBase 认证密码" - example: 12345678 - SystemRefreshTokenRequest: - type: object - description: | - 系统刷新 token 请求体。 - `users_wx_code` 允许为空。 - 当 `Authorization` 对应 token 有效时,可不传或传空; - 当 token 失效时,需提供 `users_wx_code` 走微信 code 重新签发流程。 - properties: - users_wx_code: - type: - - string - - 'null' - description: "微信小程序登录临时凭证 code" - example: 0a1b2c3d4e5f6g - RefreshTokenData: - type: object - properties: {} - DictionaryItem: - type: object - required: [enum, description, sortOrder] - properties: - enum: - type: string - example: enabled - description: - type: string - example: 启用 - image: - type: string - description: "对应图片附件的 `attachments_id`,允许为空" - example: ATT-1743037200000-abc123 - imageUrl: - type: string - description: "根据 `image -> tbl_attachments` 自动解析出的图片文件流链接" - imageAttachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - sortOrder: - type: [integer, string] - example: 1 - example: - enum: 枚举值 | string - description: 枚举描述 | string - image: 图片附件ID | string - imageUrl: 图片文件流链接 | string - imageAttachment: - attachments_id: 附件业务ID | string - attachments_filename: 原始文件名 | string - sortOrder: 排序值 | integer - DictionaryRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - system_dict_id: - description: "字典业务 ID" - type: string - dict_name: - description: "字典名称,当前按全局唯一维护" - type: string - dict_word_is_enabled: - description: "字典是否启用" - type: [boolean, string] - dict_word_parent_id: - description: "父级字典业务 ID" - type: string - dict_word_remark: - description: "备注" - type: string - items: - type: array - items: - $ref: '#/components/schemas/DictionaryItem' - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: PocketBase记录主键id | string - system_dict_id: 字典业务ID | string - dict_name: 字典名称 | string - dict_word_is_enabled: 字典是否启用 | boolean - dict_word_parent_id: 父级字典业务ID | string - dict_word_remark: 备注 | string - items: - - enum: UT1 - description: 枚举描述 | string - image: 图片附件ID | string - imageUrl: 图片文件流链接 | string - sortOrder: 排序值 | integer - created: 记录创建时间 | string - updated: 记录更新时间 | string - DictionaryListRequest: - type: object - properties: - keyword: - type: string - description: "对 `dict_name` 的模糊搜索关键字" - example: 状态 - DictionaryDetailRequest: - type: object - required: [dict_name] - properties: - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - DictionaryMutationRequest: - type: object - required: [dict_name, items] - properties: - original_dict_name: - type: string - description: "更新时用于定位原始记录;新增时可不传" - example: 用户状态 - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - dict_word_is_enabled: - type: boolean - description: "字典是否启用" - example: true - dict_word_parent_id: - type: string - description: "父级字典业务 ID" - example: '' - dict_word_remark: - type: string - description: "备注" - example: 系统状态字典 - items: - type: array - minItems: 1 - description: "每项会分别序列化写入 `dict_word_enum`、`dict_word_description`、`dict_word_image`、`dict_word_sort_order`" - items: - $ref: '#/components/schemas/DictionaryItem' - DictionaryDeleteRequest: - type: object - required: [dict_name] - properties: - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - AttachmentRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - attachments_id: - description: "附件业务 ID" - type: string - attachments_link: - type: string - description: "PocketBase 实际存储的文件名" - attachments_url: - type: string - description: "附件文件流访问链接" - attachments_download_url: - type: string - description: "附件下载链接" - attachments_filename: - description: "原始文件名" - type: string - attachments_filetype: - description: "文件类型 / MIME" - type: string - attachments_size: - description: "文件大小" - type: [number, string] - attachments_owner: - description: "上传者业务标识" - type: string - attachments_md5: - description: "文件 MD5" - type: string - attachments_ocr: - description: "OCR 识别结果" - type: string - attachments_status: - description: "附件状态" - type: string - attachments_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: PocketBase记录主键id | string - attachments_id: 附件业务ID | string - attachments_link: PocketBase实际存储文件名 | string - attachments_url: 附件文件流访问链接 | string - attachments_download_url: 附件下载链接 | string - attachments_filename: 原始文件名 | string - attachments_filetype: 文件类型或MIME | string - attachments_size: 文件大小 | number - attachments_owner: 上传者业务标识 | string - attachments_md5: 文件MD5 | string - attachments_ocr: OCR识别结果 | string - attachments_status: 附件状态 | string - attachments_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - AttachmentListRequest: - type: object - properties: - keyword: - type: string - description: "对 `attachments_id`、`attachments_filename` 的模糊搜索关键字" - example: 手册 - status: - type: string - description: "按附件状态过滤" - example: active - AttachmentDetailRequest: - type: object - required: [attachments_id] - properties: - attachments_id: - type: string - description: "附件业务 ID" - example: ATT-1743037200000-abc123 - AttachmentUploadRequest: - type: object - required: [attachments_link] - properties: - attachments_link: - type: string - format: binary - description: "要上传到 `tbl_attachments` 的单个文件" - attachments_filename: - type: string - description: "原始文件名;不传时可由前端直接使用文件名" - attachments_filetype: - type: string - description: "文件 MIME 类型" - attachments_size: - type: number - description: "文件大小" - attachments_md5: - description: "文件 MD5" - type: string - attachments_ocr: - description: "OCR 识别结果" - type: string - attachments_status: - type: string - description: "附件状态" - example: active - attachments_remark: - description: "备注" - type: string - DocumentRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - document_id: - description: "文档业务 ID" - type: string - document_create: - type: string - description: "文档创建时间,由数据库自动生成" - document_effect_date: - description: "文档生效日期" - type: string - document_expiry_date: - description: "文档到期日期" - type: string - document_type: - type: string - description: "多选时按 `system_dict_id@dict_word_enum|...` 保存" - document_title: - description: "文档标题" - type: string - document_subtitle: - description: "文档副标题" - type: string - document_summary: - description: "文档摘要" - type: string - document_content: - description: "正文内容,保存 Markdown" - type: string - document_image: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_image_ids: - type: array - description: "`document_image` 解析后的附件 id 列表" - items: - type: string - document_image_urls: - type: array - description: "根据 `document_image -> tbl_attachments` 自动解析出的图片文件流链接列表" - items: - type: string - document_image_url: - type: string - description: "兼容字段,返回第一张图片的文件流链接" - document_image_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_image_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_video: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_video_ids: - type: array - description: "`document_video` 解析后的附件 id 列表" - items: - type: string - document_video_urls: - type: array - description: "根据 `document_video -> tbl_attachments` 自动解析出的视频文件流链接列表" - items: - type: string - document_video_url: - type: string - description: "兼容字段,返回第一个视频的文件流链接" - document_video_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_video_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_file: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_file_ids: - type: array - description: "`document_file` 解析后的附件 id 列表" - items: - type: string - document_file_urls: - type: array - description: "根据 `document_file -> tbl_attachments` 自动解析出的文件流链接列表" - items: - type: string - document_file_url: - type: string - description: "兼容字段,返回第一个文件的文件流链接" - document_file_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_file_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_owner: - type: string - description: "上传者 openid" - document_relation_model: - description: "关联机型 / 模型标识" - type: string - document_keywords: - type: string - description: "固定字典多选字段,使用 `|` 分隔" - document_share_count: - description: "分享次数" - type: [number, string] - document_download_count: - description: "下载次数" - type: [number, string] - document_favorite_count: - description: "收藏次数" - type: [number, string] - document_status: - type: string - description: "文档状态,仅允许 `有效` 或 `过期`,由系统根据生效日期和到期日期自动计算;当两者都为空时默认 `有效`" - document_embedding_status: - description: "文档嵌入状态" - type: string - document_embedding_error: - description: "文档嵌入错误原因" - type: string - document_embedding_lasttime: - description: "最后一次嵌入更新时间" - type: string - document_vector_version: - description: "向量版本号 / 模型名称" - type: string - document_product_categories: - type: string - description: "固定字典多选字段,使用 `|` 分隔" - document_application_scenarios: - type: string - description: "固定字典多选字段,使用 `|` 分隔" - document_hotel_type: - type: string - description: "固定字典多选字段,使用 `|` 分隔" - document_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: PocketBase记录主键id | string - document_id: 文档业务ID | string - document_create: 文档创建时间,由数据库自动生成 | string - document_effect_date: 文档生效日期 | string - document_expiry_date: 文档到期日期 | string - document_type: 文档类型,按system_dict_id@dict_word_enum保存 | string - document_title: 文档标题 | string - document_subtitle: 文档副标题 | string - document_summary: 文档摘要 | string - document_content: 正文内容Markdown | string - document_image: 图片附件ID列表,使用竖线分隔 | string - document_image_ids: - - 图片附件ID | string - document_image_urls: - - 图片文件流链接 | string - document_image_url: 第一张图片文件流链接 | string - document_video: 视频附件ID列表,使用竖线分隔 | string - document_video_ids: - - 视频附件ID | string - document_video_urls: - - 视频文件流链接 | string - document_video_url: 第一个视频文件流链接 | string - document_file: 文件附件ID列表,使用竖线分隔 | string - document_file_ids: - - 文件附件ID | string - document_file_urls: - - 文件流链接 | string - document_file_url: 第一个文件流链接 | string - document_owner: 上传者openid | string - document_relation_model: 关联机型或模型标识 | string - document_keywords: 关键词多选,使用竖线分隔 | string - document_share_count: 分享次数 | number - document_download_count: 下载次数 | number - document_favorite_count: 收藏次数 | number - document_status: 文档状态 | string - document_embedding_status: 文档嵌入状态 | string - document_embedding_error: 文档嵌入错误原因 | string - document_embedding_lasttime: 最后一次嵌入更新时间 | string - document_vector_version: 向量版本号或模型名称 | string - document_product_categories: 产品关联文档多选,使用竖线分隔 | string - document_application_scenarios: 筛选依据多选,使用竖线分隔 | string - document_hotel_type: 适用场景多选,使用竖线分隔 | string - document_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - DocumentListRequest: - type: object - properties: - keyword: - type: string - description: "对 `document_id`、`document_title`、`document_subtitle`、`document_summary`、`document_keywords` 的模糊搜索关键字" - example: 安装 - status: - type: string - example: active - document_type: - type: string - description: "支持按存储值过滤;多选时格式为 `system_dict_id@dict_word_enum|...`" - example: 说明书 - DocumentDetailRequest: - type: object - required: [document_id] - properties: - document_id: - type: string - description: "文档业务 ID" - example: DOC-1743037200000-abc123 - DocumentMutationRequest: - type: object - required: [document_title, document_type] - properties: - document_id: - type: string - description: "创建时可不传,由服务端自动生成;更新时必填" - example: DOC-1743037200000-abc123 - document_effect_date: - type: string - description: "支持 `YYYY-MM-DD` 或 PocketBase 可识别日期时间字符串" - example: 2026-03-27 - document_expiry_date: - type: string - description: "支持 `YYYY-MM-DD` 或 PocketBase 可识别日期时间字符串" - example: 2027-03-27 - document_type: - type: string - description: "必填;前端显示为字典项描述,存库时按 `system_dict_id@dict_word_enum|...` 保存" - document_title: - description: "文档标题" - type: string - document_subtitle: - description: "文档副标题" - type: string - document_summary: - description: "文档摘要" - type: string - document_content: - description: "正文内容,保存 Markdown" - type: string - document_image: - oneOf: - - type: string - description: "多个图片附件 id 使用 `|` 分隔" - - type: array - items: - type: string - description: "图片附件 id 列表;支持数组或 `|` 分隔字符串" - document_video: - oneOf: - - type: string - description: "多个视频附件 id 使用 `|` 分隔" - - type: array - items: - type: string - description: "视频附件 id 列表;支持数组或 `|` 分隔字符串" - document_file: - oneOf: - - type: string - description: "多个文件附件 id 使用 `|` 分隔" - - type: array - items: - type: string - description: "文件附件 id 列表;支持数组或 `|` 分隔字符串" - document_relation_model: - description: "关联机型 / 模型标识" - type: string - document_keywords: - type: string - description: "从 `文档-关键词` 字典多选后使用 `|` 分隔保存" - document_share_count: - description: "分享次数" - type: number - document_download_count: - description: "下载次数" - type: number - document_favorite_count: - description: "收藏次数" - type: number - document_status: - type: string - description: "文档状态,仅允许 `有效` 或 `过期`,由系统根据生效日期和到期日期自动计算;当两者都为空时默认 `有效`" - document_embedding_status: - description: "文档嵌入状态" - type: string - document_embedding_error: - description: "文档嵌入错误原因" - type: string - document_embedding_lasttime: - description: "最后一次嵌入更新时间" - type: string - document_vector_version: - description: "向量版本号 / 模型名称" - type: string - document_product_categories: - type: string - description: "从 `文档-产品关联文档` 字典多选后使用 `|` 分隔保存" - document_application_scenarios: - type: string - description: "从 `文档-筛选依据` 字典多选后使用 `|` 分隔保存" - document_hotel_type: - type: string - description: "从 `文档-适用场景` 字典多选后使用 `|` 分隔保存" - document_remark: - description: "备注" - type: string - DocumentDeleteRequest: - type: object - required: [document_id] - properties: - document_id: - type: string - description: "文档业务 ID" - example: DOC-1743037200000-abc123 - DocumentHistoryRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - doh_id: - description: "文档操作历史业务 ID" - type: string - doh_document_id: - description: "关联文档业务 ID" - type: string - doh_operation_type: - description: "操作类型" - type: string - doh_user_id: - description: "操作人业务 ID" - type: string - doh_current_count: - description: "本次操作对应次数" - type: [number, string] - doh_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: PocketBase记录主键id | string - doh_id: 文档操作历史业务ID | string - doh_document_id: 关联文档业务ID | string - doh_operation_type: 操作类型 | string - doh_user_id: 操作人业务ID | string - doh_current_count: 本次操作对应次数 | number - doh_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - DocumentHistoryListRequest: - type: object - properties: - document_id: - type: string - description: "可选;传入时仅查询指定文档的操作历史" - example: DOC-1743037200000-abc123 -paths: - /pb/api/system/test-helloworld: - post: - tags: [系统] - summary: HelloWorld 测试接口 - responses: - '200': - description: "成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/HelloWorldData' - /pb/api/system/health: - post: - tags: [系统] - summary: 健康检查 - responses: - '200': - description: "成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/HealthData' - /pb/api/system/users-count: - post: - tags: [系统] - summary: 查询用户总数 - description: "统计 `tbl_auth_users` 集合中的记录总数,并返回一个数值。" - responses: - '200': - description: "成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/UsersCountData' - /pb/api/platform/register: - post: - tags: [平台认证] - summary: 平台用户注册 - description: | - 创建平台用户 auth record。 - 服务端会自动生成 GUID 并写入统一身份字段 `openid`,同时写入 `users_idtype = ManagePlatform`。 - 前端以 `users_phone + password/passwordConfirm` 注册,但服务端仍会创建 PocketBase 原生 auth 用户。 - 首次注册创建时,`users_level` 默认保持为空,不自动写入会员等级。 - 注册成功后直接返回 PocketBase 原生 auth token。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PlatformRegisterRequest' - responses: - '200': - description: "注册成功" - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseAuthResponse' - '400': - description: "参数错误或手机号已存在" - '500': - description: "GUID 生成失败、auth identity 缺失或保存用户失败" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/platform/login: - post: - tags: [平台认证] - summary: 平台用户登录 - description: | - 前端使用平台注册时保存的 `邮箱或手机号 + password` 登录。 - 仅允许 `users_idtype = ManagePlatform` 的用户通过该接口登录。 - 服务端会根据 `login_account` 自动判断邮箱或手机号,并定位平台用户,再使用该用户的 PocketBase 原生 identity(当前为 `email`)执行原生 password auth。 - 返回体中的 `user.users_level_name` 为服务端按“数据-会员等级”字典实时解析后的等级名称。 - 登录成功后直接返回 PocketBase 原生 auth token。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PlatformLoginRequest' - example: - login_account: 13509214696 - password: Momo123456 - responses: - '200': - description: "登录成功" - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseAuthResponse' - example: - statusCode: 200 - errMsg: 登录成功 - data: - status: login_success - is_info_complete: false - user: - pb_id: vtukf6agem2xbcv - users_id: '' - users_idtype: ManagePlatform - users_name: momo - users_phone: '13509214696' - users_phone_masked: '135****4696' - users_status: '' - users_rank_level: 0 - users_auth_type: 0 - users_type: '' - users_picture: '' - openid: app_momo - company_id: '' - users_parent_id: '' - users_promo_code: '' - usergroups_id: '' - company: null - created: '' - updated: '' - token: eyJhbGciOi... - '400': - description: "参数错误、密码错误或用户类型不匹配" - '404': - description: "平台用户不存在" - '500': - description: "平台用户缺少原生登录 identity 或服务端内部错误" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/dictionary/list: - post: - tags: [字典管理] - summary: 查询字典列表 - description: | - 公开读接口,无需 token。 - 支持按 `dict_name` 模糊搜索,返回字典全量信息,并将三个聚合字段组装为 `items`。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryListRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DictionaryRecord' - '415': - description: "请求体必须为 application/json" - /pb/api/dictionary/detail: - post: - tags: [字典管理] - summary: 查询指定字典 - description: | - 公开读接口,无需 token。 - 按唯一键 `dict_name` 查询单条字典,并返回组装后的 `items`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryDetailRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: "参数错误" - '404': - description: "未找到对应字典" - '415': - description: "请求体必须为 application/json" - /pb/api/dictionary/create: - post: - tags: [字典管理] - summary: 新增字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - `system_dict_id` 由服务端自动生成;`dict_name` 必须唯一; - `items` 会分别序列化写入 `dict_word_enum`、`dict_word_description`、`dict_word_image`、`dict_word_sort_order` 四个字段。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryMutationRequest' - responses: - '200': - description: "新增成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: "参数错误或 dict_name 已存在" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/dictionary/update: - post: - tags: [字典管理] - summary: 修改字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 根据 `original_dict_name`(未传时回退为 `dict_name`)定位原记录并更新。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryMutationRequest' - responses: - '200': - description: "修改成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: "参数错误或 dict_name 冲突" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到待修改字典" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/dictionary/delete: - post: - tags: [字典管理] - summary: 删除字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `dict_name` 真删除对应记录。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryDeleteRequest' - responses: - '200': - description: "删除成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - dict_name: - description: "字典名称,当前按全局唯一维护" - type: string - '400': - description: "参数错误或删除失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到待删除字典" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/attachment/list: - post: - tags: [附件管理] - summary: 查询附件列表 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 支持按 `attachments_id`、`attachments_filename` 模糊搜索,并可按 `attachments_status` 过滤。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentListRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '415': - description: "请求体必须为 application/json" - /pb/api/attachment/detail: - post: - tags: [附件管理] - summary: 查询附件详情 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `attachments_id` 查询单条附件,并返回 PocketBase 文件流链接与下载链接。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentDetailRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/AttachmentRecord' - '400': - description: "参数错误" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到对应附件" - '415': - description: "请求体必须为 application/json" - /pb/api/attachment/upload: - post: - tags: [附件管理] - summary: 上传附件 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 使用 `multipart/form-data` 上传单个文件到 `tbl_attachments`,服务端会自动生成 `attachments_id`, - 并返回可直接访问的 PocketBase 文件流链接。 - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/AttachmentUploadRequest' - responses: - '200': - description: "上传成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/AttachmentRecord' - '400': - description: "参数错误、缺少文件或附件保存失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - /pb/api/attachment/delete: - post: - tags: [附件管理] - summary: 删除附件 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `attachments_id` 真删除附件;若附件已被 `tbl_document.document_image`、`document_video` 或 `document_file` 引用,则拒绝删除。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentDetailRequest' - responses: - '200': - description: "删除成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - attachments_id: - description: "附件业务 ID" - type: string - '400': - description: "参数错误、附件已被文档引用或删除失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到待删除附件" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/document/list: - post: - tags: [文档管理] - summary: 查询文档列表 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 支持按标题、摘要、关键词等字段模糊搜索,并可按 `document_status`、`document_type` 过滤。 - 返回结果会自动根据 `document_image`、`document_video`、`document_file` 中的多个 `attachments_id` 关联 `tbl_attachments`, - 额外补充 `document_image_urls`、`document_video_urls`、`document_file_urls` 以及对应附件对象数组。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentListRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DocumentRecord' - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '415': - description: "请求体必须为 application/json" - /pb/api/document/detail: - post: - tags: [文档管理] - summary: 查询文档详情 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 查询单条文档,并返回与附件表联动解析后的多文件流链接。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentDetailRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: "参数错误" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到对应文档" - '415': - description: "请求体必须为 application/json" - /pb/api/document/create: - post: - tags: [文档管理] - summary: 新增文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - `document_id` 可选;未传时服务端自动生成。 - `document_title`、`document_type` 为必填;其余字段均允许为空。 - `document_image`、`document_video`、`document_file` 支持传入多个已存在于 `tbl_attachments` 的 `attachments_id`。 - 成功后会同步写入一条 `tbl_document_operation_history`,操作类型为 `create`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentMutationRequest' - responses: - '200': - description: "新增成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: "参数错误、附件不存在或文档创建失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/document/update: - post: - tags: [文档管理] - summary: 修改文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 定位现有文档并更新。 - `document_title`、`document_type` 为必填;其余字段均允许为空。 - 若传入 `document_image`、`document_video`、`document_file`,则支持多个 `attachments_id`,并会逐一校验是否存在。 - 成功后会同步写入一条 `tbl_document_operation_history`,操作类型为 `update`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentMutationRequest' - responses: - '200': - description: "修改成功" - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: "参数错误、附件不存在或修改失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到待修改文档" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/document/delete: - post: - tags: [文档管理] - summary: 删除文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 真删除文档,并在删除前同步写入一条 `tbl_document_operation_history`,操作类型为 `delete`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentDeleteRequest' - responses: - '200': - description: "删除成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - document_id: - description: "文档业务 ID" - type: string - '400': - description: "参数错误或删除失败" - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '404': - description: "未找到待删除文档" - '415': - description: "请求体必须为 application/json" - '429': - description: "重复请求过于频繁" - /pb/api/document-history/list: - post: - tags: [文档历史] - summary: 查询文档操作历史 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 若 body 传入 `document_id`,则仅查询该文档的历史;否则返回全部文档操作历史,按创建时间倒序排列。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentHistoryListRequest' - responses: - '200': - description: "查询成功" - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DocumentHistoryRecord' - '401': - description: "token 无效或已过期" - '403': - description: "非 ManagePlatform 用户无权访问" - '415': - description: "请求体必须为 application/json" diff --git a/pocket-base/spec/openapi-manage/cart.yaml b/pocket-base/spec/openapi-manage/cart.yaml index 49a82ab..966410f 100644 --- a/pocket-base/spec/openapi-manage/cart.yaml +++ b/pocket-base/spec/openapi-manage/cart.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Manage Hooks API - Cart + version: 1.0.0 + description: | + hooks 购物车接口文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - cartList: + /pb/api/cart/list: post: tags: [购物车] summary: 查询购物车列表 @@ -31,7 +43,7 @@ paths: description: 请求体必须为 application/json '500': description: 服务端错误 - cartDetail: + /pb/api/cart/detail: post: tags: [购物车] summary: 查询购物车详情 @@ -65,7 +77,7 @@ paths: description: 请求体必须为 application/json '500': description: 服务端错误 - cartCreate: + /pb/api/cart/create: post: tags: [购物车] summary: 新增购物车记录 @@ -102,7 +114,7 @@ paths: description: 重复请求过于频繁 '500': description: 服务端错误 - cartUpdate: + /pb/api/cart/update: post: tags: [购物车] summary: 修改购物车记录 @@ -144,7 +156,7 @@ paths: description: 重复请求过于频繁 '500': description: 服务端错误 - cartDelete: + /pb/api/cart/delete: post: tags: [购物车] summary: 删除购物车记录 @@ -233,6 +245,9 @@ components: product_modelnumber: type: string description: 产品型号 + product_barcode: + type: string + description: 产品料号 product_basic_price: type: [integer, number, 'null'] description: 产品基础价格 @@ -253,6 +268,7 @@ components: is_delete: 删除标记|integer product_name: 产品名称|string product_modelnumber: 产品型号|string + product_barcode: 产品料号|string product_basic_price: 产品基础价格|integer CartListRequest: type: object @@ -360,6 +376,10 @@ components: cart_status: 购物车状态|string cart_at_price: 加入购物车时价格|integer cart_remark: 备注|string + product_name: 产品名称|string + product_modelnumber: 产品型号|string + product_barcode: 产品料号|string + product_basic_price: 产品基础价格|integer CartDeleteResponse: type: object properties: diff --git a/pocket-base/spec/openapi-manage/openapi.yaml b/pocket-base/spec/openapi-manage/openapi.yaml index a55d92e..402f96a 100644 --- a/pocket-base/spec/openapi-manage/openapi.yaml +++ b/pocket-base/spec/openapi-manage/openapi.yaml @@ -6,6 +6,8 @@ info: 面向管理端与自定义 hooks 的接口文档。 本目录仅收敛自定义 hooks API,不包含 PocketBase 原生 records API。 + 本文件为目录索引,支持单文件独立导入,不依赖其他 YAML。 + 文档约定: - 不单独配置鉴权组件;如接口需要登录,请直接在说明中关注 `Authorization: Bearer ` - 示例字段值统一使用 `<字段说明>|<类型>` 风格 @@ -34,70 +36,8 @@ tags: description: hooks 购物车接口 - name: 订单 description: hooks 订单接口 -paths: - /pb/api/system/test-helloworld: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1system~1test-helloworld' - /pb/api/system/health: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1system~1health' - /pb/api/system/users-count: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1system~1users-count' - /pb/api/system/refresh-token: - $ref: '../openapi.yaml#/paths/~1pb~1api~1system~1refresh-token' - /pb/api/wechat/login: - $ref: '../openapi.yaml#/paths/~1pb~1api~1wechat~1login' - /pb/api/wechat/profile: - $ref: '../openapi.yaml#/paths/~1pb~1api~1wechat~1profile' - /pb/api/platform/register: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1platform~1register' - /pb/api/platform/login: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1platform~1login' - /pb/api/dictionary/list: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1dictionary~1list' - /pb/api/dictionary/detail: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1dictionary~1detail' - /pb/api/dictionary/create: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1dictionary~1create' - /pb/api/dictionary/update: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1dictionary~1update' - /pb/api/dictionary/delete: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1dictionary~1delete' - /pb/api/attachment/list: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1attachment~1list' - /pb/api/attachment/detail: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1attachment~1detail' - /pb/api/attachment/upload: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1attachment~1upload' - /pb/api/attachment/delete: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1attachment~1delete' - /pb/api/document/list: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document~1list' - /pb/api/document/detail: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document~1detail' - /pb/api/document/create: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document~1create' - /pb/api/document/update: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document~1update' - /pb/api/document/delete: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document~1delete' - /pb/api/document-history/list: - $ref: '../openapi-manage.yaml#/paths/~1pb~1api~1document-history~1list' - /pb/api/cart/list: - $ref: './cart.yaml#/paths/cartList' - /pb/api/cart/detail: - $ref: './cart.yaml#/paths/cartDetail' - /pb/api/cart/create: - $ref: './cart.yaml#/paths/cartCreate' - /pb/api/cart/update: - $ref: './cart.yaml#/paths/cartUpdate' - /pb/api/cart/delete: - $ref: './cart.yaml#/paths/cartDelete' - /pb/api/order/list: - $ref: './order.yaml#/paths/orderList' - /pb/api/order/detail: - $ref: './order.yaml#/paths/orderDetail' - /pb/api/order/create: - $ref: './order.yaml#/paths/orderCreate' - /pb/api/order/update: - $ref: './order.yaml#/paths/orderUpdate' - /pb/api/order/delete: - $ref: './order.yaml#/paths/orderDelete' \ No newline at end of file +paths: {} +x-index: + files: + - cart.yaml + - order.yaml \ No newline at end of file diff --git a/pocket-base/spec/openapi-manage/order.yaml b/pocket-base/spec/openapi-manage/order.yaml index 6656aca..0b33d98 100644 --- a/pocket-base/spec/openapi-manage/order.yaml +++ b/pocket-base/spec/openapi-manage/order.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Manage Hooks API - Order + version: 1.0.0 + description: | + hooks 订单接口文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - orderList: + /pb/api/order/list: post: tags: [订单] summary: 查询订单列表 @@ -31,7 +43,7 @@ paths: description: 请求体必须为 application/json '500': description: 服务端错误 - orderDetail: + /pb/api/order/detail: post: tags: [订单] summary: 查询订单详情 @@ -65,7 +77,7 @@ paths: description: 请求体必须为 application/json '500': description: 服务端错误 - orderCreate: + /pb/api/order/create: post: tags: [订单] summary: 新增订单记录 @@ -104,7 +116,7 @@ paths: description: 重复请求过于频繁 '500': description: 服务端错误 - orderUpdate: + /pb/api/order/update: post: tags: [订单] summary: 修改订单记录 @@ -148,7 +160,7 @@ paths: description: 重复请求过于频繁 '500': description: 服务端错误 - orderDelete: + /pb/api/order/delete: post: tags: [订单] summary: 删除订单记录 diff --git a/pocket-base/spec/openapi-miniapp-company.yaml b/pocket-base/spec/openapi-miniapp-company.yaml deleted file mode 100644 index cdd584c..0000000 --- a/pocket-base/spec/openapi-miniapp-company.yaml +++ /dev/null @@ -1,571 +0,0 @@ -openapi: 3.1.0 -info: - title: PocketBase MiniApp Company API - version: 1.0.0 - summary: 小程序端通过 PocketBase JS SDK 直连 tbl_company 的基础 CRUD 文档 - description: >- - 本文档面向小程序端直接使用 PocketBase JS SDK / REST API 访问 `tbl_company`。 - 本文档统一以 PocketBase 原生记录主键 `id` 作为唯一识别键。 - `company_id` 保留为普通业务字段,可用于展示、筛选和业务关联,但不再作为 CRUD 的唯一键。 - 当前线上 `tbl_company` 还包含 `company_owner_openid` 字段,用于保存公司所有者 openid,并带普通索引。 - 同时新增了国家、省、市、区的名称与编码字段,便于前端直接按行政区划存取。 - license: - name: Proprietary - identifier: LicenseRef-Proprietary -servers: - - url: https://bai-api.blv-oa.com/pb - description: 线上 PocketBase 服务 -tags: - - name: Company - description: tbl_company 公司信息基础 CRUD -paths: - /api/collections/tbl_company/records: - get: - tags: [Company] - operationId: listCompanyRecords - summary: 查询公司列表 - description: >- - 使用 PocketBase 原生 records list/search 接口查询 `tbl_company`。 - 支持三种常见模式: - 1. 全表查询:不传 `filter`; - 2. 精确查询:`filter=id="q1w2e3r4t5y6u7i"`; - 3. 模糊查询:`filter=(company_name~"华住" || company_usci~"9131" || company_entity~"张三")`; - 4. 按 `company_id` 查询单条:`filter=company_id="WX-COMPANY-10001"&perPage=1&page=1`。 - parameters: - - $ref: '#/components/parameters/Page' - - $ref: '#/components/parameters/PerPage' - - $ref: '#/components/parameters/Sort' - - $ref: '#/components/parameters/Filter' - - $ref: '#/components/parameters/Fields' - - $ref: '#/components/parameters/SkipTotal' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyListResponse' - examples: - all: - summary: 全表查询 - value: - page: 1 - perPage: 30 - totalItems: 2 - totalPages: 1 - items: - - id: q1w2e3r4t5y6u7i - collectionId: pbc_company_demo - collectionName: tbl_company - created: '2026-03-27 10:00:00.000Z' - updated: '2026-03-27 10:00:00.000Z' - company_id: C10001 - company_name: 宝镜科技 - company_type: 渠道商 - company_entity: 张三 - company_usci: '91310000123456789A' - company_nationality: 中国 - company_nationality_code: CN - company_province: 上海 - company_province_code: '310000' - company_city: 上海 - company_city_code: '310100' - company_district: 浦东新区 - company_district_code: '310115' - company_postalcode: '200000' - company_add: 上海市浦东新区XX路1号 - company_status: 有效 - company_level: A - company_owner_openid: wx-openid-owner-001 - company_remark: '' - exact: - summary: 按 id 精确查询 - value: - page: 1 - perPage: 1 - totalItems: 1 - totalPages: 1 - items: - - id: q1w2e3r4t5y6u7i - collectionId: pbc_company_demo - collectionName: tbl_company - created: '2026-03-27 10:00:00.000Z' - updated: '2026-03-27 10:00:00.000Z' - company_id: C10001 - company_name: 宝镜科技 - company_type: 渠道商 - company_entity: 张三 - company_usci: '91310000123456789A' - company_nationality: 中国 - company_nationality_code: CN - company_province: 上海 - company_province_code: '310000' - company_city: 上海 - company_city_code: '310100' - company_district: 浦东新区 - company_district_code: '310115' - company_postalcode: '200000' - company_add: 上海市浦东新区XX路1号 - company_status: 有效 - company_level: A - company_owner_openid: wx-openid-owner-001 - company_remark: '' - '400': - description: 过滤表达式或查询参数不合法 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '403': - description: 当前调用方没有 list 权限 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - post: - tags: [Company] - operationId: createCompanyRecord - summary: 新增公司 - description: >- - 创建一条 `tbl_company` 记录。当前文档以 `id` 作为记录唯一识别键, - 新建成功后由 PocketBase 自动生成 `id`;`company_id` 也由数据库自动生成, - 客户端创建时不需要传入,但仍可作为后续业务查询字段。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyCreateRequest' - examples: - default: - value: - company_name: 宝镜科技 - company_type: 渠道商 - company_entity: 张三 - company_usci: '91310000123456789A' - company_nationality: 中国 - company_nationality_code: CN - company_province: 上海 - company_province_code: '310000' - company_city: 上海 - company_city_code: '310100' - company_district: 浦东新区 - company_district_code: '310115' - company_postalcode: '200000' - company_add: 上海市浦东新区XX路1号 - company_status: 有效 - company_level: A - company_owner_openid: wx-openid-owner-001 - company_remark: 首次创建 - responses: - '200': - description: 创建成功 - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyRecord' - '400': - description: 校验失败,例如字段类型不合法或违反当前集合约束 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '403': - description: 当前调用方没有 create 权限 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '404': - description: 集合不存在 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - /api/collections/tbl_company/records/{recordId}: - get: - tags: [Company] - operationId: getCompanyRecordByRecordId - summary: 按 PocketBase 记录 id 查询公司 - description: >- - 这是 PocketBase 原生单条查询接口,路径参数必须传记录主键 `id`。 - parameters: - - $ref: '#/components/parameters/RecordId' - - $ref: '#/components/parameters/Fields' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyRecord' - '403': - description: 当前调用方没有 view 权限 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '404': - description: 记录不存在 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - patch: - tags: [Company] - operationId: updateCompanyRecordByRecordId - summary: 按 PocketBase 记录 id 更新公司 - description: >- - 这是 PocketBase 原生更新接口,路径参数统一使用记录主键 `id`。 - 如果业务侧只有 `company_id`,标准流程是先调用 list 接口 - `filter=company_id="..."&perPage=1&page=1` 查出对应记录,再用返回的 `id` 调用本接口。 - parameters: - - $ref: '#/components/parameters/RecordId' - - $ref: '#/components/parameters/Fields' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyUpdateRequest' - examples: - default: - value: - company_name: 宝镜科技(更新) - company_status: 有效 - company_level: S - company_owner_openid: wx-openid-owner-002 - company_remark: 已更新基础资料 - responses: - '200': - description: 更新成功 - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyRecord' - '400': - description: 更新参数不合法 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '403': - description: 当前调用方没有 update 权限 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '404': - description: 记录不存在 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - delete: - tags: [Company] - operationId: deleteCompanyRecordByRecordId - summary: 按 PocketBase 记录 id 删除公司 - description: >- - 这是 PocketBase 原生删除接口,路径参数统一使用记录主键 `id`。 - parameters: - - $ref: '#/components/parameters/RecordId' - responses: - '204': - description: 删除成功 - '400': - description: 删除失败,例如仍被必填 relation 引用 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '403': - description: 当前调用方没有 delete 权限 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' - '404': - description: 记录不存在 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseError' -components: - parameters: - Page: - name: page - in: query - description: 页码,默认 1 - schema: - type: integer - minimum: 1 - default: 1 - PerPage: - name: perPage - in: query - description: 每页返回条数,默认 30 - schema: - type: integer - minimum: 1 - default: 30 - Sort: - name: sort - in: query - description: 排序字段,例如 `-created,+company_name` - schema: - type: string - Filter: - name: filter - in: query - description: >- - PocketBase 过滤表达式。 - 精确查询示例:`id="q1w2e3r4t5y6u7i"`; - 模糊查询示例:`(company_name~"宝镜" || company_usci~"9131" || company_entity~"张三")` - schema: - type: string - Fields: - name: fields - in: query - description: 逗号分隔的返回字段列表,例如 `id,company_id,company_name` - schema: - type: string - SkipTotal: - name: skipTotal - in: query - description: 是否跳过 totalItems/totalPages 统计 - schema: - type: boolean - default: false - RecordId: - name: recordId - in: path - required: true - description: PocketBase 记录主键 id - schema: - type: string - schemas: - CompanyBase: - type: object - properties: - company_id: - type: string - description: 公司业务编号字段,不再作为 CRUD 唯一键 - company_name: - type: string - description: 公司名称 - company_type: - type: string - description: 公司类型 - company_entity: - type: string - description: 公司法人 - company_usci: - type: string - description: 统一社会信用代码 - company_nationality: - type: string - description: 国家 - company_nationality_code: - type: string - description: 国家编码 - company_province: - type: string - description: 省份 - company_province_code: - type: string - description: 省份编码 - company_city: - type: string - description: 城市 - company_city_code: - type: string - description: 城市编码 - company_district: - type: string - description: 区/县 - company_district_code: - type: string - description: 区/县编码 - company_postalcode: - type: string - description: 邮编 - company_add: - type: string - description: 地址 - company_status: - type: string - description: 公司状态 - company_level: - type: string - description: 公司等级 - company_owner_openid: - type: string - description: 公司所有者 openid - company_remark: - type: string - description: 备注 - CompanyCreateRequest: - type: object - description: 创建时不需要传 `company_id`,由数据库自动生成。 - properties: - company_name: - description: "公司名称" - type: string - company_type: - description: "公司类型" - type: string - company_entity: - description: "公司法人" - type: string - company_usci: - description: "统一社会信用代码" - type: string - company_nationality: - description: "国家名称" - type: string - company_nationality_code: - description: "国家编码" - type: string - company_province: - description: "省份名称" - type: string - company_province_code: - description: "省份编码" - type: string - company_city: - description: "城市名称" - type: string - company_city_code: - description: "城市编码" - type: string - company_district: - description: "区 / 县名称" - type: string - company_district_code: - description: "区 / 县编码" - type: string - company_postalcode: - description: "邮编" - type: string - company_add: - description: "地址" - type: string - company_status: - description: "公司状态" - type: string - company_level: - description: "公司等级" - type: string - company_owner_openid: - description: "公司所有者 openid" - type: string - company_remark: - description: "备注" - type: string - additionalProperties: false - CompanyUpdateRequest: - type: object - description: >- - 更新时可只传需要修改的字段;记录定位统一依赖路径参数 `id`。 - properties: - company_id: - description: "所属公司业务 ID" - type: string - company_name: - description: "公司名称" - type: string - company_type: - description: "公司类型" - type: string - company_entity: - description: "公司法人" - type: string - company_usci: - description: "统一社会信用代码" - type: string - company_nationality: - description: "国家名称" - type: string - company_nationality_code: - description: "国家编码" - type: string - company_province: - description: "省份名称" - type: string - company_province_code: - description: "省份编码" - type: string - company_city: - description: "城市名称" - type: string - company_city_code: - description: "城市编码" - type: string - company_district: - description: "区 / 县名称" - type: string - company_district_code: - description: "区 / 县编码" - type: string - company_postalcode: - description: "邮编" - type: string - company_add: - description: "地址" - type: string - company_status: - description: "公司状态" - type: string - company_level: - description: "公司等级" - type: string - company_owner_openid: - description: "公司所有者 openid" - type: string - company_remark: - description: "备注" - type: string - CompanyRecord: - allOf: - - type: object - properties: - id: - type: string - description: PocketBase 记录主键 id - collectionId: - type: string - collectionName: - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - - $ref: '#/components/schemas/CompanyBase' - CompanyListResponse: - type: object - properties: - page: - type: integer - perPage: - type: integer - totalItems: - type: integer - totalPages: - type: integer - items: - type: array - items: - $ref: '#/components/schemas/CompanyRecord' - PocketBaseError: - type: object - properties: - status: - type: integer - message: - type: string - data: - description: "业务响应数据" - type: object - additionalProperties: true diff --git a/pocket-base/spec/openapi-wx.yaml b/pocket-base/spec/openapi-wx.yaml deleted file mode 100644 index bad5134..0000000 --- a/pocket-base/spec/openapi-wx.yaml +++ /dev/null @@ -1,44 +0,0 @@ -openapi: 3.1.0 -info: - title: BAI PocketBase Native API - version: 1.0.0-wx - description: | - 顶层兼容入口。 - 当前原生 API 文档已整理到 `spec/openapi-wx/` 目录下;本文件保留为兼容总入口。 -servers: - - url: https://bai-api.blv-oa.com - description: 生产环境 - - url: http://127.0.0.1:8090 - description: PocketBase 本地环境 -tags: - - name: 企业信息 - description: PocketBase 原生公司记录接口 - - name: 附件信息 - description: PocketBase 原生附件记录接口 - - name: 产品信息 - description: PocketBase 原生产品记录接口 - - name: 文档信息 - description: PocketBase 原生文档记录接口 - - name: 购物车 - description: PocketBase 原生购物车记录接口 - - name: 订单 - description: PocketBase 原生订单记录接口 -paths: - /pb/api/collections/tbl_company/records: - $ref: './openapi-wx/company.yaml#/paths/companyRecords' - /pb/api/collections/tbl_company/records/{recordId}: - $ref: './openapi-wx/company.yaml#/paths/companyRecordById' - /pb/api/collections/tbl_attachments/records: - $ref: './openapi-wx/attachments.yaml#/paths/attachmentRecords' - /pb/api/collections/tbl_product_list/records: - $ref: './openapi-wx/products.yaml#/paths/productRecords' - /pb/api/collections/tbl_document/records: - $ref: './openapi-wx/documents.yaml#/paths/documentRecords' - /pb/api/collections/tbl_cart/records: - $ref: './openapi-wx/cart.yaml#/paths/cartRecords' - /pb/api/collections/tbl_cart/records/{recordId}: - $ref: './openapi-wx/cart.yaml#/paths/cartRecordById' - /pb/api/collections/tbl_order/records: - $ref: './openapi-wx/order.yaml#/paths/orderRecords' - /pb/api/collections/tbl_order/records/{recordId}: - $ref: './openapi-wx/order.yaml#/paths/orderRecordById' diff --git a/pocket-base/spec/openapi-wx/attachments.yaml b/pocket-base/spec/openapi-wx/attachments.yaml index 588aa0c..d287e55 100644 --- a/pocket-base/spec/openapi-wx/attachments.yaml +++ b/pocket-base/spec/openapi-wx/attachments.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Attachments + version: 1.0.0 + description: | + PocketBase 原生 `tbl_attachments` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - attachmentRecords: + /pb/api/collections/tbl_attachments/records: get: operationId: getPocketBaseAttachmentRecords tags: @@ -38,7 +50,7 @@ paths: - 不传该参数时,返回分页列表 schema: type: string - example: attachments_id="ATT-1774599142438-8n1UcU" + example: 过滤表达式|string - name: page in: query required: false @@ -60,8 +72,6 @@ paths: description: 查询成功 content: application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseAttachmentListResponse example: page: page|integer perPage: perPage|integer @@ -85,8 +95,6 @@ paths: description: 查询参数错误 content: application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -97,7 +105,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -108,7 +116,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -240,8 +248,6 @@ components: example: 总页数 | integer items: type: array - items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseAttachmentRecord example: page: page|integer perPage: perPage|integer diff --git a/pocket-base/spec/openapi-wx/cart.yaml b/pocket-base/spec/openapi-wx/cart.yaml index dddcf75..a32587d 100644 --- a/pocket-base/spec/openapi-wx/cart.yaml +++ b/pocket-base/spec/openapi-wx/cart.yaml @@ -1,11 +1,30 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Cart + version: 1.0.0 + description: | + PocketBase 原生 `tbl_cart` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 +tags: + - name: 购物车 + description: PocketBase 原生购物车记录接口 paths: - cartRecords: + /pb/api/collections/tbl_cart/records: get: + operationId: getPocketBaseCartRecords tags: [购物车] summary: 查询购物车记录列表 description: | 使用 PocketBase 原生 records list 接口查询 `tbl_cart`。 - 如需鉴权,请自行在请求头中携带 `Authorization: Bearer `。 + + 说明: + - `cart_product_id` 是 relation 字段,默认仅返回关联记录 id。 + - 如需同时返回 `tbl_product_list` 详情,请传 `expand=cart_product_id`。 parameters: - name: filter in: query @@ -13,7 +32,7 @@ paths: schema: type: string description: PocketBase 原生过滤表达式 - example: cart_id="购物车业务ID|string" + example: 过滤表达式|string - name: page in: query required: false @@ -33,7 +52,14 @@ paths: required: false schema: type: string - example: -cart_create + example: 排序表达式|string + - name: expand + in: query + required: false + schema: + type: string + description: 关系字段展开;传 `cart_product_id` 时返回 `expand.cart_product_id` + example: 关联展开字段|string responses: '200': description: 查询成功 @@ -43,18 +69,34 @@ paths: $ref: '#/components/schemas/PocketBaseCartListResponse' '400': description: 查询参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '403': description: 无权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' post: + operationId: postPocketBaseCartRecord tags: [购物车] summary: 创建购物车记录 description: | 使用 PocketBase 原生 records create 接口向 `tbl_cart` 新增记录。 - 如集合规则要求 `cart_owner` 与当前用户一致,请客户端显式提交。 requestBody: required: true content: @@ -65,7 +107,7 @@ paths: cart_id: 购物车业务ID|string cart_number: 购物车名称或分组号|string cart_owner: 购物车所有者openid|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string + cart_product_id: 产品业务ID|string cart_product_quantity: 产品数量|integer cart_status: 购物车状态|string cart_at_price: 加入购物车时价格|number @@ -79,19 +121,33 @@ paths: $ref: '#/components/schemas/PocketBaseCartRecord' '400': description: 参数错误或违反集合规则 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '403': description: 无权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 - cartRecordById: + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' + /pb/api/collections/tbl_cart/records/{recordId}: patch: + operationId: patchPocketBaseCartRecordByRecordId tags: [购物车] summary: 更新购物车记录 - description: | - 使用 PocketBase 原生 records update 接口更新 `tbl_cart`。 - 路径参数使用 PocketBase 原生 `recordId`。 parameters: - name: recordId in: path @@ -108,7 +164,7 @@ paths: example: cart_number: 购物车名称或分组号|string cart_owner: 购物车所有者openid|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string + cart_product_id: 产品业务ID|string cart_product_quantity: 产品数量|integer cart_status: 购物车状态|string cart_at_price: 加入购物车时价格|number @@ -122,18 +178,32 @@ paths: $ref: '#/components/schemas/PocketBaseCartRecord' '400': description: 参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '404': description: 记录不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' delete: + operationId: deletePocketBaseCartRecordByRecordId tags: [购物车] summary: 删除购物车记录 - description: | - 使用 PocketBase 原生 records delete 接口删除 `tbl_cart`。 - 路径参数使用 PocketBase 原生 `recordId`。 parameters: - name: recordId in: path @@ -146,878 +216,65 @@ paths: description: 删除成功 '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '404': description: 记录不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 - "400": - description: 参数错误 content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 无权访问该购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 未找到对应购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - cartCreate: - post: - operationId: postCartCreate - tags: - - 购物车 - summary: 新增购物车记录 - description: | - 调用自定义 hooks API 新增一条购物车记录。 - - 创建规则: - - 服务端自动根据当前 token 写入 `cart_owner` - - 服务端自动生成 `cart_id` - - 若未传 `cart_number`,服务端会自动生成展示编号 - - `cart_product_id` 为必填;当前 hooks 与库结构保持一致,必须传 `tbl_product_list` 的 `recordId` - - `cart_product_quantity`、`cart_at_price` 为必填 - - 目标软删除契约: - - 新建记录应默认为 `is_delete = 0` - - 当前仓库导出响应中尚未显式返回 `is_delete` 字段 - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartCreateRequest - example: - cart_number: 可选;未传时服务端自动生成|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_quantity: 产品数量,需为正整数|integer - cart_status: 可选;未传时默认 有效|string - cart_at_price: 加入购物车时价格|integer - cart_remark: 备注|string - responses: - "200": - description: 创建成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartRecord - example: - pb_id: PocketBase 记录主键 id|string - created: PocketBase 系统创建时间|string - updated: PocketBase 系统更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 关联产品的 PocketBase recordId|string - cart_product_business_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|integer - cart_remark: 备注|string - is_delete: 软删除标记;目标契约字段,当前 hooks 响应可能尚未显式透出|integer - product_name: 产品名称(服务端联动补充)|string - product_modelnumber: 产品型号(服务端联动补充)|string - product_basic_price: 产品基础价格(服务端联动补充)|integer - "400": - description: 参数错误、产品不存在或创建失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - cartUpdate: - post: - operationId: postCartUpdate - tags: - - 购物车 - summary: 修改购物车记录 - description: | - 调用自定义 hooks API 按 `cart_id` 更新购物车记录。 - - 更新规则: - - 仅允许修改当前 `Authorization` 对应用户自己的购物车记录 - - `cart_id` 为必填,用于精确定位目标记录 - - 其余字段均为可选增量更新 - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartUpdateRequest - example: - cart_id: 购物车业务 ID|string - cart_number: cart_number|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_quantity: cart_product_quantity|integer - cart_status: cart_status|string - cart_at_price: cart_at_price|integer - cart_remark: cart_remark|string - responses: - "200": - description: 更新成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartRecord - example: - pb_id: PocketBase 记录主键 id|string - created: PocketBase 系统创建时间|string - updated: PocketBase 系统更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 关联产品的 PocketBase recordId|string - cart_product_business_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|integer - cart_remark: 备注|string - is_delete: 软删除标记;目标契约字段,当前 hooks 响应可能尚未显式透出|integer - product_name: 产品名称(服务端联动补充)|string - product_modelnumber: 产品型号(服务端联动补充)|string - product_basic_price: 产品基础价格(服务端联动补充)|integer - "400": - description: 参数错误、产品不存在或更新失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 无权访问该购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 未找到待修改的购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - cartDelete: - post: - operationId: postCartDelete - tags: - - 购物车 - summary: 软删除购物车记录 - description: | - 目标契约:按 `cart_id` 软删除购物车记录,将 `is_delete` 标记为 `1`,而不是物理删除。 - - 当前仓库实现差异: - - 当前 `cartOrderService.deleteCart()` 仍直接调用 `$app.delete(record)` 做物理删除 - - 因此当前后端实现与本软删除契约不一致 - - 若要严格按本文档执行,需先同步调整后端服务实现,并在列表/详情接口中补充 `is_delete = 0` 过滤 - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartDeleteRequest - example: - cart_id: 购物车业务 ID|string - responses: - "200": - description: 删除成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/CartDeleteResponse - example: - cart_id: 购物车业务 ID|string - is_delete: 目标软删除标记值;当前实现可能仍返回物理删除结果|integer - "400": - description: 参数错误或删除失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 无权访问该购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 未找到待删除的购物车记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - cartRecords: - get: - operationId: getPocketBaseCartRecords - tags: - - 购物车 - summary: 查询当前用户购物车列表或按业务 ID 精确查询 - description: | - 使用 PocketBase 原生 records list 接口查询 `tbl_cart`。 - - 当前线上权限规则: - - `listRule = @request.auth.id != "" && cart_owner = @request.auth.openid && is_delete = 0` - - 因此调用方只能读到 `cart_owner` 等于自己 `openid` 且未软删除的记录 - - 标准调用方式: - 1. 查询当前登录用户全部购物车: - - 不传 `filter` - - 可选传 `sort=-cart_create` - 2. 按业务 ID 精确查单条: - - `filter=cart_id="CART-..."` - - `perPage=1` - - `page=1` - - 注意: - - 这是 PocketBase 原生返回结构,不是 hooks 统一包装 - - 即使不传 `filter`,返回结果也会继续受 `listRule` 限制 - security: - - BearerAuth: [] - parameters: - - name: filter - in: query - required: false - description: | - PocketBase 标准过滤表达式。 - - - 查当前用户全部购物车时:不传 - - 按 `cart_id` 精确查单条时:`cart_id="CART-1770000000000-abc123"` - schema: - type: string - example: cart_id="CART-1770000000000-abc123" - - name: page - in: query - required: false - schema: - type: integer - minimum: 1 - default: 1 - - name: perPage - in: query - required: false - schema: - type: integer - minimum: 1 - default: 20 - - name: sort - in: query - required: false - description: PocketBase 原生排序表达式,推荐 `-cart_create` - schema: - type: string - example: -cart_create - responses: - "200": - description: 查询成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartListResponse - example: - page: page|integer - perPage: perPage|integer - totalItems: totalItems|integer - totalPages: totalPages|integer - items: - - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|number - cart_remark: 备注|string - "400": - description: 查询参数错误或不满足 listRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 集合规则被锁定或服务端权限设置异常 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - post: - operationId: postPocketBaseCartRecord - tags: - - 购物车 - summary: 创建购物车记录 - description: | - 使用 PocketBase 原生 records create 接口向 `tbl_cart` 新增记录。 - - 当前线上权限规则: - - `createRule = @request.body.cart_owner != ""` - - 因此客户端创建时必须显式提交非空 `cart_owner` - - `cart_product_id` 当前为 relation 字段,必须传 `tbl_product_list` 的 PocketBase `recordId` - - 这意味着: - - 不能依赖服务端自动补 owner - - 不能省略 `cart_owner` - - 不满足规则时 PocketBase 会直接返回 `400` - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartCreateRequest - example: - cart_id: cart_id|string - cart_number: cart_number|string - cart_owner: 必须显式提交非空 owner|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_quantity: cart_product_quantity|integer,可为空 - cart_status: cart_status|string,可为空 - cart_at_price: cart_at_price|number,可为空 - cart_remark: cart_remark|string - responses: - "200": - description: 创建成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartRecord - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 关联产品的 PocketBase recordId|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|number - cart_remark: 备注|string - "400": - description: 参数错误、违反字段约束或不满足 createRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 集合规则被锁定或服务端权限设置异常 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - cartRecordById: - patch: - operationId: patchPocketBaseCartRecordByRecordId - tags: - - 购物车 - summary: 更新购物车记录 - description: | - 使用 PocketBase 原生 records update 接口更新 `tbl_cart`。 - - 标准调用流程: - 1. 先通过 `GET /pb/api/collections/tbl_cart/records?filter=cart_id="..."&perPage=1&page=1` 找到原生 `recordId` - 2. 再调用当前 `PATCH /pb/api/collections/tbl_cart/records/{recordId}` - - 当前线上权限规则: - - `updateRule = @request.auth.id != "" && cart_owner = @request.auth.openid` - - 调用方只能修改自己的购物车记录 - security: - - BearerAuth: [] - parameters: - - name: recordId - in: path - required: true - schema: - type: string - example: l2r3nq7rqhuob0h - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartUpdateRequest - example: - cart_number: cart_number|string - cart_owner: 若提交,必须仍等于当前 token 对应 openid|string - cart_product_id: cart_product_id|string - cart_product_quantity: cart_product_quantity|integer - cart_status: cart_status|string - cart_at_price: cart_at_price|number - cart_remark: cart_remark|string - responses: - "200": - description: 更新成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartRecord - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|number - cart_remark: 备注|string - "400": - description: 参数错误或违反字段约束 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 记录不存在或不满足 updateRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - delete: - operationId: deletePocketBaseCartRecordByRecordId - tags: - - 购物车 - summary: 删除购物车记录 - description: | - 使用 PocketBase 原生 records delete 接口删除 `tbl_cart`。 - - 当前线上权限规则: - - `deleteRule = @request.auth.id != "" && cart_owner = @request.auth.openid` - - 调用方只能删除自己的购物车记录 - security: - - BearerAuth: [] - parameters: - - name: recordId - in: path - required: true - schema: - type: string - example: l2r3nq7rqhuob0h - responses: - "204": - description: 删除成功 - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 记录不存在或不满足 deleteRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string + $ref: '#/components/schemas/PocketBaseNativeError' components: schemas: PocketBaseNativeError: type: object properties: code: - type: - - integer - - string + type: [integer, string] description: PocketBase错误码 - example: 错误状态码 | integer message: type: string description: PocketBase错误信息 - example: PocketBase原生错误信息 | string data: - description: PocketBase错误数据 type: object additionalProperties: true + description: PocketBase错误数据 example: - code: 业务状态码|integer - message: message|string + code: 错误状态码|integer + message: PocketBase原生错误信息|string data: - 业务响应数据字段|string: 业务响应数据值|string + 字段名|string: 字段值|string PocketBaseRecordBase: type: object - required: - - id - - collectionId - - collectionName - - created - - updated + required: [id, collectionId, collectionName, created, updated] properties: id: type: string - description: PocketBase 记录主键 - example: PocketBase记录主键 | string + description: PocketBase记录主键 collectionId: type: string - example: 集合ID | string + description: 集合ID collectionName: type: string - example: 集合名称 | string + description: 集合名称 created: type: string description: 记录创建时间 - example: 记录创建时间 | string updated: type: string description: 记录更新时间 - example: 记录更新时间 | string example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string + id: PocketBase记录主键|string + collectionId: 集合ID|string + collectionName: 集合名称|string created: 记录创建时间|string updated: 记录更新时间|string PocketBaseCartFields: @@ -1025,190 +282,154 @@ components: properties: cart_id: type: string - description: 购物车业务 ID - example: CART-1770000000000-abc123 + description: 购物车业务ID cart_number: type: string description: 购物车名称或分组号 - example: wx-user-20260403153000 cart_create: type: string - description: 购物车项创建时间,由数据库自动生成 - example: 2026-04-03 15:30:00.000Z + description: 购物车项创建时间 cart_owner: type: string - description: 购物车所有者 openid - example: wx-openid-user-001 + description: 购物车所有者openid cart_product_id: type: string - description: 关联产品的 PocketBase recordId - example: pbc_product_record_id|string - cart_product_business_id: - type: string - description: 关联产品的业务 ID(prod_list_id),用于展示 - example: PROD-1770000000000-abcd12 + description: 产品业务ID cart_product_quantity: - type: - - integer - - number + type: [integer, number] description: 产品数量 - example: 2 cart_status: type: string description: 购物车状态 - example: 有效 cart_at_price: - type: - - number - - integer + type: [number, integer] description: 加入购物车时价格 - example: 1999 cart_remark: type: string description: 备注 - example: 小程序加入购物车示例 example: - cart_id: 购物车业务 ID|string + cart_id: 购物车业务ID|string cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_business_id: 产品业务 ID|string + cart_create: 购物车项创建时间|string + cart_owner: 购物车所有者openid|string + cart_product_id: 产品业务ID|string cart_product_quantity: 产品数量|integer cart_status: 购物车状态|string cart_at_price: 加入购物车时价格|number cart_remark: 备注|string PocketBaseCartRecord: allOf: - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseRecordBase - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartFields - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|number - cart_remark: 备注|string + - $ref: '#/components/schemas/PocketBaseRecordBase' + - $ref: '#/components/schemas/PocketBaseCartFields' + - type: object + properties: + expand: + type: object + description: 关系字段展开结果(需请求参数 `expand=cart_product_id`) + properties: + cart_product_id: + $ref: '#/components/schemas/PocketBaseProductListExpand' PocketBaseCartCreateRequest: type: object - required: - - cart_owner - - cart_product_id + required: [cart_owner] properties: cart_id: type: string + example: 购物车业务ID|string cart_number: type: string + example: 购物车名称或分组号|string cart_owner: type: string - description: 必须显式提交非空 owner + example: 购物车所有者openid|string cart_product_id: type: string - description: tbl_product_list 的 PocketBase recordId + example: 产品业务ID|string cart_product_quantity: - type: - - integer - - number + type: [integer, number] + example: 产品数量|integer cart_status: type: string + example: 购物车状态|string cart_at_price: - type: - - number - - integer + type: [number, integer] + example: 加入购物车时价格|number cart_remark: type: string - example: - cart_owner: 必须显式提交非空 owner|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_quantity: cart_product_quantity|integer,可为空 - cart_status: cart_status|string,可为空 - cart_at_price: cart_at_price|number,可为空 - cart_remark: cart_remark|string + example: 备注|string PocketBaseCartUpdateRequest: type: object properties: cart_number: type: string + example: 购物车名称或分组号|string cart_owner: type: string - description: 若提交,必须仍为非空 owner + example: 购物车所有者openid|string cart_product_id: type: string - description: tbl_product_list 的 PocketBase recordId + example: 产品业务ID|string cart_product_quantity: - type: - - integer - - number + type: [integer, number] + example: 产品数量|integer cart_status: type: string + example: 购物车状态|string cart_at_price: - type: - - number - - integer + type: [number, integer] + example: 加入购物车时价格|number cart_remark: type: string - example: - cart_number: cart_number|string - cart_owner: 若提交,必须仍为非空 owner|string - cart_product_id: tbl_product_list 的 PocketBase recordId|string - cart_product_quantity: cart_product_quantity|integer - cart_status: cart_status|string - cart_at_price: cart_at_price|number - cart_remark: cart_remark|string + example: 备注|string PocketBaseCartListResponse: type: object - required: - - page - - perPage - - totalItems - - totalPages - - items + required: [page, perPage, totalItems, totalPages, items] properties: page: - type: - - integer - - string + type: [integer, string] perPage: - type: - - integer - - string + type: [integer, string] totalItems: - type: - - integer - - string + type: [integer, string] totalPages: - type: - - integer - - string + type: [integer, string] items: type: array items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCartRecord - example: - page: page|integer - perPage: perPage|integer - totalItems: totalItems|integer - totalPages: totalPages|integer - items: - - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - cart_id: 购物车业务 ID|string - cart_number: 购物车名称或分组号|string - cart_create: 购物车项创建时间,由数据库自动生成|string - cart_owner: 购物车所有者 openid|string - cart_product_id: 产品业务 ID|string - cart_product_quantity: 产品数量|integer - cart_status: 购物车状态|string - cart_at_price: 加入购物车时价格|number - cart_remark: 备注|string + $ref: '#/components/schemas/PocketBaseCartRecord' + PocketBaseProductListExpand: + type: object + description: tbl_product_list 关联展开后的记录对象(示例字段) + properties: + id: + type: string + description: PocketBase记录主键 + example: PocketBase记录主键|string + collectionId: + type: string + description: 集合ID + example: 集合ID|string + collectionName: + type: string + description: 集合名称 + example: 集合名称|string + prod_list_id: + type: string + description: 产品业务ID + example: 产品业务ID|string + prod_list_name: + type: string + description: 产品名称 + example: 产品名称|string + prod_list_modelnumber: + type: string + description: 产品型号 + example: 产品型号|string + prod_list_basic_price: + type: [number, integer] + description: 基础价格 + example: 基础价格|number + prod_list_status: + type: string + description: 产品状态 + example: 产品状态|string diff --git a/pocket-base/spec/openapi-wx/company.yaml b/pocket-base/spec/openapi-wx/company.yaml index e34c0cc..21b9383 100644 --- a/pocket-base/spec/openapi-wx/company.yaml +++ b/pocket-base/spec/openapi-wx/company.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Company + version: 1.0.0 + description: | + PocketBase 原生 `tbl_company` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - companyRecords: + /pb/api/collections/tbl_company/records: post: operationId: postPocketBaseCompanyRecord tags: @@ -21,7 +33,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyCreateRequest + $ref: #/components/schemas/PocketBaseCompanyCreateRequest example: company_name: 公司名称|string company_type: 公司类型|string @@ -47,7 +59,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyRecord + $ref: #/components/schemas/PocketBaseCompanyRecord example: id: PocketBase 记录主键|string collectionId: collectionId|string @@ -78,7 +90,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -89,7 +101,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -100,7 +112,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -142,7 +154,7 @@ paths: - 查询整个列表时:不传该参数 schema: type: string - example: company_id="WX-COMPANY-10001" + example: 过滤表达式|string - name: page in: query required: false @@ -165,7 +177,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyListResponse + $ref: #/components/schemas/PocketBaseCompanyListResponse example: page: page|integer perPage: perPage|integer @@ -201,7 +213,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -212,7 +224,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -223,13 +235,13 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string data: 业务响应数据字段|string: 业务响应数据值|string - companyRecordById: + /pb/api/collections/tbl_company/records/{recordId}: patch: operationId: patchPocketBaseCompanyRecordByRecordId tags: @@ -253,13 +265,13 @@ paths: description: 通过 `company_id` 查询结果拿到的 PocketBase 记录主键 `id` schema: type: string - example: l2r3nq7rqhuob0h + example: PocketBase记录主键|string requestBody: required: true content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyUpdateRequest + $ref: #/components/schemas/PocketBaseCompanyUpdateRequest example: company_id: 所属公司业务 ID|string company_name: 公司名称|string @@ -286,7 +298,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyRecord + $ref: #/components/schemas/PocketBaseCompanyRecord example: id: PocketBase 记录主键|string collectionId: collectionId|string @@ -317,7 +329,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -328,7 +340,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -339,7 +351,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -350,7 +362,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -653,8 +665,8 @@ components: company_remark: 备注|string PocketBaseCompanyRecord: allOf: - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseRecordBase - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyFields + - $ref: #/components/schemas/PocketBaseRecordBase + - $ref: #/components/schemas/PocketBaseCompanyFields example: id: PocketBase 记录主键|string collectionId: collectionId|string @@ -870,7 +882,7 @@ components: items: type: array items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseCompanyRecord + $ref: #/components/schemas/PocketBaseCompanyRecord example: page: page|integer perPage: perPage|integer diff --git a/pocket-base/spec/openapi-wx/documents.yaml b/pocket-base/spec/openapi-wx/documents.yaml index 14632fb..7e5b60d 100644 --- a/pocket-base/spec/openapi-wx/documents.yaml +++ b/pocket-base/spec/openapi-wx/documents.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Documents + version: 1.0.0 + description: | + PocketBase 原生 `tbl_document` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - documentRecords: + /pb/api/collections/tbl_document/records: get: operationId: getPocketBaseDocumentRecords tags: @@ -57,7 +69,7 @@ paths: - 例如:`document_type ~ "DICT-1774599144591-hAEFQj" && document_type ~ "@UT1"` schema: type: string - example: document_type ~ "DICT-1774599144591-hAEFQj" && document_type ~ "@UT1" + example: 过滤表达式|string - name: page in: query required: false @@ -84,14 +96,14 @@ paths: - `-document_create`:按最新上传倒序返回 schema: type: string - example: -document_create + example: 排序表达式|string responses: "200": description: 查询成功 content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseDocumentListResponse + $ref: #/components/schemas/PocketBaseDocumentListResponse example: page: page|integer perPage: perPage|integer @@ -135,7 +147,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -146,7 +158,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -157,7 +169,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -289,15 +301,15 @@ components: document_share_count: type: number description: 分享次数 - example: 0 + example: 分享次数|number document_download_count: type: number description: 下载次数 - example: 0 + example: 下载次数|number document_favorite_count: type: number description: 收藏次数 - example: 0 + example: 收藏次数|number document_embedding_status: type: string description: 文档嵌入状态 @@ -360,8 +372,8 @@ components: document_remark: 备注|string PocketBaseDocumentRecord: allOf: - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseRecordBase - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseDocumentFields + - $ref: #/components/schemas/PocketBaseRecordBase + - $ref: #/components/schemas/PocketBaseDocumentFields example: id: PocketBase 记录主键|string collectionId: collectionId|string @@ -427,7 +439,7 @@ components: items: type: array items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseDocumentRecord + $ref: #/components/schemas/PocketBaseDocumentRecord example: page: page|integer perPage: perPage|integer diff --git a/pocket-base/spec/openapi-wx/openapi.yaml b/pocket-base/spec/openapi-wx/openapi.yaml index ac5af86..5e1057b 100644 --- a/pocket-base/spec/openapi-wx/openapi.yaml +++ b/pocket-base/spec/openapi-wx/openapi.yaml @@ -5,6 +5,8 @@ info: description: | 本目录仅收敛 PocketBase 原生 API 文档,不包含自定义 hooks API。 + 本文件为目录索引,支持单文件独立导入,不依赖其他 YAML。 + 文档约定: - 不单独配置鉴权组件;如接口需要登录,请直接在说明中关注 `Authorization: Bearer ` - 示例字段值统一使用 `<字段说明>|<类型>` 风格 @@ -27,22 +29,12 @@ tags: description: PocketBase 原生购物车记录接口 - name: 订单 description: PocketBase 原生订单记录接口 -paths: - /pb/api/collections/tbl_company/records: - $ref: './company.yaml#/paths/companyRecords' - /pb/api/collections/tbl_company/records/{recordId}: - $ref: './company.yaml#/paths/companyRecordById' - /pb/api/collections/tbl_attachments/records: - $ref: './attachments.yaml#/paths/attachmentRecords' - /pb/api/collections/tbl_product_list/records: - $ref: './products.yaml#/paths/productRecords' - /pb/api/collections/tbl_document/records: - $ref: './documents.yaml#/paths/documentRecords' - /pb/api/collections/tbl_cart/records: - $ref: './cart.yaml#/paths/cartRecords' - /pb/api/collections/tbl_cart/records/{recordId}: - $ref: './cart.yaml#/paths/cartRecordById' - /pb/api/collections/tbl_order/records: - $ref: './order.yaml#/paths/orderRecords' - /pb/api/collections/tbl_order/records/{recordId}: - $ref: './order.yaml#/paths/orderRecordById' \ No newline at end of file +paths: {} +x-index: + files: + - company.yaml + - attachments.yaml + - products.yaml + - documents.yaml + - cart.yaml + - order.yaml \ No newline at end of file diff --git a/pocket-base/spec/openapi-wx/order.yaml b/pocket-base/spec/openapi-wx/order.yaml index 276806c..1e0d65c 100644 --- a/pocket-base/spec/openapi-wx/order.yaml +++ b/pocket-base/spec/openapi-wx/order.yaml @@ -1,11 +1,24 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Order + version: 1.0.0 + description: | + PocketBase 原生 `tbl_order` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 +tags: + - name: 订单 + description: PocketBase 原生订单记录接口 paths: - orderRecords: + /pb/api/collections/tbl_order/records: get: + operationId: getPocketBaseOrderRecords tags: [订单] summary: 查询订单记录列表 - description: | - 使用 PocketBase 原生 records list 接口查询 `tbl_order`。 - 如需鉴权,请自行在请求头中携带 `Authorization: Bearer `。 parameters: - name: filter in: query @@ -33,7 +46,7 @@ paths: required: false schema: type: string - example: -order_create + example: 排序表达式|string responses: '200': description: 查询成功 @@ -43,18 +56,32 @@ paths: $ref: '#/components/schemas/PocketBaseOrderListResponse' '400': description: 查询参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '403': description: 无权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' post: + operationId: postPocketBaseOrderRecord tags: [订单] summary: 创建订单记录 - description: | - 使用 PocketBase 原生 records create 接口向 `tbl_order` 新增记录。 - 如集合规则要求 `order_owner` 与当前用户一致,请客户端显式提交。 requestBody: required: true content: @@ -81,19 +108,33 @@ paths: $ref: '#/components/schemas/PocketBaseOrderRecord' '400': description: 参数错误或违反集合规则 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '403': description: 无权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 - orderRecordById: + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' + /pb/api/collections/tbl_order/records/{recordId}: patch: + operationId: patchPocketBaseOrderRecordByRecordId tags: [订单] summary: 更新订单记录 - description: | - 使用 PocketBase 原生 records update 接口更新 `tbl_order`。 - 路径参数使用 PocketBase 原生 `recordId`。 parameters: - name: recordId in: path @@ -126,18 +167,32 @@ paths: $ref: '#/components/schemas/PocketBaseOrderRecord' '400': description: 参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '404': description: 记录不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' delete: + operationId: deletePocketBaseOrderRecordByRecordId tags: [订单] summary: 删除订单记录 - description: | - 使用 PocketBase 原生 records delete 接口删除 `tbl_order`。 - 路径参数使用 PocketBase 原生 `recordId`。 parameters: - name: recordId in: path @@ -150,877 +205,65 @@ paths: description: 删除成功 '401': description: token 无效或已过期 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '404': description: 记录不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/PocketBaseNativeError' '500': description: 服务端错误 - "400": - description: 参数错误 - components: - schemas: - 创建规则: - - 服务端自动根据当前 token 写入 `order_owner` - - 服务端自动生成 `order_id` - - 若未传 `order_number`,服务端会自动生成展示编号 - - `order_source`、`order_source_id`、`order_snap`、`order_amount` 为必填 - - 目标软删除契约: - description: PocketBase错误码 - - 当前仓库导出响应中尚未显式返回 `is_delete` 字段 - security: - description: PocketBase错误信息 - example: PocketBase原生错误信息 | string - requestBody: - description: PocketBase错误数据 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderCreateRequest - example: - order_number: 可选;未传时服务端自动生成|string - order_source: 订单来源|string - order_status: 可选;未传时默认 订单已生成|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|integer - order_remark: 备注|string - responses: - "200": - description: 创建成功 content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderRecord - example: - pb_id: PocketBase 记录主键 id|string - created: PocketBase 系统创建时间|string - updated: PocketBase 系统更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|integer - order_remark: 备注|string - is_delete: 软删除标记;目标契约字段,当前 hooks 响应可能尚未显式透出|integer - "400": - description: 参数错误或创建失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - orderUpdate: - post: - operationId: postOrderUpdate - tags: - - 订单 - summary: 修改订单记录 - description: | - 调用自定义 hooks API 按 `order_id` 更新订单记录。 - - 更新规则: - - 仅允许修改当前 `Authorization` 对应用户自己的订单记录 - - `order_id` 为必填,用于精确定位目标记录 - - 其余字段均为可选增量更新 - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderUpdateRequest - example: - order_id: 订单业务 ID|string - order_number: order_number|string - order_source: order_source|string - order_status: order_status|string - order_source_id: order_source_id|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: order_amount|integer - order_remark: order_remark|string - responses: - "200": - description: 更新成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderRecord - example: - pb_id: PocketBase 记录主键 id|string - created: PocketBase 系统创建时间|string - updated: PocketBase 系统更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|integer - order_remark: 备注|string - is_delete: 软删除标记;目标契约字段,当前 hooks 响应可能尚未显式透出|integer - "400": - description: 参数错误或更新失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 无权访问该订单记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 未找到待修改的订单记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - orderDelete: - post: - operationId: postOrderDelete - tags: - - 订单 - summary: 软删除订单记录 - description: | - 目标契约:按 `order_id` 软删除订单记录,将 `is_delete` 标记为 `1`,而不是物理删除。 - - 当前仓库实现差异: - - 当前 `cartOrderService.deleteOrder()` 仍直接调用 `$app.delete(record)` 做物理删除 - - 因此当前后端实现与本软删除契约不一致 - - 若要严格按本文档执行,需先同步调整后端服务实现,并在列表/详情接口中补充 `is_delete = 0` 过滤 - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderDeleteRequest - example: - order_id: 订单业务 ID|string - responses: - "200": - description: 删除成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/OrderDeleteResponse - example: - order_id: 订单业务 ID|string - is_delete: 目标软删除标记值;当前实现可能仍返回物理删除结果|integer - "400": - description: 参数错误或删除失败 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 无权访问该订单记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 未找到待删除的订单记录 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "415": - description: 请求体必须为 application/json - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "429": - description: 重复请求过于频繁 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/ErrorResponse - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - orderRecords: - get: - operationId: getPocketBaseOrderRecords - tags: - - 订单 - summary: 查询当前用户订单列表或按业务 ID 精确查询 - description: | - 使用 PocketBase 原生 records list 接口查询 `tbl_order`。 - - 当前线上权限规则: - - `listRule = @request.auth.id != "" && order_owner = @request.auth.openid && is_delete = 0` - - 因此调用方只能读到 `order_owner` 等于自己 `openid` 且未软删除的记录 - - 标准调用方式: - 1. 查询当前登录用户全部订单: - - 不传 `filter` - - 可选传 `sort=-order_create` - 2. 按业务 ID 精确查单条: - - `filter=order_id="ORDER-..."` - - `perPage=1` - - `page=1` - security: - - BearerAuth: [] - parameters: - - name: filter - in: query - required: false - schema: - type: string - example: order_id="ORDER-1770000000000-abc123" - - name: page - in: query - required: false - schema: - type: integer - minimum: 1 - default: 1 - - name: perPage - in: query - required: false - schema: - type: integer - minimum: 1 - default: 20 - - name: sort - in: query - required: false - description: PocketBase 原生排序表达式,推荐 `-order_create` - schema: - type: string - example: -order_create - responses: - "200": - description: 查询成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderListResponse - example: - page: page|integer - perPage: perPage|integer - totalItems: totalItems|integer - totalPages: totalPages|integer - items: - - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|number - order_remark: 备注|string - "400": - description: 查询参数错误或不满足 listRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 集合规则被锁定或服务端权限设置异常 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - post: - operationId: postPocketBaseOrderRecord - tags: - - 订单 - summary: 创建订单记录 - description: | - 使用 PocketBase 原生 records create 接口向 `tbl_order` 新增记录。 - - 当前线上权限规则: - - `createRule = @request.auth.id != "" && @request.body.order_owner = @request.auth.openid` - - 因此客户端创建时必须显式提交 `order_owner`,并且值必须等于当前 token 对应的 `openid` - - 这意味着: - - 不能依赖服务端自动补 owner - - 不能省略 `order_owner` - - 不满足规则时 PocketBase 会直接返回 `400` - security: - - BearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderCreateRequest - example: - order_id: order_id|string - order_number: order_number|string - order_owner: 必须显式提交,且值必须等于当前 token 对应 openid|string - order_source: order_source|string - order_status: order_status|string - order_source_id: order_source_id|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: order_amount|number - order_remark: order_remark|string - responses: - "200": - description: 创建成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderRecord - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|number - order_remark: 备注|string - "400": - description: 参数错误、违反字段约束或不满足 createRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "403": - description: 集合规则被锁定或服务端权限设置异常 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - orderRecordById: - patch: - operationId: patchPocketBaseOrderRecordByRecordId - tags: - - 订单 - summary: 更新订单记录 - description: | - 使用 PocketBase 原生 records update 接口更新 `tbl_order`。 - - 标准调用流程: - 1. 先通过 `GET /pb/api/collections/tbl_order/records?filter=order_id="..."&perPage=1&page=1` 找到原生 `recordId` - 2. 再调用当前 `PATCH /pb/api/collections/tbl_order/records/{recordId}` - - 当前线上权限规则: - - `updateRule = @request.auth.id != "" && order_owner = @request.auth.openid` - - 调用方只能修改自己的订单记录 - security: - - BearerAuth: [] - parameters: - - name: recordId - in: path - required: true - schema: - type: string - example: l2r3nq7rqhuob0h - requestBody: - required: true - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderUpdateRequest - example: - order_number: order_number|string - order_owner: 若提交,必须仍等于当前 token 对应 openid|string - order_source: order_source|string - order_status: order_status|string - order_source_id: order_source_id|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: order_amount|number - order_remark: order_remark|string - responses: - "200": - description: 更新成功 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderRecord - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|number - order_remark: 备注|string - "400": - description: 参数错误或违反字段约束 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 记录不存在或不满足 updateRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - delete: - operationId: deletePocketBaseOrderRecordByRecordId - tags: - - 订单 - summary: 删除订单记录 - description: | - 使用 PocketBase 原生 records delete 接口删除 `tbl_order`。 - - 当前线上权限规则: - - `deleteRule = @request.auth.id != "" && order_owner = @request.auth.openid` - - 调用方只能删除自己的订单记录 - security: - - BearerAuth: [] - parameters: - - name: recordId - in: path - required: true - schema: - type: string - example: l2r3nq7rqhuob0h - responses: - "204": - description: 删除成功 - "401": - description: token 缺失、无效或已过期 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "404": - description: 记录不存在或不满足 deleteRule - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string - "500": - description: 服务端错误 - content: - application/json: - schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError - example: - code: 业务状态码|integer - message: message|string - data: - 业务响应数据字段|string: 业务响应数据值|string + $ref: '#/components/schemas/PocketBaseNativeError' components: schemas: - ApiResponseBase: - type: object - required: - - statusCode - - errMsg - - data - properties: - statusCode: - type: - - integer - - string - description: 业务状态码 - example: 业务状态码 | integer - errMsg: - type: string - description: 业务提示信息 - example: 业务提示信息 | string - data: - description: 业务响应数据 - type: object - additionalProperties: true - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - ErrorResponse: - type: object - required: - - statusCode - - errMsg - - data - properties: - statusCode: - type: - - integer - - string - description: 业务状态码 - example: 业务状态码 | integer - errMsg: - type: string - description: 业务提示信息 - example: 失败原因提示 | string - data: - description: 业务响应数据 - type: object - additionalProperties: true - example: - statusCode: 业务状态码|integer - errMsg: 业务提示信息|string - data: - 业务响应数据字段|string: 业务响应数据值|string - HookRecordBase: - type: object - properties: - pb_id: - type: string - description: PocketBase 记录主键 id - example: l2r3nq7rqhuob0h - created: - type: string - description: PocketBase 系统创建时间 - example: 2026-04-03 15:30:00.000Z - updated: - type: string - description: PocketBase 系统更新时间 - example: 2026-04-03 15:35:00.000Z - example: - pb_id: PocketBase 记录主键 id|string - created: PocketBase 系统创建时间|string - updated: PocketBase 系统更新时间|string PocketBaseNativeError: type: object properties: code: - type: - - integer - - string - description: 业务状态码 - example: 错误状态码 | integer + type: [integer, string] + description: PocketBase错误码 message: type: string - example: PocketBase原生错误信息 | string + description: PocketBase错误信息 data: - description: 业务响应数据 type: object additionalProperties: true + description: PocketBase错误数据 example: - code: 业务状态码|integer - message: message|string + code: 错误状态码|integer + message: PocketBase原生错误信息|string data: - 业务响应数据字段|string: 业务响应数据值|string + 字段名|string: 字段值|string PocketBaseRecordBase: type: object - required: - - id - - collectionId - - collectionName - - created - - updated + required: [id, collectionId, collectionName, created, updated] properties: id: type: string - description: PocketBase 记录主键 - example: PocketBase记录主键 | string + description: PocketBase记录主键 collectionId: type: string - example: 集合ID | string + description: 集合ID collectionName: type: string - example: 集合名称 | string + description: 集合名称 created: type: string description: 记录创建时间 - example: 记录创建时间 | string updated: type: string description: 记录更新时间 - example: 记录更新时间 | string example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string + id: PocketBase记录主键|string + collectionId: 集合ID|string + collectionName: 集合名称|string created: 记录创建时间|string updated: 记录更新时间|string PocketBaseOrderFields: @@ -1028,34 +271,26 @@ components: properties: order_id: type: string - description: 订单业务 ID - example: ORDER-1770000000000-abc123 + description: 订单业务ID order_number: type: string description: 订单编号 - example: wx-user-20260403153500 order_create: type: string - description: 订单创建时间,由数据库自动生成 - example: 2026-04-03 15:35:00.000Z + description: 订单创建时间 order_owner: type: string - description: 订单所有者 openid - example: wx-openid-user-001 + description: 订单所有者openid order_source: type: string description: 订单来源 - example: 购物车 order_status: type: string description: 订单状态 - example: 订单已生成 order_source_id: type: string - description: 来源关联业务 ID - example: CART-1770000000000-abc123 + description: 来源关联业务ID order_snap: - description: 订单快照 JSON oneOf: - type: object additionalProperties: true @@ -1063,60 +298,32 @@ components: items: type: object additionalProperties: true + description: 订单快照 order_amount: - type: - - number - - integer + type: [number, integer] description: 订单金额 - example: 3998 order_remark: type: string description: 备注 - example: 小程序订单示例 example: - order_id: 订单业务 ID|string + order_id: 订单业务ID|string order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string + order_create: 订单创建时间|string + order_owner: 订单所有者openid|string order_source: 订单来源|string order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string + order_source_id: 来源关联业务ID|string order_snap: - order_snap字段|string: order_snap值|string + 字段名|string: 字段值|string order_amount: 订单金额|number order_remark: 备注|string PocketBaseOrderRecord: allOf: - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseRecordBase - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderFields - example: - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|number - order_remark: 备注|string + - $ref: '#/components/schemas/PocketBaseRecordBase' + - $ref: '#/components/schemas/PocketBaseOrderFields' PocketBaseOrderCreateRequest: type: object - required: - - order_id - - order_number - - order_owner - - order_source - - order_status - - order_source_id - - order_snap - - order_amount + required: [order_id, order_number, order_owner, order_source, order_status, order_source_id, order_snap, order_amount] properties: order_id: type: string @@ -1124,7 +331,6 @@ components: type: string order_owner: type: string - description: 必须显式提交,且值必须等于当前 token 对应 openid order_source: type: string order_status: @@ -1140,22 +346,9 @@ components: type: object additionalProperties: true order_amount: - type: - - number - - integer + type: [number, integer] order_remark: type: string - example: - order_id: order_id|string - order_number: order_number|string - order_owner: 必须显式提交,且值必须等于当前 token 对应 openid|string - order_source: order_source|string - order_status: order_status|string - order_source_id: order_source_id|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: order_amount|number - order_remark: order_remark|string PocketBaseOrderUpdateRequest: type: object properties: @@ -1163,7 +356,6 @@ components: type: string order_owner: type: string - description: 若提交,必须仍等于当前 token 对应 openid order_source: type: string order_status: @@ -1179,69 +371,22 @@ components: type: object additionalProperties: true order_amount: - type: - - number - - integer + type: [number, integer] order_remark: type: string - example: - order_number: order_number|string - order_owner: 若提交,必须仍等于当前 token 对应 openid|string - order_source: order_source|string - order_status: order_status|string - order_source_id: order_source_id|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: order_amount|number - order_remark: order_remark|string PocketBaseOrderListResponse: type: object - required: - - page - - perPage - - totalItems - - totalPages - - items + required: [page, perPage, totalItems, totalPages, items] properties: page: - type: - - integer - - string + type: [integer, string] perPage: - type: - - integer - - string + type: [integer, string] totalItems: - type: - - integer - - string + type: [integer, string] totalPages: - type: - - integer - - string + type: [integer, string] items: type: array items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseOrderRecord - example: - page: page|integer - perPage: perPage|integer - totalItems: totalItems|integer - totalPages: totalPages|integer - items: - - id: PocketBase 记录主键|string - collectionId: collectionId|string - collectionName: collectionName|string - created: 记录创建时间|string - updated: 记录更新时间|string - order_id: 订单业务 ID|string - order_number: 订单编号|string - order_create: 订单创建时间,由数据库自动生成|string - order_owner: 订单所有者 openid|string - order_source: 订单来源|string - order_status: 订单状态|string - order_source_id: 来源关联业务 ID|string - order_snap: - order_snap字段|string: order_snap值|string - order_amount: 订单金额|number - order_remark: 备注|string + $ref: '#/components/schemas/PocketBaseOrderRecord' diff --git a/pocket-base/spec/openapi-wx/products.yaml b/pocket-base/spec/openapi-wx/products.yaml index bb43a17..7f10e70 100644 --- a/pocket-base/spec/openapi-wx/products.yaml +++ b/pocket-base/spec/openapi-wx/products.yaml @@ -1,5 +1,17 @@ +openapi: 3.1.0 +info: + title: BAI PocketBase Native API - Products + version: 1.0.0 + description: | + PocketBase 原生 `tbl_product_list` records API 文档。 + 本文件可单独导入使用,不依赖其他 YAML。 +servers: + - url: https://bai-api.blv-oa.com + description: 生产环境 + - url: http://localhost:8090 + description: PocketBase 本地环境 paths: - productRecords: + /pb/api/collections/tbl_product_list/records: get: operationId: getPocketBaseProductListRecords tags: @@ -30,7 +42,7 @@ paths: 推荐写法:`prod_list_category="<产品分类>"` schema: type: string - example: prod_list_category="<产品分类>" + example: 过滤表达式|string - name: page in: query required: false @@ -57,14 +69,14 @@ paths: - `prod_list_sort`:按分类排序值从小到大 schema: type: string - example: prod_list_sort + example: 排序表达式|string responses: "200": description: 查询成功 content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseProductListListResponse + $ref: #/components/schemas/PocketBaseProductListListResponse example: page: page|integer perPage: perPage|integer @@ -79,6 +91,7 @@ paths: prod_list_id: 产品列表业务 ID,唯一标识|string prod_list_name: 产品名称|string prod_list_modelnumber: 产品型号|string + prod_list_barcode: 产品料号|string prod_list_icon: 产品图标附件 ID,保存 tbl_attachments.attachments_id|string prod_list_description: 产品说明|string prod_list_feature: 产品特色|string @@ -103,7 +116,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -114,7 +127,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -125,7 +138,7 @@ paths: content: application/json: schema: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseNativeError + $ref: #/components/schemas/PocketBaseNativeError example: code: 业务状态码|integer message: message|string @@ -202,6 +215,10 @@ components: type: string description: 产品型号 example: <产品型号>| + prod_list_barcode: + type: string + description: 产品料号 + example: <产品料号>| prod_list_icon: type: string description: 产品图标附件 ID,保存 `tbl_attachments.attachments_id` @@ -242,7 +259,7 @@ components: - number - integer description: 排序值(同分类内按升序) - example: 10 + example: 排序值|number prod_list_comm_type: type: string description: 通讯类型 @@ -268,7 +285,7 @@ components: - number - integer description: 基础价格 - example: 1999 + example: 基础价格|number prod_list_vip_price: type: array description: 会员价数组,每项包含会员等级枚举值与价格 @@ -282,10 +299,10 @@ components: type: - number - integer - example: 1899 + example: 会员价格|number example: - - viplevel: VIP1 - price: 1899 + - viplevel: 会员等级|string + price: 会员价格|number prod_list_remark: type: string description: 备注 @@ -294,6 +311,7 @@ components: prod_list_id: 产品列表业务 ID,唯一标识|string prod_list_name: 产品名称|string prod_list_modelnumber: 产品型号|string + prod_list_barcode: 产品料号|string prod_list_icon: 产品图标附件 ID,保存 tbl_attachments.attachments_id|string prod_list_description: 产品说明|string prod_list_feature: 产品特色|string @@ -315,8 +333,8 @@ components: prod_list_remark: 备注|string PocketBaseProductListRecord: allOf: - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseRecordBase - - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseProductListFields + - $ref: #/components/schemas/PocketBaseRecordBase + - $ref: #/components/schemas/PocketBaseProductListFields example: id: PocketBase 记录主键|string collectionId: collectionId|string @@ -326,6 +344,7 @@ components: prod_list_id: 产品列表业务 ID,唯一标识|string prod_list_name: 产品名称|string prod_list_modelnumber: 产品型号|string + prod_list_barcode: 产品料号|string prod_list_icon: 产品图标附件 ID,保存 tbl_attachments.attachments_id|string prod_list_description: 产品说明|string prod_list_feature: 产品特色|string @@ -377,7 +396,7 @@ components: items: type: array items: - $ref: ../openapi-wx.yaml#/components/schemas/PocketBaseProductListRecord + $ref: #/components/schemas/PocketBaseProductListRecord example: page: page|integer perPage: perPage|integer @@ -392,6 +411,7 @@ components: prod_list_id: 产品列表业务 ID,唯一标识|string prod_list_name: 产品名称|string prod_list_modelnumber: 产品型号|string + prod_list_barcode: 产品料号|string prod_list_icon: 产品图标附件 ID,保存 tbl_attachments.attachments_id|string prod_list_description: 产品说明|string prod_list_feature: 产品特色|string diff --git a/pocket-base/spec/openapi.yaml b/pocket-base/spec/openapi.yaml deleted file mode 100644 index 2709804..0000000 --- a/pocket-base/spec/openapi.yaml +++ /dev/null @@ -1,1891 +0,0 @@ -openapi: 3.1.0 -info: - title: BAI PocketBase Hooks API - description: | - 基于 PocketBase `bai_api_pb_hooks` 的对外接口文档,可直接导入 Postman。 - 当前 `tbl_auth_users.openid` 已被定义为全平台统一身份锚点: - - 微信用户:`openid = 微信 openid` - - 平台用户:`openid = 服务端生成的 GUID` - 请在 Apifox 环境中统一设置全局 Header:`Authorization: Bearer {{token}}`。 - version: 1.0.0 -servers: - - url: https://bai-api.blv-oa.com - description: 生产环境 - - url: http://localhost:8090 - description: PocketBase 本地环境 -tags: - - name: 系统 - description: 基础检查接口 - - name: 微信认证 - description: 面向微信用户的认证接口;认证成功后仍统一使用全平台 `openid` 与 PocketBase 原生 token。 - - name: 平台认证 - description: 面向平台用户的认证接口;平台用户会生成 GUID 并写入统一 `openid` 字段。 - - name: 字典管理 - description: 字典读接口公开;字典写接口面向 ManagePlatform 用户。 - - name: 附件管理 - description: 面向 ManagePlatform 用户的附件上传、查询与删除接口。 - - name: 文档管理 - description: 面向 ManagePlatform 用户的文档新增、查询、修改、删除接口;查询时会自动返回关联附件的 PocketBase 文件流链接。 - - name: 文档历史 - description: 面向 ManagePlatform 用户的文档操作历史查询接口。 -components: - schemas: - ApiResponse: - type: object - required: [statusCode, errMsg, data] - properties: - statusCode: - type: integer - description: "业务状态码" - example: 200 - errMsg: - type: string - description: "业务提示信息" - example: 操作成功 - data: - description: "业务响应数据" - type: object - additionalProperties: true - HealthData: - type: object - properties: - status: - type: string - example: healthy - version: - type: string - description: 当前已部署 hooks 版本号,用于确认发布是否生效 - example: 2026.03.26-health-probe.1 - timestamp: - type: string - format: date-time - UsersCountData: - type: object - properties: - total_users: - type: integer - description: tbl_auth_users 表中的用户总数 - example: 128 - HelloWorldData: - type: object - properties: - message: - type: string - example: Hello, World! - timestamp: - type: string - format: date-time - status: - type: string - example: success - build_time: - anyOf: - - type: string - format: date-time - - type: 'null' - CompanyInfo: - description: 用户所属公司信息;当用户尚未绑定公司时返回 `null` - anyOf: - - type: object - properties: - pb_id: - type: string - description: PocketBase 记录主键 id - company_id: - type: string - description: 公司业务 id,由数据库自动生成 - company_name: - type: string - description: 公司名称 - company_type: - type: string - description: 公司类型 - company_entity: - type: string - description: 公司法人 - company_usci: - type: string - description: 统一社会信用代码 - company_nationality: - type: string - description: 国家名称 - company_nationality_code: - type: string - description: 国家编码 - company_province: - type: string - description: 省份名称 - company_province_code: - type: string - description: 省份编码 - company_city: - type: string - description: 城市名称 - company_city_code: - type: string - description: 城市编码 - company_district: - type: string - description: 区/县名称 - company_district_code: - type: string - description: 区/县编码 - company_postalcode: - type: string - description: 邮政编码 - company_add: - type: string - description: 公司地址 - company_status: - type: string - description: 公司状态 - company_level: - type: string - description: 公司等级 - company_owner_openid: - type: string - description: 公司所有者 openid - company_remark: - type: string - description: 备注 - created: - type: string - description: 记录创建时间 - updated: - type: string - description: 记录更新时间 - - type: 'null' - UserInfo: - type: object - description: | - 统一用户视图。 - 其中 `openid` 为全平台统一身份标识:微信用户使用微信 openid,平台用户使用服务端生成 GUID。 - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - users_convers_id: - description: "会话侧用户 ID" - type: string - users_id: - description: "用户业务 ID" - type: string - users_idtype: - description: 用户身份来源类型 - anyOf: - - type: string - enum: [WeChat, ManagePlatform] - - type: string - users_id_number: - description: "证件号" - type: string - users_status: - description: "用户状态" - type: string - users_rank_level: - description: "用户星级数值" - type: [number, string] - users_auth_type: - description: "账户类型" - type: [number, string] - users_type: - description: "用户类型" - anyOf: - - type: string - enum: [游客, 注册用户] - - type: string - users_name: - description: "用户姓名 / 昵称" - type: string - users_phone: - description: "手机号" - type: string - users_phone_masked: - type: string - users_level: - type: string - description: 用户等级 - users_level_name: - type: string - description: 用户等级名称,按 `users_level -> 数据-会员等级` 字典描述实时解析 - users_tag: - type: string - description: 用户标签 - users_picture: - type: string - description: 用户头像附件的 `attachments_id` - users_picture_url: - type: string - description: 根据 `users_picture -> tbl_attachments` 自动解析出的头像文件流链接 - users_id_pic_a: - type: string - description: 证件正面附件的 `attachments_id` - users_id_pic_a_url: - type: string - description: 根据 `users_id_pic_a -> tbl_attachments` 自动解析出的文件流链接 - users_id_pic_b: - type: string - description: 证件反面附件的 `attachments_id` - users_id_pic_b_url: - type: string - description: 根据 `users_id_pic_b -> tbl_attachments` 自动解析出的文件流链接 - users_title_picture: - type: string - description: 资质附件的 `attachments_id` - users_title_picture_url: - type: string - description: 根据 `users_title_picture -> tbl_attachments` 自动解析出的文件流链接 - openid: - type: string - description: 全平台统一身份标识;微信用户为微信 openid,平台用户为服务端生成的 GUID - company_id: - type: string - description: 公司业务 id,存储 `tbl_company.company_id` - users_parent_id: - type: string - description: 上级用户业务 id - users_promo_code: - type: string - description: 推广码 - usergroups_id: - type: string - description: 用户组业务 id - company: - $ref: '#/components/schemas/CompanyInfo' - created: - type: string - description: 用户创建时间 - updated: - type: string - description: 用户更新时间 - example: - pb_id: PocketBase记录主键id | string - users_convers_id: 会话侧用户ID | string - users_id: 用户业务ID | string - users_idtype: 用户身份来源类型 | string - users_id_number: 证件号 | string - users_type: 用户类型 | string - users_name: 用户姓名或昵称 | string - users_status: 用户状态 | string - users_rank_level: 用户星级数值 | number - users_auth_type: 账户类型 | number - users_phone: 手机号 | string - users_phone_masked: 手机号脱敏值 | string - users_level: 用户等级 | string - users_level_name: 用户等级名称 | string - users_tag: 用户标签 | string - users_picture: 用户头像附件ID | string - users_picture_url: 用户头像文件流链接 | string - users_id_pic_a: 证件正面附件ID | string - users_id_pic_a_url: 证件正面文件流链接 | string - users_id_pic_b: 证件反面附件ID | string - users_id_pic_b_url: 证件反面文件流链接 | string - users_title_picture: 资质附件ID | string - users_title_picture_url: 资质附件文件流链接 | string - openid: 全平台统一身份标识 | string - company_id: 公司业务id | string - users_parent_id: 上级用户业务id | string - users_promo_code: 推广码 | string - usergroups_id: 用户组业务id | string - company: - pb_id: PocketBase记录主键id | string - company_id: 公司业务id,由数据库自动生成 | string - company_name: 公司名称 | string - company_type: 公司类型 | string - company_entity: 公司法人 | string - company_usci: 统一社会信用代码 | string - company_nationality: 国家名称 | string - company_nationality_code: 国家编码 | string - company_province: 省份名称 | string - company_province_code: 省份编码 | string - company_city: 城市名称 | string - company_city_code: 城市编码 | string - company_district: 区县名称 | string - company_district_code: 区县编码 | string - company_postalcode: 邮政编码 | string - company_add: 公司地址 | string - company_status: 公司状态 | string - company_level: 公司等级 | string - company_owner_openid: 公司所有者openid | string - company_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - created: 用户创建时间 | string - updated: 用户更新时间 | string - PocketBaseAuthResponse: - type: object - description: | - 项目统一认证响应。 - 所有对外接口统一返回 `statusCode`、`errMsg`、`data`,认证成功时额外返回顶层 `token`。 - properties: - statusCode: - type: integer - description: "业务状态码" - example: 200 - errMsg: - type: string - description: "业务提示信息" - example: 登录成功 - data: - description: "业务响应数据" - type: object - properties: - status: - anyOf: - - type: string - enum: [register_success, login_success] - - type: string - is_info_complete: - type: [boolean, string] - user: - $ref: '#/components/schemas/UserInfo' - token: - type: string - description: PocketBase 原生 auth token;仅认证类接口在成功时额外返回 - example: - statusCode: 200 - errMsg: 登录成功 - data: - status: 登录或注册状态 | string - is_info_complete: 资料是否完整 | boolean - user: - pb_id: PocketBase记录主键id | string - users_id: 用户业务ID | string - users_idtype: 用户身份来源类型 | string - users_name: 用户姓名或昵称 | string - users_phone: 手机号 | string - users_phone_masked: 手机号脱敏值 | string - users_status: 用户状态 | string - users_rank_level: 用户星级数值 | number - users_auth_type: 账户类型 | number - users_type: 用户类型 | string - users_picture: 用户头像附件ID | string - users_picture_url: 用户头像文件流链接 | string - users_id_pic_a: 证件正面附件ID | string - users_id_pic_a_url: 证件正面文件流链接 | string - users_id_pic_b: 证件反面附件ID | string - users_id_pic_b_url: 证件反面文件流链接 | string - users_title_picture: 资质附件ID | string - users_title_picture_url: 资质附件文件流链接 | string - openid: 全平台统一身份标识 | string - company_id: 公司业务id | string - users_parent_id: 上级用户业务id | string - users_promo_code: 推广码 | string - usergroups_id: 用户组业务id | string - company: - pb_id: PocketBase记录主键id | string - company_id: 公司业务id,由数据库自动生成 | string - company_name: 公司名称 | string - company_type: 公司类型 | string - company_entity: 公司法人 | string - company_usci: 统一社会信用代码 | string - company_nationality: 国家名称 | string - company_nationality_code: 国家编码 | string - company_province: 省份名称 | string - company_province_code: 省份编码 | string - company_city: 城市名称 | string - company_city_code: 城市编码 | string - company_district: 区县名称 | string - company_district_code: 区县编码 | string - company_postalcode: 邮政编码 | string - company_add: 公司地址 | string - company_status: 公司状态 | string - company_level: 公司等级 | string - company_owner_openid: 公司所有者openid | string - company_remark: 备注 | string - created: 记录创建时间 | string - updated: 记录更新时间 | string - created: 用户创建时间 | string - updated: 用户更新时间 | string - token: PocketBase原生认证token | string - WechatLoginRequest: - type: object - required: [users_wx_code] - description: 微信小程序登录/注册请求体。 - properties: - users_wx_code: - type: string - description: 微信小程序登录临时凭证 code - example: 0a1b2c3d4e5f6g - WechatProfileRequest: - type: object - description: 微信用户资料完善请求体。 - properties: - users_name: - type: string - description: "用户姓名 / 昵称" - example: 张三 - users_phone_code: - type: string - description: 可选。若传入,服务端优先通过微信接口换取真实手机号并写入数据库 - example: 2b7d9f2e3c4a5b6d7e8f - users_phone: - type: string - description: 可选。未传 `users_phone_code` 时,可直接写入手机号 - example: '13800138000' - users_type: - type: string - description: 可选。用户类型;仅在传入非空值时更新 - example: 服务商 - company_id: - type: string - description: 可选。公司业务 id;仅在传入非空值时更新 - example: WX-COMPANY-10001 - users_tag: - type: string - description: 可选。用户标签;非空时才更新 - example: 核心客户 - users_picture: - type: string - description: 可选。用户头像附件的 `attachments_id` - example: ATT-1743123456789-abc123 - users_id_pic_a: - type: string - description: 可选。证件正面附件的 `attachments_id` - users_id_pic_b: - type: string - description: 可选。证件反面附件的 `attachments_id` - users_title_picture: - type: string - description: 可选。资质附件的 `attachments_id` - WechatProfileResponseData: - type: object - properties: - status: - type: string - enum: [update_success] - user: - $ref: '#/components/schemas/UserInfo' - PlatformRegisterRequest: - type: object - required: [users_name, users_phone, password, passwordConfirm, users_picture] - description: 平台用户注册请求体;注册成功后将生成 GUID 并写入统一 `openid` 字段。 - properties: - users_name: - type: string - description: "用户姓名 / 昵称" - example: 张三 - users_phone: - type: string - description: "手机号" - example: '13800138000' - password: - type: string - description: "PocketBase 认证密码" - example: '12345678' - passwordConfirm: - type: string - example: '12345678' - users_picture: - type: string - description: 用户头像附件的 `attachments_id` - example: ATT-1743123456789-abc123 - users_id_number: - description: "证件号" - type: string - users_id_pic_a: - type: string - description: 可选。证件正面附件的 `attachments_id` - users_id_pic_b: - type: string - description: 可选。证件反面附件的 `attachments_id` - users_title_picture: - type: string - description: 可选。资质附件的 `attachments_id` - users_level: - description: "用户等级文本" - type: string - users_tag: - description: "用户标签" - type: string - users_type: - description: "用户类型" - type: string - company_id: - description: "所属公司业务 ID" - type: string - users_parent_id: - description: "上级用户业务 ID" - type: string - users_promo_code: - description: "推广码" - type: string - usergroups_id: - description: "用户组 / 角色 ID" - type: string - PlatformLoginRequest: - type: object - required: [login_account, password] - description: 平台用户登录请求体;前端使用邮箱或手机号 + 密码提交,服务端内部转换为 PocketBase 原生 password auth。 - properties: - login_account: - type: string - description: 支持邮箱或手机号 - example: admin@example.com - password: - type: string - description: "PocketBase 认证密码" - example: '12345678' - SystemRefreshTokenRequest: - type: object - description: | - 系统刷新 token 请求体。 - `users_wx_code` 允许为空。 - 当 `Authorization` 对应 token 有效时,可不传或传空; - 当 token 失效时,需提供 `users_wx_code` 走微信 code 重新签发流程。 - properties: - users_wx_code: - anyOf: - - type: string - - type: 'null' - description: 微信小程序登录临时凭证 code - example: 0a1b2c3d4e5f6g - RefreshTokenData: - type: object - properties: {} - DictionaryItem: - type: object - required: [enum, description, sortOrder] - properties: - enum: - type: string - example: enabled - description: - type: string - example: 启用 - image: - type: string - description: 对应图片附件的 `attachments_id`,允许为空 - example: ATT-1743037200000-abc123 - imageUrl: - type: string - description: 根据 `image -> tbl_attachments` 自动解析出的图片文件流链接 - imageAttachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - sortOrder: - type: integer - example: 1 - example: - enum: enabled - description: 启用 - image: ATT-1743037200000-abc123 - imageUrl: https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/enabled.png - imageAttachment: - attachments_id: ATT-1743037200000-abc123 - attachments_filename: enabled.png - sortOrder: 1 - DictionaryRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - system_dict_id: - description: "字典业务 ID" - type: string - dict_name: - description: "字典名称,当前按全局唯一维护" - type: string - dict_word_is_enabled: - description: "字典是否启用" - type: boolean - dict_word_parent_id: - description: "父级字典业务 ID" - type: string - dict_word_remark: - description: "备注" - type: string - items: - type: array - items: - $ref: '#/components/schemas/DictionaryItem' - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: y3qk5cuirz515d6 - system_dict_id: DICT-1774599144591-hAEFQj - dict_name: 类型-发现页菜单 - dict_word_is_enabled: true - dict_word_parent_id: '' - dict_word_remark: 首页菜单字典 - items: - - enum: UT1 - description: 每日资讯 - image: ATT-1743037200000-abc123 - imageUrl: https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/news.png - sortOrder: 1 - created: '2026-03-28 07:20:00.000Z' - updated: '2026-03-29 08:00:00.000Z' - DictionaryListRequest: - type: object - properties: - keyword: - type: string - description: 对 `dict_name` 的模糊搜索关键字 - example: 状态 - DictionaryDetailRequest: - type: object - required: [dict_name] - properties: - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - DictionaryMutationRequest: - type: object - required: [dict_name, items] - properties: - original_dict_name: - type: string - description: 更新时用于定位原始记录;新增时可不传 - example: 用户状态 - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - dict_word_is_enabled: - type: boolean - description: "字典是否启用" - example: true - dict_word_parent_id: - type: string - description: "父级字典业务 ID" - example: '' - dict_word_remark: - type: string - description: "备注" - example: 系统状态字典 - items: - type: array - minItems: 1 - description: 每项会分别序列化写入 `dict_word_enum`、`dict_word_description`、`dict_word_image`、`dict_word_sort_order` - items: - $ref: '#/components/schemas/DictionaryItem' - DictionaryDeleteRequest: - type: object - required: [dict_name] - properties: - dict_name: - type: string - description: "字典名称,当前按全局唯一维护" - example: 用户状态 - AttachmentRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - attachments_id: - description: "附件业务 ID" - type: string - attachments_link: - type: string - description: PocketBase 实际存储的文件名 - attachments_url: - type: string - description: 附件文件流访问链接 - attachments_download_url: - type: string - description: 附件下载链接 - attachments_filename: - description: "原始文件名" - type: string - attachments_filetype: - description: "文件类型 / MIME" - type: string - attachments_size: - description: "文件大小" - type: number - attachments_owner: - description: "上传者业务标识" - type: string - attachments_md5: - description: "文件 MD5" - type: string - attachments_ocr: - description: "OCR 识别结果" - type: string - attachments_status: - description: "附件状态" - type: string - attachments_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: a1b2c3d4e5f6g7h - attachments_id: ATT-1743037200000-abc123 - attachments_link: enabled.png - attachments_url: https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/enabled.png - attachments_download_url: https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/enabled.png?download=1 - attachments_filename: enabled.png - attachments_filetype: image/png - attachments_size: 24576 - attachments_owner: app_momo - attachments_md5: 4b825dc642cb6eb9a060e54bf8d69288 - attachments_ocr: '' - attachments_status: active - attachments_remark: 字典图标 - created: '2026-03-28 07:20:00.000Z' - updated: '2026-03-29 08:00:00.000Z' - AttachmentListRequest: - type: object - properties: - keyword: - type: string - description: 对 `attachments_id`、`attachments_filename` 的模糊搜索关键字 - example: 手册 - status: - type: string - description: 按附件状态过滤 - example: active - AttachmentDetailRequest: - type: object - required: [attachments_id] - properties: - attachments_id: - type: string - description: "附件业务 ID" - example: ATT-1743037200000-abc123 - AttachmentUploadRequest: - type: object - required: [attachments_link] - properties: - attachments_link: - type: string - format: binary - description: 要上传到 `tbl_attachments` 的单个文件 - attachments_filename: - type: string - description: 原始文件名;不传时可由前端直接使用文件名 - attachments_filetype: - type: string - description: 文件 MIME 类型 - attachments_size: - type: number - description: 文件大小 - attachments_md5: - description: "文件 MD5" - type: string - attachments_ocr: - description: "OCR 识别结果" - type: string - attachments_status: - type: string - description: "附件状态" - example: active - attachments_remark: - description: "备注" - type: string - DocumentRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - document_id: - description: "文档业务 ID" - type: string - document_create: - type: string - description: 文档创建时间,由数据库自动生成 - document_effect_date: - description: "文档生效日期" - type: string - document_expiry_date: - description: "文档到期日期" - type: string - document_type: - type: string - description: 多选时按 `system_dict_id@dict_word_enum|...` 保存 - document_title: - description: "文档标题" - type: string - document_subtitle: - description: "文档副标题" - type: string - document_summary: - description: "文档摘要" - type: string - document_content: - description: "正文内容,保存 Markdown" - type: string - document_image: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_image_ids: - type: array - description: "`document_image` 解析后的附件 id 列表" - items: - type: string - document_image_urls: - type: array - description: "根据 `document_image -> tbl_attachments` 自动解析出的图片文件流链接列表" - items: - type: string - document_image_url: - type: string - description: "兼容字段,返回第一张图片的文件流链接" - document_image_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_image_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_video: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_video_ids: - type: array - description: "`document_video` 解析后的附件 id 列表" - items: - type: string - document_video_urls: - type: array - description: "根据 `document_video -> tbl_attachments` 自动解析出的视频文件流链接列表" - items: - type: string - document_video_url: - type: string - description: "兼容字段,返回第一个视频的文件流链接" - document_video_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_video_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_file: - type: string - description: "关联多个 `attachments_id`,底层使用 `|` 分隔保存" - document_file_ids: - type: array - description: "`document_file` 解析后的附件 id 列表" - items: - type: string - document_file_urls: - type: array - description: "根据 `document_file -> tbl_attachments` 自动解析出的文件流链接列表" - items: - type: string - document_file_url: - type: string - description: "兼容字段,返回第一个文件的文件流链接" - document_file_attachments: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - document_file_attachment: - anyOf: - - $ref: '#/components/schemas/AttachmentRecord' - - type: 'null' - document_owner: - type: string - description: 上传者 openid - document_relation_model: - description: "关联机型 / 模型标识" - type: string - document_keywords: - type: string - description: 固定字典多选字段,使用 `|` 分隔 - document_share_count: - description: "分享次数" - type: number - document_download_count: - description: "下载次数" - type: number - document_favorite_count: - description: "收藏次数" - type: number - document_status: - type: string - description: 文档状态,仅允许 `有效` 或 `过期`,由系统根据生效日期和到期日期自动计算;当两者都为空时默认 `有效` - document_embedding_status: - description: "文档嵌入状态" - type: string - document_embedding_error: - description: "文档嵌入错误原因" - type: string - document_embedding_lasttime: - description: "最后一次嵌入更新时间" - type: string - document_vector_version: - description: "向量版本号 / 模型名称" - type: string - document_product_categories: - type: string - description: 固定字典多选字段,使用 `|` 分隔 - document_application_scenarios: - type: string - description: 固定字典多选字段,使用 `|` 分隔 - document_hotel_type: - type: string - description: 固定字典多选字段,使用 `|` 分隔 - document_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: docpb_001 - document_id: DOC-1774677099775-WtHUaJ - document_create: '2026-03-28 07:20:00.000Z' - document_effect_date: '2026-03-28' - document_expiry_date: '2027-03-28' - document_type: DICT-1774599144591-hAEFQj@UT1 - document_title: 智能化重构补记行业价值新链条 - document_subtitle: 每日资讯 - document_summary: 文档摘要示例 - document_content: '# 正文内容' - document_image: ATT-1743037200000-abc123|ATT-1743037200001-def456 - document_image_ids: - - ATT-1743037200000-abc123 - document_image_urls: - - https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/news.png - document_image_url: https://bai-api.blv-oa.com/api/files/tbl_attachments/a1/news.png - document_video: ATT-1743037200002-ghi789 - document_video_ids: - - ATT-1743037200002-ghi789 - document_video_urls: - - https://bai-api.blv-oa.com/api/files/tbl_attachments/a2/demo.mp4 - document_video_url: https://bai-api.blv-oa.com/api/files/tbl_attachments/a2/demo.mp4 - document_file: ATT-1743037200003-jkl012 - document_file_ids: - - ATT-1743037200003-jkl012 - document_file_urls: - - https://bai-api.blv-oa.com/api/files/tbl_attachments/a3/manual.pdf - document_file_url: https://bai-api.blv-oa.com/api/files/tbl_attachments/a3/manual.pdf - document_owner: app_momo - document_relation_model: OR1 - document_keywords: 酒店|智能化 - document_share_count: 3 - document_download_count: 12 - document_favorite_count: 5 - document_status: 有效 - document_embedding_status: succeed - document_embedding_error: '' - document_embedding_lasttime: '2026-03-29' - document_vector_version: text-embedding-3-large - document_product_categories: OR1|AZ4 - document_application_scenarios: 每日资讯 - document_hotel_type: 高端酒店 - document_remark: 文档备注 - created: '2026-03-28 07:20:00.000Z' - updated: '2026-03-29 08:00:00.000Z' - DocumentListRequest: - type: object - properties: - keyword: - type: string - description: 对 `document_id`、`document_title`、`document_subtitle`、`document_summary`、`document_keywords` 的模糊搜索关键字 - example: 安装 - status: - type: string - example: active - document_type: - type: string - description: 支持按存储值过滤;多选时格式为 `system_dict_id@dict_word_enum|...` - example: 说明书 - DocumentDetailRequest: - type: object - required: [document_id] - properties: - document_id: - type: string - description: "文档业务 ID" - example: DOC-1743037200000-abc123 - DocumentMutationRequest: - type: object - required: [document_title, document_type] - properties: - document_id: - type: string - description: 创建时可不传,由服务端自动生成;更新时必填 - example: DOC-1743037200000-abc123 - document_effect_date: - type: string - description: 支持 `YYYY-MM-DD` 或 PocketBase 可识别日期时间字符串 - example: 2026-03-27 - document_expiry_date: - type: string - description: 支持 `YYYY-MM-DD` 或 PocketBase 可识别日期时间字符串 - example: 2027-03-27 - document_type: - type: string - description: 必填;前端显示为字典项描述,存库时按 `system_dict_id@dict_word_enum|...` 保存 - document_title: - description: "文档标题" - type: string - document_subtitle: - description: "文档副标题" - type: string - document_summary: - description: "文档摘要" - type: string - document_content: - description: "正文内容,保存 Markdown" - type: string - document_image: - oneOf: - - type: string - description: 多个图片附件 id 使用 `|` 分隔 - - type: array - items: - type: string - description: 图片附件 id 列表;支持数组或 `|` 分隔字符串 - document_video: - oneOf: - - type: string - description: 多个视频附件 id 使用 `|` 分隔 - - type: array - items: - type: string - description: 视频附件 id 列表;支持数组或 `|` 分隔字符串 - document_file: - oneOf: - - type: string - description: 多个文件附件 id 使用 `|` 分隔 - - type: array - items: - type: string - description: 文件附件 id 列表;支持数组或 `|` 分隔字符串 - document_relation_model: - description: "关联机型 / 模型标识" - type: string - document_keywords: - type: string - description: 从 `文档-关键词` 字典多选后使用 `|` 分隔保存 - document_share_count: - description: "分享次数" - type: number - document_download_count: - description: "下载次数" - type: number - document_favorite_count: - description: "收藏次数" - type: number - document_status: - type: string - description: 文档状态,仅允许 `有效` 或 `过期`,由系统根据生效日期和到期日期自动计算;当两者都为空时默认 `有效` - document_embedding_status: - description: "文档嵌入状态" - type: string - document_embedding_error: - description: "文档嵌入错误原因" - type: string - document_embedding_lasttime: - description: "最后一次嵌入更新时间" - type: string - document_vector_version: - description: "向量版本号 / 模型名称" - type: string - document_product_categories: - type: string - description: 从 `文档-产品关联文档` 字典多选后使用 `|` 分隔保存 - document_application_scenarios: - type: string - description: 从 `文档-筛选依据` 字典多选后使用 `|` 分隔保存 - document_hotel_type: - type: string - description: 从 `文档-适用场景` 字典多选后使用 `|` 分隔保存 - document_remark: - description: "备注" - type: string - DocumentDeleteRequest: - type: object - required: [document_id] - properties: - document_id: - type: string - description: "文档业务 ID" - example: DOC-1743037200000-abc123 - DocumentHistoryRecord: - type: object - properties: - pb_id: - description: "PocketBase 记录主键 id" - type: string - doh_id: - description: "文档操作历史业务 ID" - type: string - doh_document_id: - description: "关联文档业务 ID" - type: string - doh_operation_type: - description: "操作类型" - type: string - doh_user_id: - description: "操作人业务 ID" - type: string - doh_current_count: - description: "本次操作对应次数" - type: number - doh_remark: - description: "备注" - type: string - created: - description: "记录创建时间" - type: string - updated: - description: "记录更新时间" - type: string - example: - pb_id: histpb_001 - doh_id: DOH-1774677099775-WtHUaJ - doh_document_id: DOC-1774677099775-WtHUaJ - doh_operation_type: update - doh_user_id: app_momo - doh_current_count: 1 - doh_remark: 更新文档 - created: '2026-03-29 08:00:00.000Z' - updated: '2026-03-29 08:00:00.000Z' - DocumentHistoryListRequest: - type: object - properties: - document_id: - type: string - description: 可选;传入时仅查询指定文档的操作历史 - example: DOC-1743037200000-abc123 -paths: - /pb/api/system/test-helloworld: - post: - tags: [系统] - summary: HelloWorld 测试接口 - responses: - '200': - description: 成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/HelloWorldData' - /pb/api/system/health: - post: - tags: [系统] - summary: 健康检查 - responses: - '200': - description: 成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/HealthData' - /pb/api/system/users-count: - post: - tags: [系统] - summary: 查询用户总数 - description: 统计 `tbl_auth_users` 集合中的记录总数,并返回一个数值。 - responses: - '200': - description: 成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/UsersCountData' - /pb/api/system/refresh-token: - post: - tags: [系统] - summary: 刷新系统认证 token - description: | - 当前实现支持两种刷新路径: - 1) 若 `Authorization` 对应 token 仍有效:直接按当前 auth record 续签(不调用微信接口)。 - 2) 若 token 已过期:仅在 body 提供 `users_wx_code` 时才走微信 code 重新签发。 - 返回体仅包含新的 `token`,不返回完整登录用户信息。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/SystemRefreshTokenRequest' - responses: - '200': - description: 刷新成功(返回精简 token) - content: - application/json: - schema: - allOf: - - $ref: '#/components/schemas/ApiResponse' - - type: object - properties: - token: - type: string - description: 新签发的 PocketBase 原生 auth token - example: - statusCode: 200 - errMsg: 刷新成功 - data: {} - token: eyJhbGciOi... - '400': - description: 参数错误或微信侧身份换取失败 - '401': - description: token 无效/已过期,且未提供 users_wx_code - '404': - description: 用户不存在 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/wechat/login: - post: - tags: [微信认证] - summary: 微信登录/注册合一 - description: | - 使用微信 code 换取微信侧 openid,并写入统一身份字段 `tbl_auth_users.openid`。 - 若 `tbl_auth_users` 中不存在对应用户则自动创建 auth record,随后返回 PocketBase 原生 auth token。 - 首次注册创建时会写入 `users_idtype = WeChat`。 - 首次注册创建时,`users_level` 默认保持为空,不自动写入会员等级。 - 返回的 `token` 可直接用于 PocketBase SDK 与当前 hooks 接口调用。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/WechatLoginRequest' - responses: - '200': - description: 登录或注册成功 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseAuthResponse' - '400': - description: 参数错误或微信侧身份换取失败 - '401': - description: PocketBase 原生认证失败 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - '500': - description: 保存 auth 用户失败或服务端内部错误 - /pb/api/platform/register: - post: - tags: [平台认证] - summary: 平台用户注册 - description: | - 创建平台用户 auth record。 - 服务端会自动生成 GUID 并写入统一身份字段 `openid`,同时写入 `users_idtype = ManagePlatform`。 - 前端以 `users_phone + password/passwordConfirm` 注册,但服务端仍会创建 PocketBase 原生 auth 用户。 - 首次注册创建时,`users_level` 默认保持为空,不自动写入会员等级。 - 注册成功后直接返回 PocketBase 原生 auth token。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PlatformRegisterRequest' - responses: - '200': - description: 注册成功 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseAuthResponse' - '400': - description: 参数错误或手机号已存在 - '500': - description: GUID 生成失败、auth identity 缺失或保存用户失败 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/platform/login: - post: - tags: [平台认证] - summary: 平台用户登录 - description: | - 前端使用平台注册时保存的 `邮箱或手机号 + password` 登录。 - 仅允许 `users_idtype = ManagePlatform` 的用户通过该接口登录。 - 服务端会根据 `login_account` 自动判断邮箱或手机号,并定位平台用户,再使用该用户的 PocketBase 原生 identity(当前为 `email`)执行原生 password auth。 - 返回体中的 `user.users_level_name` 为服务端按“数据-会员等级”字典实时解析后的等级名称。 - 登录成功后直接返回 PocketBase 原生 auth token。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PlatformLoginRequest' - example: - login_account: '13509214696' - password: Momo123456 - responses: - '200': - description: 登录成功 - content: - application/json: - schema: - $ref: '#/components/schemas/PocketBaseAuthResponse' - example: - statusCode: 200 - errMsg: 登录成功 - data: - status: login_success - is_info_complete: false - user: - pb_id: vtukf6agem2xbcv - users_id: '' - users_idtype: ManagePlatform - users_name: momo - users_phone: '13509214696' - users_phone_masked: '135****4696' - users_status: '' - users_rank_level: 0 - users_auth_type: 0 - users_type: 注册用户 - users_picture: '' - openid: app_momo - company_id: '' - users_parent_id: '' - users_promo_code: '' - usergroups_id: '' - company: null - created: '' - updated: '' - token: eyJhbGciOi... - '400': - description: 参数错误、密码错误或用户类型不匹配 - '404': - description: 平台用户不存在 - '500': - description: 平台用户缺少原生登录 identity 或服务端内部错误 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/wechat/profile: - post: - tags: [微信认证] - summary: 更新微信用户资料 - description: | - 基于当前 `Authorization` 对应 auth record 中的统一 `openid` 定位当前微信用户。 - 当前接口按“非空字段增量更新”处理资料完善。 - 若传入 `users_phone_code`,优先调用微信接口换取真实手机号; - 若未传 `users_phone_code` 但传入 `users_phone`,则直接写入手机号; - 未传或传空的字段不会清空数据库已有值。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/WechatProfileRequest' - responses: - '200': - description: 更新成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/WechatProfileResponseData' - '401': - description: token 无效或当前 auth record 缺少统一身份字段 openid - '400': - description: 参数错误、手机号已被注册、微信手机号换取失败或资料更新失败 - /pb/api/dictionary/list: - post: - tags: [字典管理] - summary: 查询字典列表 - description: | - 公开读接口,无需 token。 - 支持按 `dict_name` 模糊搜索,返回字典全量信息,并将三个聚合字段组装为 `items`。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryListRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DictionaryRecord' - '415': - description: 请求体必须为 application/json - /pb/api/dictionary/detail: - post: - tags: [字典管理] - summary: 查询指定字典 - description: | - 公开读接口,无需 token。 - 按唯一键 `dict_name` 查询单条字典,并返回组装后的 `items`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryDetailRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: 参数错误 - '404': - description: 未找到对应字典 - '415': - description: 请求体必须为 application/json - /pb/api/dictionary/create: - post: - tags: [字典管理] - summary: 新增字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - `system_dict_id` 由服务端自动生成;`dict_name` 必须唯一; - `items` 会分别序列化写入 `dict_word_enum`、`dict_word_description`、`dict_word_image`、`dict_word_sort_order` 四个字段。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryMutationRequest' - responses: - '200': - description: 新增成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: 参数错误或 dict_name 已存在 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/dictionary/update: - post: - tags: [字典管理] - summary: 修改字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 根据 `original_dict_name`(未传时回退为 `dict_name`)定位原记录并更新。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryMutationRequest' - responses: - '200': - description: 修改成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DictionaryRecord' - '400': - description: 参数错误或 dict_name 冲突 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到待修改字典 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/dictionary/delete: - post: - tags: [字典管理] - summary: 删除字典 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `dict_name` 真删除对应记录。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DictionaryDeleteRequest' - responses: - '200': - description: 删除成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - dict_name: - description: "字典名称,当前按全局唯一维护" - type: string - '400': - description: 参数错误或删除失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到待删除字典 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/attachment/list: - post: - tags: [附件管理] - summary: 查询附件列表 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 支持按 `attachments_id`、`attachments_filename` 模糊搜索,并可按 `attachments_status` 过滤。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentListRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/AttachmentRecord' - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '415': - description: 请求体必须为 application/json - /pb/api/attachment/detail: - post: - tags: [附件管理] - summary: 查询附件详情 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `attachments_id` 查询单条附件,并返回 PocketBase 文件流链接与下载链接。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentDetailRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/AttachmentRecord' - '400': - description: 参数错误 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到对应附件 - '415': - description: 请求体必须为 application/json - /pb/api/attachment/upload: - post: - tags: [附件管理] - summary: 上传附件 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 使用 `multipart/form-data` 上传单个文件到 `tbl_attachments`,服务端会自动生成 `attachments_id`, - 并返回可直接访问的 PocketBase 文件流链接。 - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/AttachmentUploadRequest' - responses: - '200': - description: 上传成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/AttachmentRecord' - '400': - description: 参数错误、缺少文件或附件保存失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - /pb/api/attachment/delete: - post: - tags: [附件管理] - summary: 删除附件 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `attachments_id` 真删除附件;若附件已被 `tbl_document.document_image`、`document_video` 或 `document_file` 引用,则拒绝删除。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AttachmentDetailRequest' - responses: - '200': - description: 删除成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - attachments_id: - description: "附件业务 ID" - type: string - '400': - description: 参数错误、附件已被文档引用或删除失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到待删除附件 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/document/list: - post: - tags: [文档管理] - summary: 查询文档列表 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 支持按标题、摘要、关键词等字段模糊搜索,并可按 `document_status`、`document_type` 过滤。 - 返回结果会自动根据 `document_image`、`document_video`、`document_file` 中的多个 `attachments_id` 关联 `tbl_attachments`, - 额外补充 `document_image_urls`、`document_video_urls`、`document_file_urls` 以及对应附件对象数组。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentListRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DocumentRecord' - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '415': - description: 请求体必须为 application/json - /pb/api/document/detail: - post: - tags: [文档管理] - summary: 查询文档详情 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 查询单条文档,并返回与附件表联动解析后的多文件流链接。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentDetailRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: 参数错误 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到对应文档 - '415': - description: 请求体必须为 application/json - /pb/api/document/create: - post: - tags: [文档管理] - summary: 新增文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - `document_id` 可选;未传时服务端自动生成。 - `document_title`、`document_type` 为必填;其余字段均允许为空。 - `document_image`、`document_video`、`document_file` 支持传入多个已存在于 `tbl_attachments` 的 `attachments_id`。 - 成功后会同步写入一条 `tbl_document_operation_history`,操作类型为 `create`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentMutationRequest' - responses: - '200': - description: 新增成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: 参数错误、附件不存在或文档创建失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/document/update: - post: - tags: [文档管理] - summary: 修改文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 定位现有文档并更新。 - `document_title`、`document_type` 为必填;其余字段均允许为空。 - 若传入 `document_image`、`document_video`、`document_file`,则支持多个 `attachments_id`,并会逐一校验是否存在。 - 成功后会同步写入一条 `tbl_document_operation_history`,操作类型为 `update`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentMutationRequest' - responses: - '200': - description: 修改成功 - content: - application/json: - schema: - description: "业务响应数据" - $ref: '#/components/schemas/DocumentRecord' - '400': - description: 参数错误、附件不存在或修改失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到待修改文档 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/document/delete: - post: - tags: [文档管理] - summary: 删除文档 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 按 `document_id` 真删除文档,并在删除前同步写入一条 `tbl_document_operation_history`,操作类型为 `delete`。 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentDeleteRequest' - responses: - '200': - description: 删除成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - document_id: - description: "文档业务 ID" - type: string - '400': - description: 参数错误或删除失败 - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '404': - description: 未找到待删除文档 - '415': - description: 请求体必须为 application/json - '429': - description: 重复请求过于频繁 - /pb/api/document-history/list: - post: - tags: [文档历史] - summary: 查询文档操作历史 - description: | - 仅允许 `ManagePlatform` 用户访问。 - 若 body 传入 `document_id`,则仅查询该文档的历史;否则返回全部文档操作历史,按创建时间倒序排列。 - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/DocumentHistoryListRequest' - responses: - '200': - description: 查询成功 - content: - application/json: - schema: - description: "业务响应数据" - type: object - properties: - items: - type: array - items: - $ref: '#/components/schemas/DocumentHistoryRecord' - '401': - description: token 无效或已过期 - '403': - description: 非 ManagePlatform 用户无权访问 - '415': - description: 请求体必须为 application/json diff --git a/script/package.json b/script/package.json index 76a50b4..9332a01 100644 --- a/script/package.json +++ b/script/package.json @@ -14,6 +14,7 @@ "migrate:add-is-delete-field": "node pocketbase.add-is-delete-field.js", "migrate:apply-soft-delete-rules": "node pocketbase.apply-soft-delete-rules.js", "migrate:ensure-cart-order-autogen-id": "node pocketbase.ensure-cart-order-autogen-id.js", + "migrate:cart-active-unique-index": "node pocketbase.cart-active-unique-index.js", "migrate:product-params-array": "node migrate-product-parameters-to-array.js", "migrate:add-product-function-field": "node add-product-function-field.js", "test:company-native-api": "node test-tbl-company-native-api.js", diff --git a/script/pocketbase.cart-active-unique-index.js b/script/pocketbase.cart-active-unique-index.js new file mode 100644 index 0000000..4575c3f --- /dev/null +++ b/script/pocketbase.cart-active-unique-index.js @@ -0,0 +1,145 @@ +import { createRequire } from 'module'; +import PocketBase from 'pocketbase'; + +const require = createRequire(import.meta.url); + +let runtimeConfig = {}; +try { + runtimeConfig = require('../pocket-base/bai_api_pb_hooks/bai_api_shared/config/runtime.js'); +} catch (_error) { + runtimeConfig = {}; +} + +const PB_URL = String(process.env.PB_URL || 'https://bai-api.blv-oa.com/pb').replace(/\/+$/, ''); +const AUTH_TOKEN = process.env.POCKETBASE_AUTH_TOKEN || runtimeConfig.POCKETBASE_AUTH_TOKEN || ''; +const COLLECTION = 'tbl_cart'; +const ACTIVE_UNIQUE_INDEX = 'CREATE UNIQUE INDEX idx_tbl_cart_owner_product_active_unique ON tbl_cart (cart_owner, cart_product_id) WHERE is_delete = 0'; +const TEMP_RULE = '@request.auth.id != ""'; + +if (!AUTH_TOKEN) { + console.error('Missing POCKETBASE_AUTH_TOKEN'); + process.exit(1); +} + +const pb = new PocketBase(PB_URL); + +function buildCollectionPayload(base, overrides = {}) { + const rawFields = Array.isArray(base.fields) ? base.fields : []; + const safeFields = rawFields.filter((field) => field && field.name !== 'id'); + + return { + name: base.name, + type: base.type, + listRule: Object.prototype.hasOwnProperty.call(overrides, 'listRule') ? overrides.listRule : base.listRule, + viewRule: Object.prototype.hasOwnProperty.call(overrides, 'viewRule') ? overrides.viewRule : base.viewRule, + createRule: Object.prototype.hasOwnProperty.call(overrides, 'createRule') ? overrides.createRule : base.createRule, + updateRule: Object.prototype.hasOwnProperty.call(overrides, 'updateRule') ? overrides.updateRule : base.updateRule, + deleteRule: Object.prototype.hasOwnProperty.call(overrides, 'deleteRule') ? overrides.deleteRule : base.deleteRule, + fields: safeFields, + indexes: Object.prototype.hasOwnProperty.call(overrides, 'indexes') ? overrides.indexes : (base.indexes || []), + }; +} + +async function setTempRules(collection) { + const payload = buildCollectionPayload(collection, { + listRule: TEMP_RULE, + viewRule: TEMP_RULE, + createRule: TEMP_RULE, + updateRule: TEMP_RULE, + deleteRule: TEMP_RULE, + }); + await pb.collections.update(collection.id, payload); +} + +async function restoreRules(collection) { + await pb.collections.update(collection.id, buildCollectionPayload(collection)); +} + +function groupKey(record) { + const owner = String(record.cart_owner || '').trim(); + const product = String(record.cart_product_id || '').trim(); + return `${owner}||${product}`; +} + +async function dedupeActiveRows() { + const rows = await pb.collection(COLLECTION).getFullList({ + filter: 'is_delete = 0', + sort: '-updated', + fields: 'id,cart_owner,cart_product_id,is_delete,updated', + }); + + const groups = new Map(); + for (const row of rows) { + const key = groupKey(row); + if (!groups.has(key)) groups.set(key, []); + groups.get(key).push(row); + } + + let duplicateGroups = 0; + let softDeleted = 0; + + for (const [, items] of groups) { + if (items.length <= 1) continue; + duplicateGroups += 1; + + const keep = items[0]; + for (let i = 1; i < items.length; i += 1) { + const row = items[i]; + await pb.collection(COLLECTION).update(row.id, { is_delete: 1 }); + softDeleted += 1; + } + + console.log(`dedupe group keep=${keep.id} deleted=${items.length - 1}`); + } + + return { total: rows.length, duplicateGroups, softDeleted }; +} + +async function applyActiveUniqueIndex() { + const collection = await pb.collections.getOne(COLLECTION); + const indexes = Array.isArray(collection.indexes) ? collection.indexes.slice() : []; + if (!indexes.includes(ACTIVE_UNIQUE_INDEX)) { + indexes.push(ACTIVE_UNIQUE_INDEX); + } + + const payload = buildCollectionPayload(collection, { indexes }); + await pb.collections.update(collection.id, payload); + + const latest = await pb.collections.getOne(COLLECTION); + const ok = Array.isArray(latest.indexes) && latest.indexes.includes(ACTIVE_UNIQUE_INDEX); + if (!ok) { + throw new Error('Active unique index was not applied.'); + } +} + +async function main() { + pb.authStore.save(AUTH_TOKEN, null); + console.log(`connect ${PB_URL}`); + + const original = await pb.collections.getOne(COLLECTION); + + try { + await setTempRules(original); + const dedupe = await dedupeActiveRows(); + console.log(JSON.stringify(dedupe, null, 2)); + } finally { + const latest = await pb.collections.getOne(COLLECTION); + const restoreBase = { + ...latest, + listRule: original.listRule, + viewRule: original.viewRule, + createRule: original.createRule, + updateRule: original.updateRule, + deleteRule: original.deleteRule, + }; + await restoreRules(restoreBase); + } + + await applyActiveUniqueIndex(); + console.log('active unique index applied'); +} + +main().catch((error) => { + console.error('migration failed', error?.response || error?.message || error); + process.exitCode = 1; +}); diff --git a/script/pocketbase.cart-order.js b/script/pocketbase.cart-order.js index e0c44de..4431db6 100644 --- a/script/pocketbase.cart-order.js +++ b/script/pocketbase.cart-order.js @@ -48,11 +48,11 @@ async function buildCollections() { updateRule: `${OWNER_AUTH_RULE} && ${CART_OWNER_MATCH_RULE}`, deleteRule: `${OWNER_AUTH_RULE} && ${CART_OWNER_MATCH_RULE}`, fields: [ - { name: 'cart_id', type: 'text', required: true, autogeneratePattern: 'CART-[0-9]{13}-[A-Za-z0-9]{6}' }, + { name: 'cart_id', type: 'text', required: false, autogeneratePattern: 'CART-[0-9]{13}-[A-Za-z0-9]{6}' }, { name: 'cart_number', type: 'text', required: false }, { name: 'cart_create', type: 'autodate', onCreate: true, onUpdate: false }, { name: 'cart_owner', type: 'text', required: true }, - { name: 'cart_product_id', type: 'relation', required: true, collectionId: productCollectionId, maxSelect: 1, cascadeDelete: false }, + { name: 'cart_product_id', type: 'relation', required: false, collectionId: productCollectionId, maxSelect: 1, cascadeDelete: false }, { name: 'cart_product_quantity', type: 'number', required: false }, { name: 'cart_status', type: 'text', required: false }, { name: 'cart_at_price', type: 'number', required: false }, @@ -61,6 +61,7 @@ async function buildCollections() { ], indexes: [ 'CREATE UNIQUE INDEX idx_tbl_cart_cart_id ON tbl_cart (cart_id)', + 'CREATE UNIQUE INDEX idx_tbl_cart_owner_product_active_unique ON tbl_cart (cart_owner, cart_product_id) WHERE is_delete = 0', 'CREATE INDEX idx_tbl_cart_cart_number ON tbl_cart (cart_number)', 'CREATE INDEX idx_tbl_cart_cart_owner ON tbl_cart (cart_owner)', 'CREATE INDEX idx_tbl_cart_cart_product_id ON tbl_cart (cart_product_id)', diff --git a/script/pocketbase.ensure-cart-order-autogen-id.js b/script/pocketbase.ensure-cart-order-autogen-id.js index a054ab1..a9ad3f3 100644 --- a/script/pocketbase.ensure-cart-order-autogen-id.js +++ b/script/pocketbase.ensure-cart-order-autogen-id.js @@ -57,11 +57,13 @@ const TARGETS = [ collectionName: 'tbl_cart', fieldName: 'cart_id', autogeneratePattern: 'CART-[0-9]{13}-[A-Za-z0-9]{6}', + required: false, }, { collectionName: 'tbl_order', fieldName: 'order_id', autogeneratePattern: 'ORDER-[0-9]{13}-[A-Za-z0-9]{6}', + required: true, }, ]; @@ -128,7 +130,7 @@ async function ensureAutoGenerateField(target) { return normalizeFieldPayload(field, { type: 'text', - required: true, + required: typeof target.required === 'boolean' ? target.required : true, autogeneratePattern: target.autogeneratePattern, }); }); diff --git a/script/pocketbase.product-list.js b/script/pocketbase.product-list.js index 415d953..4aabe2c 100644 --- a/script/pocketbase.product-list.js +++ b/script/pocketbase.product-list.js @@ -35,6 +35,7 @@ const collections = [ { name: 'prod_list_id', type: 'text', required: true }, { name: 'prod_list_name', type: 'text', required: true }, { name: 'prod_list_modelnumber', type: 'text' }, + { name: 'prod_list_barcode', type: 'text' }, { name: 'prod_list_icon', type: 'text' }, { name: 'prod_list_description', type: 'text' }, { name: 'prod_list_feature', type: 'text' },