Commit 6c31a476 authored by liguangyu06's avatar liguangyu06
Browse files

同步基础管理与统计报表用例文档,并更新 Playwright 脚本与 PO。

对齐 CSV/MD/测试点与现网列名及组合查询;补充厂商资质子 Tab 与基础模块复跑脚本。
parent aa8987ce
...@@ -79,7 +79,7 @@ scripts/run-ci.mjs Jenkins / 定时执行入口 ...@@ -79,7 +79,7 @@ scripts/run-ci.mjs Jenkins / 定时执行入口
| `pages/` | 业务操作、取数/快照(如 `snapshotList`) | 用例主断言、流程编排、裸密码 | | `pages/` | 业务操作、取数/快照(如 `snapshotList`) | 用例主断言、流程编排、裸密码 |
| `tests/` | 调用 Page 方法 + **`expect` 断言业务结果** | `page.locator(...)`(反例探测除外)、访问 `locators` | | `tests/` | 调用 Page 方法 + **`expect` 断言业务结果** | `page.locator(...)`(反例探测除外)、访问 `locators` |
厂商管理样板:`tests/spd/vendor-query.spec.ts` + `tests/spd/helpers/vendor-assert.helper.ts`(断言在用例;PO 无 `expect`)。 厂商管理样板:`tests/spd/vendor-query.spec.ts`(9 条,与 `testcase/…厂商查询…csv` 一致)+ `pages/spd/vendor-query.page.ts`(列设置见 `pages/spd/helpers/column-settings.helper.ts`)+ `tests/spd/helpers/vendor-assert.helper.ts`(列表/空态断言在用例层)。
**智能等待**:查询按钮 loading、Ant Spin、表体有行/空态,统一走 `core/smart-wait.ts`。动画沉降用 `waitUiSettle`(双 rAF),不要在 Page 里写 `waitForTimeout`。 **智能等待**:查询按钮 loading、Ant Spin、表体有行/空态,统一走 `core/smart-wait.ts`。动画沉降用 `waitUiSettle`(双 rAF),不要在 Page 里写 `waitForTimeout`。
......
...@@ -202,10 +202,19 @@ export class BasePage { ...@@ -202,10 +202,19 @@ export class BasePage {
return retryAction(async () => (await locator.innerText()).trim(), { label: '读取文本' }); return retryAction(async () => (await locator.innerText()).trim(), { label: '读取文本' });
} }
/** 搜索条作用域:有 iframe 用首个 iframe,否则用主文档。 */ /** 搜索条作用域:仅当 iframe 内存在业务筛选表单时才用 iframe,避免误进空 iframe。 */
async queryScope(): Promise<FilterScope> { async queryScope(): Promise<FilterScope> {
const frames = this.page.locator('iframe'); const frames = this.page.locator('iframe');
if ((await frames.count().catch(() => 0)) > 0) return this.page.frameLocator('iframe').first(); const frameCount = await frames.count().catch(() => 0);
for (let i = 0; i < frameCount; i += 1) {
const frame = this.page.frameLocator(`iframe >> nth=${i}`);
const hasForm = await frame
.locator('.ant-form-item, .ant-form')
.first()
.isVisible()
.catch(() => false);
if (hasForm) return frame;
}
return this.page; return this.page;
} }
...@@ -236,7 +245,16 @@ export class BasePage { ...@@ -236,7 +245,16 @@ export class BasePage {
await this.expandFiltersIfCollapsed(scope); await this.expandFiltersIfCollapsed(scope);
for (const field of fields) { for (const field of fields) {
const item = await this.resolveFilterItem(scope, field.label); const labels = field.aliases?.length ? [field.label, ...field.aliases] : [field.label];
let item: Locator | null = null;
let resolvedLabel = field.label;
for (const candidate of labels) {
item = await this.resolveFilterItem(scope, candidate);
if (item) {
resolvedLabel = candidate;
break;
}
}
if (!item) { if (!item) {
missing.push(field.label); missing.push(field.label);
if (options.skipMissing === false) { if (options.skipMissing === false) {
...@@ -245,16 +263,16 @@ export class BasePage { ...@@ -245,16 +263,16 @@ export class BasePage {
continue; continue;
} }
if (field.kind === 'select') { if (field.kind === 'select') {
await this.pickFirstOption(scope, item, field.label); await this.pickFirstOption(scope, item, resolvedLabel);
} else if (field.kind === 'dateRange') { } else if (field.kind === 'dateRange') {
await this.fillDateRange(scope, item, field.label); await this.fillDateRange(scope, item, resolvedLabel);
} else { } else {
const input = item.locator('input').first(); const input = item.locator('input').first();
await this.fill(input, field.value ?? '', `组合查询:${field.label}`, { await this.fill(input, field.value ?? '样', `组合查询:${resolvedLabel}`, {
fallbacks: [scope.getByPlaceholder(new RegExp(field.label)).first()], fallbacks: [scope.getByPlaceholder(new RegExp(resolvedLabel)).first()],
}); });
} }
applied.push(field.label); applied.push(resolvedLabel);
} }
logger.step(`组合查询:已填 ${applied.length}/${fields.length} 项,未找到 ${missing.join('、') || '无'}`); logger.step(`组合查询:已填 ${applied.length}/${fields.length} 项,未找到 ${missing.join('、') || '无'}`);
...@@ -284,21 +302,35 @@ export class BasePage { ...@@ -284,21 +302,35 @@ export class BasePage {
* 搜索条中的单个字段:按 label[for] 精确定位到同级控件容器。 * 搜索条中的单个字段:按 label[for] 精确定位到同级控件容器。
* antd 的 label for / 控件 id 一一对应,比 hasText 更可靠(避免「物料名称」误命中含同名文字的外层)。 * antd 的 label for / 控件 id 一一对应,比 hasText 更可靠(避免「物料名称」误命中含同名文字的外层)。
*/ */
protected filterLabelCandidates(label: string): string[] {
const aliasMap: Record<string, string[]> = {
进院供应商: ['进院供应商', '进院供应商名称', '销售商(自定义)', '销售商', '供应商'],
销售商: ['销售商', '销售商(自定义)', '销售商名称', '进院供应商', '供应商'],
供应商: ['供应商', '进院供应商', '销售商(自定义)', '销售商'],
};
const extra = aliasMap[label];
return extra ? [...new Set([label, ...extra])] : [label];
}
protected async resolveFilterItem(scope: FilterScope, label: string): Promise<Locator | null> { protected async resolveFilterItem(scope: FilterScope, label: string): Promise<Locator | null> {
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); for (const candidate of this.filterLabelCandidates(label)) {
const exactLabel = new RegExp(`^\\s*${escaped}\\s*$`); const escaped = candidate.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const labels = scope.locator('.ant-form-item label').filter({ hasText: exactLabel }); const exactLabel = new RegExp(`^\\s*${escaped}\\s*$`);
const count = await labels.count().catch(() => 0); const labels = scope.locator('.ant-form-item label').filter({ hasText: exactLabel });
for (let i = 0; i < count; i += 1) { const count = await labels.count().catch(() => 0);
const lab = labels.nth(i); for (let i = 0; i < count; i += 1) {
const id = await lab.getAttribute('for').catch(() => null); const lab = labels.nth(i);
if (!id) continue; const id = await lab.getAttribute('for').catch(() => null);
const item = scope.locator('.ant-form-item').filter({ has: scope.locator(`#${CSS_ESCAPE(id)}`) }).first(); if (!id) continue;
if (await item.isVisible().catch(() => false)) return item; const item = scope.locator('.ant-form-item').filter({ has: scope.locator(`#${CSS_ESCAPE(id)}`) }).first();
if (await item.isVisible().catch(() => false)) return item;
}
const fallback = scope
.locator('.ant-form-item')
.filter({ has: scope.locator('label', { hasText: exactLabel }) })
.first();
if (await fallback.isVisible().catch(() => false)) return fallback;
} }
// 退化:label 所在表单项(仅当 label 文本完全相等时)
const fallback = scope.locator('.ant-form-item').filter({ has: scope.locator('label', { hasText: exactLabel }) }).first();
if (await fallback.isVisible().catch(() => false)) return fallback;
return null; return null;
} }
...@@ -306,11 +338,33 @@ export class BasePage { ...@@ -306,11 +338,33 @@ export class BasePage {
* 打开下拉并取第一个可选项。浮层挂在**当前 scope 的 document.body**—— * 打开下拉并取第一个可选项。浮层挂在**当前 scope 的 document.body**——
* iframe 页面的浮层在 iframe 内,主页面查不到,因此 scope 必须传对。 * iframe 页面的浮层在 iframe 内,主页面查不到,因此 scope 必须传对。
*/ */
protected async activeSelectDropdown(scope: FilterScope): Promise<Locator> {
await expect
.poll(
async () => {
for (const root of [scope, this.page]) {
const panel = root.locator('.ant-select-dropdown:not(.ant-select-dropdown-hidden)').last();
if (await panel.isVisible().catch(() => false)) return true;
}
return false;
},
{ timeout: 15_000 },
)
.toBeTruthy();
for (const root of [scope, this.page]) {
const panel = root.locator('.ant-select-dropdown:not(.ant-select-dropdown-hidden)').last();
if (await panel.isVisible().catch(() => false)) return panel;
}
return scope.locator('.ant-select-dropdown:not(.ant-select-dropdown-hidden)').last();
}
protected async pickFirstOption(scope: FilterScope, item: Locator, label: string): Promise<string> { protected async pickFirstOption(scope: FilterScope, item: Locator, label: string): Promise<string> {
const dropdown = scope.locator('.ant-select-dropdown:not(.ant-select-dropdown-hidden)').last();
await this.click(item.locator('.ant-select-selector').first(), `组合查询:展开「${label}」`); await this.click(item.locator('.ant-select-selector').first(), `组合查询:展开「${label}」`);
const dropdown = await this.activeSelectDropdown(scope);
const option = dropdown.locator('.ant-select-item-option:not(.ant-select-item-option-disabled)').first(); const option = dropdown.locator('.ant-select-item-option:not(.ant-select-item-option-disabled)').first();
await option.waitFor({ state: 'visible', timeout: timeouts.expect }); await expect
.poll(async () => option.isVisible().catch(() => false), { timeout: timeouts.expect })
.toBeTruthy();
const text = ((await option.innerText().catch(() => '')) ?? '').replace(/\s/g, ''); const text = ((await option.innerText().catch(() => '')) ?? '').replace(/\s/g, '');
await this.click(option, `组合查询:选择「${label}」`); await this.click(option, `组合查询:选择「${label}」`);
await this.waitSettle(300); await this.waitSettle(300);
...@@ -358,6 +412,8 @@ const CSS_ESCAPE = (id: string) => id.replace(/([^\w-])/g, '\\$1'); ...@@ -358,6 +412,8 @@ const CSS_ESCAPE = (id: string) => id.replace(/([^\w-])/g, '\\$1');
export type FilterField = { export type FilterField = {
/** 搜索条上的字段名,需与页面 label 文本一致 */ /** 搜索条上的字段名,需与页面 label 文本一致 */
label: string; label: string;
/** 页面 label 别名(按顺序尝试定位) */
aliases?: string[];
kind: 'text' | 'select' | 'dateRange'; kind: 'text' | 'select' | 'dateRange';
/** kind=text 时的输入值;其余可省略 */ /** kind=text 时的输入值;其余可省略 */
value?: string; value?: string;
......
...@@ -8,11 +8,21 @@ const COLUMN_HEADER_ALIAS_GROUPS: readonly (readonly string[])[] = [ ...@@ -8,11 +8,21 @@ const COLUMN_HEADER_ALIAS_GROUPS: readonly (readonly string[])[] = [
['医保单件名称', '单件名称', '医保名称'], ['医保单件名称', '单件名称', '医保名称'],
['HIS编码', 'HIS码', 'His编码'], ['HIS编码', 'HIS码', 'His编码'],
['结算单标签', '标签'], ['结算单标签', '标签'],
['物料编码', '产品编号', '产品编码', '物资编码', '商品编码', '物料编号'], ['物料编号', '物料编码', '产品编号', '产品编码', '物资编码', '商品编码'],
['物料名称', '产品名称', '物资名称', '商品名称', '产品俗称'], ['物料名称', '产品名称', '物资名称', '商品名称', '产品俗称'],
['规格型号', '规格', '产品规格'], ['规格型号', '规格', '产品规格'],
['产品批号', '批号'], ['产品批号', '批号'],
['进院供应商', '进院供应商名称', '默认进院供应商', '供应商名称', '供应商', '销售商', '销售商名称'], [
'销售商(自定义)',
'销售商(自定义)名称',
'进院供应商',
'进院供应商名称',
'默认销售商',
'默认进院供应商',
'默认供应商',
'销售商',
'销售商名称',
],
['单号', '变更单号', '申请单号', '授权单号'], ['单号', '变更单号', '申请单号', '授权单号'],
['方案编码', '评价方案编码'], ['方案编码', '评价方案编码'],
['方案名称', '评价方案名称'], ['方案名称', '评价方案名称'],
...@@ -23,7 +33,7 @@ const COLUMN_HEADER_ALIAS_GROUPS: readonly (readonly string[])[] = [ ...@@ -23,7 +33,7 @@ const COLUMN_HEADER_ALIAS_GROUPS: readonly (readonly string[])[] = [
['序号', '行号'], ['序号', '行号'],
['注册证号(新)', '注册证号', '新注册证号'], ['注册证号(新)', '注册证号', '新注册证号'],
['启用云仓', '云仓', '是否启用云仓'], ['启用云仓', '云仓', '是否启用云仓'],
['二级供应商名称', '二级供应商', '供应商名称'], ['供应商', '供应商名称', '二级供应商', '二级供应商名称', '默认二级供应商'],
['院区', '院区名称'], ['院区', '院区名称'],
['产品类型', '耗材类型', '物资类型'], ['产品类型', '耗材类型', '物资类型'],
]; ];
......
import type { Locator } from '@playwright/test'; import type { Locator } from '@playwright/test';
import { columnHeaderMatchTokens, columnHeaderTextsMatch } from './column-header-match.util'; import { columnHeaderMatchTokens, scoreColumnHeaderMatch } from './column-header-match.util';
/** 与 table-scroll-layout.helper 一致:不参与列对齐的单元格。 */ /** 与 table-scroll-layout.helper 一致:不参与列对齐的单元格。 */
export function isUtilityTableCellClass(className: string): boolean { export function isUtilityTableCellClass(className: string): boolean {
...@@ -16,10 +16,23 @@ export function isUtilityTableCellClass(className: string): boolean { ...@@ -16,10 +16,23 @@ export function isUtilityTableCellClass(className: string): boolean {
} }
export function resolveColumnIndexFromLabels(headerLabels: string[], columnName: string): number { export function resolveColumnIndexFromLabels(headerLabels: string[], columnName: string): number {
let index = headerLabels.findIndex((item) => columnHeaderTextsMatch(item, columnName)); const pickBest = (name: string): number => {
let bestIndex = -1;
let bestScore = 0;
for (let i = 0; i < headerLabels.length; i += 1) {
const score = scoreColumnHeaderMatch(headerLabels[i], name);
if (score > bestScore) {
bestScore = score;
bestIndex = i;
}
}
return bestScore > 0 ? bestIndex : -1;
};
let index = pickBest(columnName);
if (index >= 0) return index; if (index >= 0) return index;
for (const token of columnHeaderMatchTokens(columnName)) { for (const token of columnHeaderMatchTokens(columnName)) {
index = headerLabels.findIndex((item) => columnHeaderTextsMatch(item, token)); index = pickBest(token);
if (index >= 0) return index; if (index >= 0) return index;
} }
return -1; return -1;
...@@ -42,6 +55,12 @@ export async function dataHeaderLabelsFromCells(headerCells: Locator): Promise<s ...@@ -42,6 +55,12 @@ export async function dataHeaderLabelsFromCells(headerCells: Locator): Promise<s
if (!raw) { if (!raw) {
raw = ((await th.innerText({ timeout: 1_500 }).catch(() => '')) || '').trim(); raw = ((await th.innerText({ timeout: 1_500 }).catch(() => '')) || '').trim();
} }
if (!raw) {
raw = ((await th.getAttribute('title')) ?? '').trim();
}
if (!raw) {
raw = ((await th.getAttribute('aria-label')) ?? '').trim();
}
labels.push(raw.replace(/\s/g, '')); labels.push(raw.replace(/\s/g, ''));
} }
return labels; return labels;
......
/** 宽表横向滚动时,扣除 ant-table 左右固定列占用的可视区域。 */
export type RectLike = { left: number; right: number; width: number };
export function computeTableScrollHostInsets(
hostRect: Pick<RectLike, 'left' | 'right'>,
fixedLeft: Pick<RectLike, 'left' | 'width'> | null,
fixedRight: Pick<RectLike, 'right' | 'width'> | null,
basePad = 48,
): { leftPad: number; rightPad: number } {
let leftPad = basePad;
let rightPad = basePad;
if (fixedLeft && fixedLeft.width > 0 && fixedLeft.left <= hostRect.left + 4) {
leftPad = Math.max(leftPad, fixedLeft.width + 16);
}
if (fixedRight && fixedRight.width > 0 && fixedRight.right >= hostRect.right - 4) {
rightPad = Math.max(rightPad, fixedRight.width + 16);
}
return { leftPad, rightPad };
}
/** 为露出表头 th,相对当前 scrollLeft 的增量;无需滚动则 null。 */
export function deltaScrollLeftForTableHeader(
thRect: Pick<RectLike, 'left' | 'right'>,
hostRect: Pick<RectLike, 'left' | 'right'>,
insets: { leftPad: number; rightPad: number },
): number | null {
if (thRect.left < hostRect.left + insets.leftPad) {
return -(hostRect.left - thRect.left + insets.leftPad);
}
if (thRect.right > hostRect.right - insets.rightPad) {
return thRect.right - (hostRect.right - insets.rightPad);
}
return null;
}
/** 供 page.evaluate 内联:与 computeTableScrollHostInsets / deltaScrollLeftForTableHeader 保持一致。 */
export function readTableScrollInsetsInDom(root: HTMLElement, hostRect: DOMRect): { leftPad: number; rightPad: number } {
const fixedLeft = root.querySelector('.ant-table-fixed-left') as HTMLElement | null;
const fixedRight = root.querySelector('.ant-table-fixed-right') as HTMLElement | null;
return computeTableScrollHostInsets(
hostRect,
fixedLeft ? fixedLeft.getBoundingClientRect() : null,
fixedRight ? fixedRight.getBoundingClientRect() : null,
);
}
export function headerOverlapsFixedRight(thRect: Pick<RectLike, 'left' | 'right'>, fixedRightRect: RectLike | null): boolean {
if (!fixedRightRect || fixedRightRect.width <= 0) return false;
return thRect.right > fixedRightRect.left + 2 && thRect.left < fixedRightRect.right;
}
export function deltaScrollToClearFixedRight(
thRect: Pick<RectLike, 'left' | 'right'>,
fixedRightRect: RectLike | null,
): number | null {
if (!headerOverlapsFixedRight(thRect, fixedRightRect)) return null;
return thRect.right - fixedRightRect!.left + 32;
}
export function applyScrollLeftDeltaForHeaderTh(
root: HTMLElement,
matchedTh: HTMLElement,
scrollContainers: Iterable<Element>,
): void {
const fixedRight = root.querySelector('.ant-table-fixed-right') as HTMLElement | null;
const fixedRightRect = fixedRight ? fixedRight.getBoundingClientRect() : null;
for (let pass = 0; pass < 3; pass += 1) {
const thRect = matchedTh.getBoundingClientRect();
let moved = false;
for (const container of Array.from(scrollContainers)) {
const host = container as HTMLElement;
if (host.scrollWidth <= host.clientWidth + 4) continue;
const hostRect = host.getBoundingClientRect();
const insets = readTableScrollInsetsInDom(root, hostRect);
const delta = deltaScrollLeftForTableHeader(thRect, hostRect, insets);
if (delta != null) {
host.scrollLeft = Math.max(0, host.scrollLeft + delta);
moved = true;
}
const clearFixed = deltaScrollToClearFixedRight(matchedTh.getBoundingClientRect(), fixedRightRect);
if (clearFixed != null) {
host.scrollLeft = Math.max(0, host.scrollLeft + clearFixed);
moved = true;
}
}
if (!moved) break;
if (!headerOverlapsFixedRight(matchedTh.getBoundingClientRect(), fixedRightRect)) break;
}
}
...@@ -6,8 +6,8 @@ export const anaChgColumns = { ...@@ -6,8 +6,8 @@ export const anaChgColumns = {
field: '起始时间', field: '起始时间',
productName: '物料名称', productName: '物料名称',
spec: '规格型号', spec: '规格型号',
supplierName: '进院供应商', supplierName: '销售商(自定义)',
field2: '二级供应商', field2: '供应商',
consumableType: '耗材类型', consumableType: '耗材类型',
id: '阳采ID', id: '阳采ID',
productCode: '物料编号', productCode: '物料编号',
...@@ -35,8 +35,8 @@ export const anaChgComboQuickFields: readonly DeptQuickFieldDef[] = [ ...@@ -35,8 +35,8 @@ export const anaChgComboQuickFields: readonly DeptQuickFieldDef[] = [
export const anaChgComboDrawerFields: readonly CenterReportDrawerField[] = [ export const anaChgComboDrawerFields: readonly CenterReportDrawerField[] = [
{ key: 'productName', type: 'text', label: '物料名称' }, { key: 'productName', type: 'text', label: '物料名称' },
{ key: 'spec', type: 'text', label: '规格型号' }, { key: 'spec', type: 'text', label: '规格型号' },
{ key: 'supplierName', type: 'text', label: '进院供应商' }, { key: 'supplierName', type: 'text', label: '销售商(自定义)' },
{ key: 'field2', type: 'text', label: '二级供应商' }, { key: 'field2', type: 'text', label: '供应商' },
{ key: 'consumableType', type: 'select', label: '耗材类型' }, { key: 'consumableType', type: 'select', label: '耗材类型' },
]; ];
...@@ -56,8 +56,8 @@ export const anaChgSortColumns = [ ...@@ -56,8 +56,8 @@ export const anaChgSortColumns = [
'规格型号', '规格型号',
'器械注册人-术语配置', '器械注册人-术语配置',
'单位', '单位',
'进院供应商', '销售商(自定义)',
'二级供应商', '供应商',
'耗材类型', '耗材类型',
'数量', '数量',
] as const; ] as const;
...@@ -74,7 +74,7 @@ export const anaChgData: CenterReportPageData & { ...@@ -74,7 +74,7 @@ export const anaChgData: CenterReportPageData & {
coreTableHeaders: ['物料编号','物料名称', '产品俗称', '规格型号', '原单价', '现单价', '数量', '总差额'], coreTableHeaders: ['物料编号','物料名称', '产品俗称', '规格型号', '原单价', '现单价', '数量', '总差额'],
summaryKeywords: ['选中总数量', '选中总差额'], summaryKeywords: ['选中总数量', '选中总差额'],
columnAliases: { columnAliases: {
supplierName: ['进院供应商名称'], supplierName: ['销售商(自定义)名称'],
field4: ['器械注册人'], field4: ['器械注册人'],
field5: ['采购计划号'], field5: ['采购计划号'],
}, },
...@@ -105,7 +105,7 @@ export const anaChgData: CenterReportPageData & { ...@@ -105,7 +105,7 @@ export const anaChgData: CenterReportPageData & {
exportQueryFromSample: true, exportQueryFromSample: true,
columnSettingsToggleCandidates: ['备注'], columnSettingsToggleCandidates: ['备注'],
comboSampleScrollColumns: ['进院供应商'], comboSampleScrollColumns: ['销售商(自定义)'],
comboSamplePickKeys: ['field', 'productName', 'spec', 'supplierName', 'field2', 'consumableType'], comboSamplePickKeys: ['field', 'productName', 'spec', 'supplierName', 'field2', 'consumableType'],
comboSampleMaxRowScan: 5, comboSampleMaxRowScan: 5,
drawerFields: anaChgComboDrawerFields, drawerFields: anaChgComboDrawerFields,
......
...@@ -4,22 +4,22 @@ import type { DeptQuickFieldDef } from './dept-report-field-defs'; ...@@ -4,22 +4,22 @@ import type { DeptQuickFieldDef } from './dept-report-field-defs';
export const anaProvColumns = { export const anaProvColumns = {
field: '时间', field: '时间',
supplierName: '进院供应商名称', supplierName: '销售商(自定义)名称',
campus: '院区名称', campus: '院区名称',
} as const; } as const;
export const anaProvComboFullQuickFields: readonly DeptQuickFieldDef[] = [ export const anaProvComboFullQuickFields: readonly DeptQuickFieldDef[] = [
{ key: 'field', label: '时间', type: 'date' }, { key: 'field', label: '时间', type: 'date' },
{ key: 'supplierName', label: '进院供应商名称', type: 'select' }, { key: 'supplierName', label: '销售商(自定义)名称', type: 'select' },
]; ];
export const anaProvComboQuickFields: readonly DeptQuickFieldDef[] = [ export const anaProvComboQuickFields: readonly DeptQuickFieldDef[] = [
{ key: 'field', label: '时间', type: 'date' }, { key: 'field', label: '时间', type: 'date' },
{ key: 'supplierName', label: '进院供应商名称', type: 'select' }, { key: 'supplierName', label: '销售商(自定义)名称', type: 'select' },
]; ];
export const anaProvComboDrawerFields: readonly CenterReportDrawerField[] = [ export const anaProvComboDrawerFields: readonly CenterReportDrawerField[] = [
{ key: 'supplierName', type: 'select', label: '进院供应商名称' }, { key: 'supplierName', type: 'select', label: '销售商(自定义)名称' },
]; ];
export const anaProvComboAssertKeys = ['field', 'campus'] as const; export const anaProvComboAssertKeys = ['field', 'campus'] as const;
...@@ -39,20 +39,20 @@ export const anaProvData: CenterReportPageData & { ...@@ -39,20 +39,20 @@ export const anaProvData: CenterReportPageData & {
iframeSrc: 'statistics/prov', iframeSrc: 'statistics/prov',
productNameSelector: '#form_item_supplierName', productNameSelector: '#form_item_supplierName',
columns: anaProvColumns, columns: anaProvColumns,
coreTableHeaders: ['进院供应商名称', '时间'], coreTableHeaders: ['销售商(自定义)名称', '时间'],
columnAliases: { columnAliases: {
supplierName: ['进院供应商'], supplierName: ['销售商(自定义)'],
}, },
horizontalScrollAnchorColumn: '时间', horizontalScrollAnchorColumn: '时间',
horizontalScrollTargetColumn: '进院供应商名称', horizontalScrollTargetColumn: '销售商(自定义)名称',
horizontalScrollDragDelta: 320, horizontalScrollDragDelta: 320,
mockNotExistProduct: '__NOT_EXIST_SUPPLIER__99999', mockNotExistProduct: '__NOT_EXIST_SUPPLIER__99999',
/** 图表页快捷区常仅有「时间」,用未来区间反例空态。 */ /** 图表页快捷区常仅有「时间」,用未来区间反例空态。 */
mockFieldLabel: '时间', mockFieldLabel: '时间',
mockPreferFutureDate: true, mockPreferFutureDate: true,
drawerResetFieldLabel: '进院供应商名称', drawerResetFieldLabel: '销售商(自定义)名称',
drawerResetFieldKey: 'supplierName', drawerResetFieldKey: 'supplierName',
paginationPageSizeFrom: '50 条/页', paginationPageSizeFrom: '50 条/页',
paginationPageSizeTo: '100 条/页', paginationPageSizeTo: '100 条/页',
...@@ -71,7 +71,7 @@ export const anaProvData: CenterReportPageData & { ...@@ -71,7 +71,7 @@ export const anaProvData: CenterReportPageData & {
exportQueryFromSample: true, exportQueryFromSample: true,
columnSettingsToggleCandidates: ['备注'], columnSettingsToggleCandidates: ['备注'],
comboSampleScrollColumns: ['进院供应商'], comboSampleScrollColumns: ['销售商(自定义)'],
comboSamplePickKeys: ['field', 'supplierName'], comboSamplePickKeys: ['field', 'supplierName'],
comboSampleMaxRowScan: 5, comboSampleMaxRowScan: 5,
drawerFields: anaProvComboDrawerFields, drawerFields: anaProvComboDrawerFields,
......
...@@ -11,7 +11,7 @@ export const centerReportEntryColumns = { ...@@ -11,7 +11,7 @@ export const centerReportEntryColumns = {
campus: '院区名称', campus: '院区名称',
sourceUnit: '来源单位', sourceUnit: '来源单位',
batchNo: '批号', batchNo: '批号',
supplier: '进院供应商', supplier: '销售商(自定义)',
billMode: '单据形态', billMode: '单据形态',
} as const; } as const;
...@@ -31,7 +31,7 @@ export const centerReportEntryDrawerFields: ReadonlyArray<{ ...@@ -31,7 +31,7 @@ export const centerReportEntryDrawerFields: ReadonlyArray<{
{ key: 'sourceUnit', type: 'text', label: '来源单位' }, { key: 'sourceUnit', type: 'text', label: '来源单位' },
{ key: 'billMode', type: 'select', label: '单据形态' }, { key: 'billMode', type: 'select', label: '单据形态' },
{ key: 'batchNo', type: 'text', label: '批号' }, { key: 'batchNo', type: 'text', label: '批号' },
{ key: 'supplier', type: 'text', label: '进院供应商' }, { key: 'supplier', type: 'text', label: '销售商(自定义)' },
]; ];
function buildSortColumnCases(): Array<{ id: string; column: string }> { function buildSortColumnCases(): Array<{ id: string; column: string }> {
......
...@@ -16,7 +16,7 @@ export const centerReportLmmSheetColumns = { ...@@ -16,7 +16,7 @@ export const centerReportLmmSheetColumns = {
orderNo: '单号', orderNo: '单号',
amount: '金额', amount: '金额',
generationStyle: '生成方式', generationStyle: '生成方式',
supplier: '进院供应商', supplier: '销售商(自定义)',
purchaser: '采购员', purchaser: '采购员',
sourceTarget: '来源/目标', sourceTarget: '来源/目标',
storageArea: '库区名称', storageArea: '库区名称',
...@@ -37,7 +37,7 @@ export const centerReportLmmSheetComboDrawerFields: readonly CenterReportDrawerF ...@@ -37,7 +37,7 @@ export const centerReportLmmSheetComboDrawerFields: readonly CenterReportDrawerF
{ key: 'campus', type: 'select', label: '院区名称' }, { key: 'campus', type: 'select', label: '院区名称' },
{ key: 'billType', type: 'select', label: '单据类型' }, { key: 'billType', type: 'select', label: '单据类型' },
{ key: 'generationStyle', type: 'select', label: '生成方式' }, { key: 'generationStyle', type: 'select', label: '生成方式' },
{ key: 'supplier', type: 'text', label: '进院供应商' }, { key: 'supplier', type: 'text', label: '销售商(自定义)' },
{ key: 'purchaser', type: 'text', label: '采购员' }, { key: 'purchaser', type: 'text', label: '采购员' },
{ key: 'sourceTarget', type: 'select', label: '来源/目标' }, { key: 'sourceTarget', type: 'select', label: '来源/目标' },
{ key: 'storageArea', type: 'select', label: '库区名称' }, { key: 'storageArea', type: 'select', label: '库区名称' },
...@@ -62,7 +62,7 @@ export const centerReportLmmSheetData: CenterReportPageData = { ...@@ -62,7 +62,7 @@ export const centerReportLmmSheetData: CenterReportPageData = {
productNameSelector: '#form_item_goodsName', productNameSelector: '#form_item_goodsName',
columns: centerReportLmmSheetColumns, columns: centerReportLmmSheetColumns,
columnAliases: { columnAliases: {
materialName: ['物资名称', '产品名称'], materialName: ['物资名称', '物料名称'],
consumableCategory: ['耗材分类', '物资分类'], consumableCategory: ['耗材分类', '物资分类'],
materialCode: ['物资编码', '物资编号'], materialCode: ['物资编码', '物资编号'],
sourceTarget: ['来源/去向', '来源/目标'], sourceTarget: ['来源/去向', '来源/目标'],
...@@ -84,6 +84,6 @@ export const centerReportLmmSheetData: CenterReportPageData = { ...@@ -84,6 +84,6 @@ export const centerReportLmmSheetData: CenterReportPageData = {
exportTaskName: '中心库出入库明细(后勤)报表', exportTaskName: '中心库出入库明细(后勤)报表',
columnSettingsToggleCandidates: ['产地', '制单人', '科室名称'], columnSettingsToggleCandidates: ['产地', '制单人', '科室名称'],
horizontalScrollAnchorColumn: '物资名称', horizontalScrollAnchorColumn: '物资名称',
horizontalScrollTargetColumn: '进院供应商', horizontalScrollTargetColumn: '销售商(自定义)',
horizontalScrollDragDelta: 320, horizontalScrollDragDelta: 320,
}; };
...@@ -3,10 +3,10 @@ import type { CenterReportDrawerField } from './center-report-shared.types'; ...@@ -3,10 +3,10 @@ import type { CenterReportDrawerField } from './center-report-shared.types';
import type { DeptQuickFieldDef, QuickDrawerSyncField } from './dept-report-field-defs'; import type { DeptQuickFieldDef, QuickDrawerSyncField } from './dept-report-field-defs';
export const centerReportNetEntryColumns = { export const centerReportNetEntryColumns = {
goodsCode: '产品编码', goodsCode: '物料编码',
goodsName: '产品名称', goodsName: '物料名称',
campus: '院区', campus: '院区',
supplier: '进院供应商', supplier: '销售商(自定义)',
spec: '规格型号', spec: '规格型号',
consumableType: '耗材类型', consumableType: '耗材类型',
billDate: '单据日期', billDate: '单据日期',
...@@ -16,14 +16,14 @@ export const centerReportNetEntryColumns = { ...@@ -16,14 +16,14 @@ export const centerReportNetEntryColumns = {
/** 可排序列以 data/scan/netEntrySummary-sort-columns.json 为准(默认表头无「院区」,不写排序用例)。 */ /** 可排序列以 data/scan/netEntrySummary-sort-columns.json 为准(默认表头无「院区」,不写排序用例)。 */
export const centerReportNetEntrySortColumns = [ export const centerReportNetEntrySortColumns = [
'产品编码', '物料编码',
'产品名称', '物料名称',
'单位', '单位',
'耗材类型', '耗材类型',
'是否集采', '是否集采',
'是否计费', '是否计费',
'厂家', '厂家',
'进院供应商', '销售商(自定义)',
'供应商编码', '供应商编码',
'医保单件名称', '医保单件名称',
'注册证号', '注册证号',
...@@ -43,8 +43,8 @@ export const centerReportNetEntryData: CenterReportPageData = { ...@@ -43,8 +43,8 @@ export const centerReportNetEntryData: CenterReportPageData = {
productNameSelector: '#form_item_goodsName', productNameSelector: '#form_item_goodsName',
goodsCodeSelector: '#form_item_goodsCode', goodsCodeSelector: '#form_item_goodsCode',
columns: centerReportNetEntryColumns, columns: centerReportNetEntryColumns,
columnAliases: { goodsCode: ['产品编码', '物资编码'], goodsName: ['产品名称', '物资名称'] }, columnAliases: { goodsCode: ['物料编码', '物资编码'], goodsName: ['物料名称', '物资名称'] },
coreTableHeaders: ['院区', '产品编码', '产品名称', '是否集采', '是否计费', '进院供应商'], coreTableHeaders: ['院区', '物料编码', '物料名称', '是否集采', '是否计费', '销售商(自定义)'],
extraTableHeaders: ['27位医保编码', '医保单件名称'], extraTableHeaders: ['27位医保编码', '医保单件名称'],
dimensions: ['供应商', '物资编码', '是否计费', '是否集采'], dimensions: ['供应商', '物资编码', '是否计费', '是否集采'],
drawerFields: [ drawerFields: [
......
...@@ -3,8 +3,8 @@ import type { CenterReportDrawerField } from './center-report-shared.types'; ...@@ -3,8 +3,8 @@ import type { CenterReportDrawerField } from './center-report-shared.types';
import type { DeptQuickFieldDef, QuickDrawerSyncField } from './dept-report-field-defs'; import type { DeptQuickFieldDef, QuickDrawerSyncField } from './dept-report-field-defs';
export const centerReportNetOutColumns = { export const centerReportNetOutColumns = {
goodsCode: '产品编码', goodsCode: '物料编码',
goodsName: '产品名称', goodsName: '物料名称',
campus: '院区', campus: '院区',
parentDept: '上级科室名称', parentDept: '上级科室名称',
parentDeptCode: '上级科室编码', parentDeptCode: '上级科室编码',
...@@ -22,8 +22,8 @@ export const centerReportNetOutSortColumns = [ ...@@ -22,8 +22,8 @@ export const centerReportNetOutSortColumns = [
'上级科室名称', '上级科室名称',
'科室编码', '科室编码',
'科室名称', '科室名称',
'产品编码', '物料编码',
'产品名称', '物料名称',
'单位', '单位',
'耗材类型', '耗材类型',
'厂家', '厂家',
...@@ -45,14 +45,14 @@ export const centerReportNetOutData: CenterReportPageData = { ...@@ -45,14 +45,14 @@ export const centerReportNetOutData: CenterReportPageData = {
goodsCodeSelector: '#form_item_goodsCode', goodsCodeSelector: '#form_item_goodsCode',
columns: centerReportNetOutColumns, columns: centerReportNetOutColumns,
columnAliases: { columnAliases: {
goodsCode: ['产品编码', '物资编码'], goodsCode: ['物料编码', '物资编码'],
goodsName: ['产品名称', '物资名称'], goodsName: ['物料名称', '物资名称'],
parentDept: ['上级科室名称', '上级科室'], parentDept: ['上级科室名称', '上级科室'],
parentDeptCode: ['上级科室编码'], parentDeptCode: ['上级科室编码'],
deptName: ['科室名称'], deptName: ['科室名称'],
deptCode: ['科室编码'], deptCode: ['科室编码'],
}, },
coreTableHeaders: ['院区', '产品编码', '产品名称', '耗材类型'], coreTableHeaders: ['院区', '物料编码', '物料名称', '耗材类型'],
extraTableHeaders: ['上级科室名称', '科室名称', '27位医保编码', 'HIS收费编码'], extraTableHeaders: ['上级科室名称', '科室名称', '27位医保编码', 'HIS收费编码'],
dimensions: ['上级科室编码', '科室名称', '物资编码', '耗材类型'], dimensions: ['上级科室编码', '科室名称', '物资编码', '耗材类型'],
drawerFields: [ drawerFields: [
......
...@@ -18,7 +18,7 @@ export const centerReportOutColumns = { ...@@ -18,7 +18,7 @@ export const centerReportOutColumns = {
campus: '院区名称', campus: '院区名称',
outboundTarget: '出库目标', outboundTarget: '出库目标',
batchNo: '批号', batchNo: '批号',
supplier: '进院供应商', supplier: '销售商(自定义)',
billMode: '单据形态', billMode: '单据形态',
} as const; } as const;
...@@ -42,7 +42,7 @@ export const centerReportOutDrawerFields: ReadonlyArray<{ ...@@ -42,7 +42,7 @@ export const centerReportOutDrawerFields: ReadonlyArray<{
{ key: 'outboundTarget', type: 'select', label: '出库目标' }, { key: 'outboundTarget', type: 'select', label: '出库目标' },
{ key: 'billMode', type: 'select', label: '单据形态' }, { key: 'billMode', type: 'select', label: '单据形态' },
{ key: 'batchNo', type: 'text', label: '批号' }, { key: 'batchNo', type: 'text', label: '批号' },
{ key: 'supplier', type: 'text', label: '进院供应商' }, { key: 'supplier', type: 'text', label: '销售商(自定义)' },
]; ];
export const centerReportOutSortColumns = [ export const centerReportOutSortColumns = [
......
...@@ -9,9 +9,9 @@ export type CenterReportDrawerField = { ...@@ -9,9 +9,9 @@ export type CenterReportDrawerField = {
export type CenterReportPageData = { export type CenterReportPageData = {
reportPath: string; reportPath: string;
iframeSrc: string; iframeSrc: string;
/** 产品名称输入框选择器(iframe 内) */ /** 物料名称输入框选择器(iframe 内) */
productNameSelector: string; productNameSelector: string;
/** 物资/产品编码输入框(净入/净出库等多维度页) */ /** 物资/物料编码输入框(净入/净出库等多维度页) */
goodsCodeSelector?: string; goodsCodeSelector?: string;
columns: Record<string, string>; columns: Record<string, string>;
columnAliases?: Partial<Record<string, readonly string[]>>; columnAliases?: Partial<Record<string, readonly string[]>>;
...@@ -33,7 +33,7 @@ export type CenterReportPageData = { ...@@ -33,7 +33,7 @@ export type CenterReportPageData = {
mockNotExistMaterial?: string; mockNotExistMaterial?: string;
mockNotExistDept?: string; mockNotExistDept?: string;
mockNotExistSupplier?: string; mockNotExistSupplier?: string;
/** 空列表反例写入的筛选项标签(产品名称 / 单号 / 科室等) */ /** 空列表反例写入的筛选项标签(物料名称 / 单号 / 科室等) */
mockFieldLabel?: string; mockFieldLabel?: string;
mockDateStart?: string; mockDateStart?: string;
mockDateEnd?: string; mockDateEnd?: string;
...@@ -77,6 +77,11 @@ export type CenterReportPageData = { ...@@ -77,6 +77,11 @@ export type CenterReportPageData = {
waitTableOnOpen?: boolean; waitTableOnOpen?: boolean;
/** iframe 内主查询按钮文案,默认「查 询」;财务分析等页为「搜 索」 */ /** iframe 内主查询按钮文案,默认「查 询」;财务分析等页为「搜 索」 */
searchBtnLabel?: '查 询' | '搜 索'; searchBtnLabel?: '查 询' | '搜 索';
/**
* 进页后主表不自动出数/出列,须点「查 询」后才有列表字段与数据。
* 为 true 时取样本、表头断言等会先 search(),不依赖「已有行则跳过查询」优化。
*/
listRequiresExplicitSearch?: boolean;
extraTableHeaders?: readonly string[]; extraTableHeaders?: readonly string[];
/** 导出后在下载中心(任务中心)显示的任务名称;未配置时校验最近导出任务 */ /** 导出后在下载中心(任务中心)显示的任务名称;未配置时校验最近导出任务 */
exportTaskName?: string; exportTaskName?: string;
......
...@@ -2,13 +2,14 @@ import { ...@@ -2,13 +2,14 @@ import {
detailSheetSummaryMatch, detailSheetSummaryMatch,
type CenterReportDrawerField, type CenterReportDrawerField,
} from './center-report-shared.types'; } from './center-report-shared.types';
import { reportAccountDateQuickRange } from './report-default-date-range';
/** 出入库明细查询 · 列表列名与抽屉字段映射(动态取数用)。 */ /** 出入库明细查询 · 列表列名与抽屉字段映射(动态取数用)。 */
export const centerReportSheetColumns = { export const centerReportSheetColumns = {
productCode: '物料编号', productCode: '物料编号',
productName: '物料名称', productName: '物料名称',
batchNo: '批号', batchNo: '批号',
supplier: '进院供应商', supplier: '销售商(自定义)',
campus: '院区名称', campus: '院区名称',
accountDate: '记账日期', accountDate: '记账日期',
billType: '单据类型', billType: '单据类型',
...@@ -43,6 +44,7 @@ export const centerReportSheetColumnAliases: Partial< ...@@ -43,6 +44,7 @@ export const centerReportSheetColumnAliases: Partial<
sourceTarget: ['来源/去向', '来源/目标'], sourceTarget: ['来源/去向', '来源/目标'],
orderNo: ['单据号', '单号'], orderNo: ['单据号', '单号'],
operationDate: ['制单日期', '制单时间'], operationDate: ['制单日期', '制单时间'],
supplier: ['进院供应商', '销售商(自定义)名称'],
}; };
/** 高级筛选抽屉表单项 label(与列表列名不一致时)。 */ /** 高级筛选抽屉表单项 label(与列表列名不一致时)。 */
...@@ -75,7 +77,7 @@ export const centerReportSheetDrawerFields: ReadonlyArray<{ ...@@ -75,7 +77,7 @@ export const centerReportSheetDrawerFields: ReadonlyArray<{
{ key: 'chargeable', type: 'select', label: '是否收费' }, { key: 'chargeable', type: 'select', label: '是否收费' },
{ key: 'focusControl', type: 'select', label: '是否重点管控' }, { key: 'focusControl', type: 'select', label: '是否重点管控' },
{ key: 'focusControlType', type: 'select', label: '重点管控分类' }, { key: 'focusControlType', type: 'select', label: '重点管控分类' },
{ key: 'supplier', type: 'text', label: '进院供应商' }, { key: 'supplier', type: 'text', label: '销售商(自定义)' },
{ key: 'operationDate', type: 'dateRange', label: '制单日期' }, { key: 'operationDate', type: 'dateRange', label: '制单日期' },
{ key: 'sourceType', type: 'select', label: '入库来源' }, { key: 'sourceType', type: 'select', label: '入库来源' },
{ key: 'manufacturer', type: 'text', label: '生产厂家' }, { key: 'manufacturer', type: 'text', label: '生产厂家' },
...@@ -87,8 +89,8 @@ export const centerReportSheetSortColumns = [ ...@@ -87,8 +89,8 @@ export const centerReportSheetSortColumns = [
'单位', '单位',
'备注', '备注',
'批号', '批号',
'进院供应商', '销售商(自定义)',
'二级供应商', '供应商',
'院区名称', '院区名称',
'耗材分类', '耗材分类',
'记账日期', '记账日期',
...@@ -127,10 +129,11 @@ export const centerReportSheetData = { ...@@ -127,10 +129,11 @@ export const centerReportSheetData = {
reportPath: '/spd/form/centerReport/report/centerPages/sheet', reportPath: '/spd/form/centerReport/report/centerPages/sheet',
sheetPath: '/spd/form/centerReport/report/centerPages/sheet', sheetPath: '/spd/form/centerReport/report/centerPages/sheet',
iframeSrc: 'centerPages/sheet', iframeSrc: 'centerPages/sheet',
defaultQuickDateRange: reportAccountDateQuickRange,
productNameSelector: '#form_item_goodsName', productNameSelector: '#form_item_goodsName',
columns: centerReportSheetColumns, columns: centerReportSheetColumns,
columnAliases: centerReportSheetColumnAliases, columnAliases: centerReportSheetColumnAliases,
coreTableHeaders: ['物料编号','物料名称', '批号', '进院供应商', '院区名称'], coreTableHeaders: ['物料编号','物料名称', '批号', '销售商(自定义)', '院区名称'],
summaryKeywords: detailSheetSummaryMatch.metricLabels, summaryKeywords: detailSheetSummaryMatch.metricLabels,
summaryMatch: detailSheetSummaryMatch, summaryMatch: detailSheetSummaryMatch,
drawerLabels: centerReportSheetDrawerLabels, drawerLabels: centerReportSheetDrawerLabels,
...@@ -154,7 +157,7 @@ export const centerReportSheetData = { ...@@ -154,7 +157,7 @@ export const centerReportSheetData = {
mockBatchNo: 'MOCK_BATCH_001', mockBatchNo: 'MOCK_BATCH_001',
mockInvalidPage: '99999', mockInvalidPage: '99999',
/** 列设置 toggle 候选非核心列 */ /** 列设置 toggle 候选非核心列 */
columnSettingsToggleCandidates: ['备注', '产品俗称', '二级供应商'], columnSettingsToggleCandidates: ['备注', '产品俗称', '供应商'],
/** 横向拖拉滚动:锚点列与滚动后应可见的远侧列 */ /** 横向拖拉滚动:锚点列与滚动后应可见的远侧列 */
horizontalScrollAnchorColumn: '物料编号', horizontalScrollAnchorColumn: '物料编号',
horizontalScrollTargetColumn: '医保编码', horizontalScrollTargetColumn: '医保编码',
......
import { buildSortColumnCases, type CenterReportPageData } from './center-report-shared.types'; import { buildSortColumnCases, type CenterReportPageData } from './center-report-shared.types';
import { reportStatPeriodQuickRange } from './report-default-date-range';
export const centerReportTurnoverColumns = { export const centerReportTurnoverColumns = {
productCode: '物料编号', productCode: '物料编号',
productName: '物料名称', productName: '物料名称',
spec: '规格型号', spec: '规格型号',
manufacturer: '生产厂家', manufacturer: '器械注册人',
consumableType: '耗材类型', consumableType: '耗材类型',
campus: '院区名称', campus: '院区名称',
stockQty: '库存数量', stockQty: '库存数量',
...@@ -28,7 +29,7 @@ export const centerReportTurnoverComboQuickFields = [ ...@@ -28,7 +29,7 @@ export const centerReportTurnoverComboQuickFields = [
export const centerReportTurnoverSortColumns = [ export const centerReportTurnoverSortColumns = [
'期初数量', '期初数量',
'期末数量', '期末数量',
'平均库存', '平均库存数量',
'出库数量', '出库数量',
'库存周转天数', '库存周转天数',
'库存周转次数', '库存周转次数',
...@@ -38,14 +39,29 @@ export const centerReportTurnoverSortColumns = [ ...@@ -38,14 +39,29 @@ export const centerReportTurnoverSortColumns = [
export const centerReportTurnoverData: CenterReportPageData = { export const centerReportTurnoverData: CenterReportPageData = {
reportPath: '/spd/form/centerReport/report/statistics/pro', reportPath: '/spd/form/centerReport/report/statistics/pro',
iframeSrc: 'statistics/pro', iframeSrc: 'statistics/pro',
defaultQuickDateRange: reportStatPeriodQuickRange,
productNameSelector: '#table_search_form_goodsName', productNameSelector: '#table_search_form_goodsName',
columns: centerReportTurnoverColumns, columns: centerReportTurnoverColumns,
coreTableHeaders: ['物料编号','物料名称', '规格型号', '生产厂家', '耗材类型', '默认供应商'], columnAliases: {
extraTableHeaders: ['时间段天数', '期初数量', '期末数量', '平均库存', '出库数量', '库存周转天数', '库存周转次数', '库存周转率'], productName: ['物料名称'],
manufacturer: ['生产厂家'],
},
mockFieldLabel: '物料名称',
coreTableHeaders: ['物料编号', '物料名称', '规格型号', '器械注册人', '耗材类型', '默认销售商'],
extraTableHeaders: [
'时间段天数',
'期初数量',
'期末数量',
'平均库存数量',
'出库数量',
'库存周转天数',
'库存周转次数',
'库存周转率',
],
sortColumns: centerReportTurnoverSortColumns, sortColumns: centerReportTurnoverSortColumns,
sortCasePrefix: 'STAT-PTR', sortCasePrefix: 'STAT-PTR',
sortCaseStartIndex: 10, sortCaseStartIndex: 10,
columnSettingsToggleCandidates: ['单位', '默认供应商'], columnSettingsToggleCandidates: ['单位', '默认销售商'],
mockNotExistProduct: '__NOT_EXIST_PRODUCT__99999', mockNotExistProduct: '__NOT_EXIST_PRODUCT__99999',
horizontalScrollAnchorColumn: '物料编号', horizontalScrollAnchorColumn: '物料编号',
horizontalScrollTargetColumn: '库存周转率', horizontalScrollTargetColumn: '库存周转率',
......
...@@ -26,7 +26,6 @@ export const consumeDeptRankDeptSortColumns = ['消耗数量', '消耗金额'] a ...@@ -26,7 +26,6 @@ export const consumeDeptRankDeptSortColumns = ['消耗数量', '消耗金额'] a
/** 右侧产品明细可排序列(不含序号、占比)。 */ /** 右侧产品明细可排序列(不含序号、占比)。 */
export const consumeDeptRankDetailSortColumns = ['物料名称', export const consumeDeptRankDetailSortColumns = ['物料名称',
'规格型号',
'器械注册人-术语配置', '器械注册人-术语配置',
'单价', '单价',
'消耗数量', '消耗数量',
......
...@@ -21,8 +21,8 @@ export const consumeHighColumns = { ...@@ -21,8 +21,8 @@ export const consumeHighColumns = {
his: 'HIS计费日期', his: 'HIS计费日期',
field3: '消耗方式', field3: '消耗方式',
manufacturer: '生产厂家', manufacturer: '生产厂家',
supplierName: '进院供应商名称', supplierName: '销售商(自定义)名称',
subSupplierName: '二级供应商名称', subSupplierName: '供应商名称',
consumableCategory: '耗材分类', consumableCategory: '耗材分类',
field4: '特殊高值标记', field4: '特殊高值标记',
batchNo: '批号', batchNo: '批号',
...@@ -42,8 +42,8 @@ export const consumeHighColumns = { ...@@ -42,8 +42,8 @@ export const consumeHighColumns = {
id2: '条码ID', id2: '条码ID',
field11: '备注', field11: '备注',
27: '27位医保编码', 27: '27位医保编码',
supplierName2: '进院供应商', supplierName2: '销售商(自定义)',
field12: '二级供应商', field12: '供应商',
field13: '数量', field13: '数量',
field14: '结算单价', field14: '结算单价',
field15: '结算金额', field15: '结算金额',
...@@ -78,7 +78,7 @@ export const consumeHighComboDrawerFields: readonly CenterReportDrawerField[] = ...@@ -78,7 +78,7 @@ export const consumeHighComboDrawerFields: readonly CenterReportDrawerField[] =
{ key: 'isVolume', type: 'select', label: '是否带量' }, { key: 'isVolume', type: 'select', label: '是否带量' },
{ key: 'onlineOfflineFlag', type: 'select', label: '线上线下标记' }, { key: 'onlineOfflineFlag', type: 'select', label: '线上线下标记' },
{ key: 'spec', type: 'text', label: '规格型号' }, { key: 'spec', type: 'text', label: '规格型号' },
{ key: 'supplierName', type: 'text', label: '进院供应商名称' }, { key: 'supplierName', type: 'text', label: '销售商(自定义)名称' },
]; ];
export const consumeHighComboAssertKeys = ['patientName', 'udi', 'productName'] as const; export const consumeHighComboAssertKeys = ['patientName', 'udi', 'productName'] as const;
...@@ -95,10 +95,10 @@ export const consumeHighData: CenterReportPageData & { ...@@ -95,10 +95,10 @@ export const consumeHighData: CenterReportPageData & {
columns: consumeHighColumns, columns: consumeHighColumns,
coreTableHeaders: ['物料编号','物料名称', '产品俗称', '单位', 'UDI码', '条码ID', '原厂码', 'HIS编码'], coreTableHeaders: ['物料编号','物料名称', '产品俗称', '单位', 'UDI码', '条码ID', '原厂码', 'HIS编码'],
columnAliases: { columnAliases: {
supplierName: ['进院供应商'], supplierName: ['销售商(自定义)'],
field5: ['采购计划号'], field5: ['采购计划号'],
}, },
sortColumns: ['物料编号','物料名称', 'UDI码', '条码ID', '原厂码', 'HIS编码', '备注', '规格型号', '27位医保编码', '进院供应商', '结算单价', '库存科室', '记账时间', 'HIS计费时间', '患者名称'], sortColumns: ['物料编号','物料名称', 'UDI码', '条码ID', '原厂码', 'HIS编码', '备注', '规格型号', '27位医保编码', '销售商(自定义)', '结算单价', '库存科室', '记账时间', 'HIS计费时间', '患者名称'],
sortCasePrefix: 'STAT-CHC', sortCasePrefix: 'STAT-CHC',
sortCaseStartIndex: 13, sortCaseStartIndex: 13,
...@@ -142,7 +142,7 @@ export const consumeHighSortColumns = [ ...@@ -142,7 +142,7 @@ export const consumeHighSortColumns = [
'备注', '备注',
'规格型号', '规格型号',
'27位医保编码', '27位医保编码',
'进院供应商', '销售商(自定义)',
'结算单价', '结算单价',
'库存科室', '库存科室',
'记账时间', '记账时间',
......
import { import type { CenterReportPageData } from './center-report-shared.types';
buildSortColumnCases,
type CenterReportPageData,
} from './center-report-shared.types';
import type { CenterReportDrawerField } from './center-report-shared.types'; import type { CenterReportDrawerField } from './center-report-shared.types';
import type { DeptQuickFieldDef } from './dept-report-field-defs'; import type { DeptQuickFieldDef } from './dept-report-field-defs';
...@@ -40,24 +37,12 @@ export const costDeptClassifyChargeComboDrawerFields: readonly CenterReportDrawe ...@@ -40,24 +37,12 @@ export const costDeptClassifyChargeComboDrawerFields: readonly CenterReportDrawe
export const costDeptClassifyChargeComboAssertKeys = ['deptNameCol'] as const; export const costDeptClassifyChargeComboAssertKeys = ['deptNameCol'] as const;
/** 主表可排序列(透视表仅「科室名称」列带 sorter)。 */
export const costDeptClassifyChargeSortColumns = ['科室名称'] as const;
export const costDeptClassifyChargeSortCases = buildSortColumnCases(
'STAT-CCC',
costDeptClassifyChargeSortColumns,
4,
);
export const costDeptClassifyChargeData: CenterReportPageData = { export const costDeptClassifyChargeData: CenterReportPageData = {
reportPath: '/spd/form/settleCost/report/settel/chargeSummary', reportPath: '/spd/form/settleCost/report/settel/chargeSummary',
iframeSrc: 'settel/chargeSummary', iframeSrc: 'settel/chargeSummary',
productNameSelector: '#form_item_goodsName', productNameSelector: '#form_item_goodsName',
columns: costDeptClassifyChargeColumns, columns: costDeptClassifyChargeColumns,
coreTableHeaders: ['科室类型', '科室名称', '科室小计'], coreTableHeaders: ['科室类型', '科室名称', '科室小计'],
sortColumns: [...costDeptClassifyChargeSortColumns],
sortCasePrefix: 'STAT-CCC',
sortCaseStartIndex: 4,
mockNotExistProduct: '__NOT_EXIST_DEPT__99999', mockNotExistProduct: '__NOT_EXIST_DEPT__99999',
mockFieldLabel: '入账日期', mockFieldLabel: '入账日期',
mockNotExistDept: '__NOT_EXIST_DEPT__99999', mockNotExistDept: '__NOT_EXIST_DEPT__99999',
......
...@@ -7,7 +7,7 @@ export const costDeptNetInColumns = { ...@@ -7,7 +7,7 @@ export const costDeptNetInColumns = {
deptName: '科室名称', deptName: '科室名称',
consumableType: '耗材类型', consumableType: '耗材类型',
statDate: '统计日期', statDate: '统计日期',
supplierName: '进院供应商', supplierName: '销售商(自定义)',
productCode: '物料编码', productCode: '物料编码',
productName: '物料名称', productName: '物料名称',
batchNo: '批号', batchNo: '批号',
...@@ -33,7 +33,7 @@ export const costDeptNetInData: CenterReportPageData = { ...@@ -33,7 +33,7 @@ export const costDeptNetInData: CenterReportPageData = {
iframeSrc: 'settel/costSearch', iframeSrc: 'settel/costSearch',
productNameSelector: '#form_item_goodsName', productNameSelector: '#form_item_goodsName',
columns: costDeptNetInColumns, columns: costDeptNetInColumns,
coreTableHeaders: ['物料名称', '科室名称', '进院供应商', '统计日期', '统计月份', '耗材类型'], coreTableHeaders: ['物料名称', '科室名称', '销售商(自定义)', '统计日期', '统计月份', '耗材类型'],
mockNotExistProduct: '__NOT_EXIST_PRODUCT__99999', mockNotExistProduct: '__NOT_EXIST_PRODUCT__99999',
mockFieldLabel: '物料名称', mockFieldLabel: '物料名称',
mockFieldInDrawer: true, mockFieldInDrawer: true,
......
...@@ -12,7 +12,7 @@ export const costEntryDetailColumns = { ...@@ -12,7 +12,7 @@ export const costEntryDetailColumns = {
unit: '单位', unit: '单位',
registrationNo: '注册证号', registrationNo: '注册证号',
insuranceCode27: '27位医保编码', insuranceCode27: '27位医保编码',
supplierName: '进院供应商', supplierName: '销售商(自定义)',
settlementPrice: '结算单价', settlementPrice: '结算单价',
consumableCategory: '耗材分类', consumableCategory: '耗材分类',
financeClassify: '财务分类', financeClassify: '财务分类',
...@@ -68,7 +68,7 @@ export const costEntryDetailData: CenterReportPageData = { ...@@ -68,7 +68,7 @@ export const costEntryDetailData: CenterReportPageData = {
columns: costEntryDetailColumns, columns: costEntryDetailColumns,
columnAliases: { columnAliases: {
manufacturer: ['器械注册人-术语配置', '生产厂家', '器械注册人'], manufacturer: ['器械注册人-术语配置', '生产厂家', '器械注册人'],
supplierName: ['进院供应商', '进院供应商名称'], supplierName: ['销售商(自定义)', '销售商(自定义)名称'],
}, },
coreTableHeaders: ['物料名称', '规格型号', '入账数量', '入账金额', '入账日期'], coreTableHeaders: ['物料名称', '规格型号', '入账数量', '入账金额', '入账日期'],
summaryKeywords: ['入账数量', '入账金额'], summaryKeywords: ['入账数量', '入账金额'],
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment