This commit is contained in:
yumoqing 2026-03-23 18:27:34 +08:00
parent 46a384b7b9
commit 39705f3e04
6 changed files with 188 additions and 37 deletions

View File

@ -6,7 +6,11 @@
"logined_userorgid": "ownerid",
"browserfields": {
"exclouded": ["id", "ownerid" ],
"alters": {}
"alters": {
"providerid":{
"dataurl":"{{entire_url('/rbac/get_provider.dspy')}}"
}
}
},
"editexclouded": [
"id", "ownerid"

Binary file not shown.

View File

@ -1,8 +1,10 @@
from pricing.pricing import (
PricingProgram
)
from write_pattern import write_pattern_xlsx
from ahserver.serverenv import ServerEnv
def load_pricing():
env = ServerEnv()
env.write_patten = PricingProgram.write_patten
env.calculate_prices = PricingProgram.pricing

View File

@ -4,46 +4,66 @@ from ahserver.serverenv import ServerEnv
from sqlor.dbpools import DBPools, get_sor_context
from appPublic.log import debug, exception
from appPublic.dictObject import DictObject
from .write_pattern import write_pattern_xlsx
import yaml
"""
采用yaml描述定价策略
一下是一个例子
pricing_unit: 1000
- id: input_token_pricing_1
field: prompt_tokens
between: 0 ~= 1000
- id: input_token_pricing_2
- cnt_field: prompt_tokens
between: 1000 ~= 100000
- id: input_token_pricing_2
- cnt_field: prompt_tokens
between: 100000 ~=
- id: output_pricing
- cnt_field: completion_tokens
在pricing_program的pricing_spec表中定义定价的数据字段
遵循一下规格
字典结构key是字段名需定义字段的type(类型)label(标题)value_mode(值方式)可选options(可选项)可选
必须要有一个price字段其type: float
value_mode 有下列可能的取值
between # 定价表中此字段以如此格式给出:
# "小值 ~ 大值", "~"的前面或后面可以加"="
# 表示含小值,或含大值
in # 定价表中此字段值有如下格式值1 值2 ...
= # 缺省,给定单一值
> #
>=
<
<=
例子vidu定价字段
'''
model:
type: str
label: "模型"
options:
- "viduq3-pro"
- "viduq3-turbo"
视频定价
fields:
resolution:
type: str
label: 分辨率
value_mode:
- between
- in
- =
- >
- >=
- <
- <=
label: "分辨率"
options:
- "1024p"
- "720p"
- "540p"
duration:
type: int
label: 时长
audio:
type: boolean
label: 音频
type: int # 建议改为 int 或 strtimes 不是标准类型
label: "时长"
# 如果时长也有选项,需要补全,例如:
# options:
# - 5
# - 10
off_peak:
type: int # 建议改为 int 或 str因为值是 0 和 1
label: "错峰执行"
options:
- off_peak # 正常时段
- normal # 错峰
price:
type: float
label: 单价
'''
pricing_program_timing表中的pricing_data字段的数据是一个只有一个属性"pricings"的字典
其值为定价条目列表每个定价条目是个字典key值为pricing_spec字段定义的字段
pricings:
- resolution: 480p
duration: 4
@ -81,11 +101,8 @@ pricings:
- resolution: 720p
duration: 12
audio: true
"""
"""
typefuncs = {
'int': int,
'float': float
@ -139,6 +156,22 @@ def check_value(field, spec_value, data_value):
return x
class PricingProgram:
@staticmethod
async def load_pricing(ppid, webpath_xlsx):
pass
@staticmethod
async def write_patten(request, ppid):
async with get_sor_context(request._run_ns, 'pricing') as sor:
env = request._run_ns
recs = await sor.R('pricing_program', {'id': ppid})
if not recs:
debug(f'id={ppid} pricing_program not found')
r = recs[0]
PricingProgram.pp_db2app(r)
x = [ DictObject(**f) for f in r.pricing_spec ]
webpath = env.quote(write_pattern_xlsx(x))
return entire_url(f'/idfile?path={webpath}')
@staticmethod
def pp_db2app(pp):
try:

BIN
pricing/test.xlsx Normal file

Binary file not shown.

112
pricing/write_pattern.py Normal file
View File

@ -0,0 +1,112 @@
import yaml
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
from appPublic.dictObject import DictObject
from appPublic.uniqueID import getID
from ahserver.filestorage import FileStorage
def create_colnames():
r = {}
fls = ['', 'A', 'B']
i = 1
for fl in fls:
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
r[f'{fl}{c}'] = i
i = i + 1
return r
colnames = create_colnames()
reverse_colnames = {v:k for k,v in colnames.items()}
def write_pattern_xlsx(fields: dict) -> str:
wb = Workbook()
ws_data = wb.active
hidden = wb.create_sheet('dict')
hidden.sheet_status = 'hidden'
# 3. 写入表头
headers = []
c = 1
opt_id = 0
for f in fields.values():
ws_data.cell(row=1, column=c, value=f.label or f.name)
if f.options:
create_options(ws_data, c, hidden, opt_id, f.options)
opt_id = opt_id + 1
c += 1
fs = FileStorage()
fp = fs._name2path(f'pricing_{getID}.xlsx')
wb.save(fp)
webpath = fs.webpath(fp)
return webpath
def create_options(ws, dcol, sheet, opt_id, options):
r = 2
vc = opt_id + 1
for v in options:
sheet.cell(row=r, column=vc, value=v)
r = r + 1
colname = reverse_colnames[vc]
dv = DataValidation(type="list",
formula1=f'dict!${colname}$1:${colname}$4',
allow_blank=True)
dv.error = '请选择下拉菜单中的有效职位。'
dv.errorTitle = '输入无效'
ws.add_data_validation(dv)
cn = reverse_colnames[dcol]
dv.add(f'{cn}2:{cn}1048576')
def load_xlsx_pricing(xlsxpath):
wb = load_workbook(xlsxpath)
ws = wb.active
d = []
for row in ws.iter_rows(min_row=2, values_only=True):
r = {}
for c, cell in enumerate(row):
r.update({ws.cell(row=1, column=c+1).value:cell})
d.append(r)
print(d)
return d
if __name__ == '__main__':
fields_str = """model:
type: str
label: "模型"
options:
- "viduq3-pro"
- "viduq3-turbo"
resolution:
type: str
label: "分辨率"
options:
- "1024p"
- "720p"
- "540p"
duration:
type: int # 建议改为 int 或 strtimes 不是标准类型
label: "时长"
# 如果时长也有选项,需要补全,例如:
# options:
# - 5
# - 10
off_peak:
type: int # 建议改为 int 或 str因为值是 0 和 1
label: "错峰执行"
options:
- off_peak # 正常时段
- normal # 错峰
price:
type: float
label: 单价
"""
"""
fields = DictObject(**yaml.safe_load(fields_str))
print(f'{fields=}, {type(fields)=}')
write_pattern_xlsx(fields)
"""
load_xlsx_pricing('./test.xlsx')