Merge branch 'main' of git.opencomputing.cn:yumoqing/kboss
This commit is contained in:
commit
2189cf34fd
@ -35,6 +35,8 @@ async def get_user_balance(ns={}):
|
||||
}
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
balance = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
ns['balance'] = balance
|
||||
debug(ns)
|
||||
return {
|
||||
'status': 'ok',
|
||||
'balance': balance
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
async def sync_model_to_llm(ns={}):
|
||||
import aiohttp
|
||||
|
||||
async def get_sync_orgid(sor):
|
||||
if ns.get('orgid'):
|
||||
return ns.get('orgid')
|
||||
user_li = await sor.R('users', {'id': await get_user()})
|
||||
return user_li[0].get('orgid') if user_li else ''
|
||||
|
||||
# 从数据库读取domain和Bearer token
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
@ -13,6 +19,13 @@ async def sync_model_to_llm(ns={}):
|
||||
}
|
||||
domain = domain_li[0]['pvalue']
|
||||
bearer_token = user_key[0]['pvalue']
|
||||
# sync_orgid = await get_sync_orgid(sor)
|
||||
sync_orgid = "mIWUHBeeDM8mwAFPIQ8pS" # 固定写
|
||||
if not sync_orgid:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到当前用户所属机构'
|
||||
}
|
||||
|
||||
url = f"{domain}/llmage/list_llms"
|
||||
header = {
|
||||
@ -33,29 +46,103 @@ async def sync_model_to_llm(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
new_llms_count = 0
|
||||
sync_products_count = 0
|
||||
new_llms_list = []
|
||||
for category_list in result:
|
||||
for item in category_list.get('llms', []):
|
||||
provider_orgcode = item.get('providerid')
|
||||
provider_name = item.get('provider_name') or item.get('providerid') or '模型供应商'
|
||||
if not provider_orgcode:
|
||||
continue
|
||||
|
||||
provider_ns = {
|
||||
'orgid': sync_orgid,
|
||||
'orgcode': provider_orgcode,
|
||||
'orgname': provider_name,
|
||||
'name': provider_name,
|
||||
'description': provider_name,
|
||||
'appid': item.get('upappid') or '',
|
||||
'providerkey': provider_orgcode,
|
||||
'state': '1',
|
||||
'start_date': '2026-07-01',
|
||||
'end_date': '9999-12-31',
|
||||
'settle_flowid': '0',
|
||||
'salemode': '0',
|
||||
'settle_mode': '3',
|
||||
'settle_datep': 'M00',
|
||||
'contactor': '连战',
|
||||
'contactor_phone': '13800138000',
|
||||
'emailaddress': 'lianzhan@cntoai.com',
|
||||
'address': '北京市海淀区',
|
||||
'org_type': '4'
|
||||
}
|
||||
provider_res = await path_call('../provider/providerAdd.dspy', provider_ns)
|
||||
if not provider_res.get('status'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '供应商同步失败, %s, %s' % (provider_name, provider_res.get('msg'))
|
||||
}
|
||||
provider_data = provider_res.get('data') or {}
|
||||
provider_orgid = provider_data.get('provider_orgid') or provider_data.get('orgid')
|
||||
protocolid = provider_data.get('protocolid')
|
||||
if not provider_orgid or not protocolid:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '供应商同步失败, 未返回provider_orgid或protocolid, %s' % provider_name
|
||||
}
|
||||
|
||||
product_ns = {
|
||||
'providerid': provider_orgid,
|
||||
'providerpid': item.get('id'),
|
||||
'protocolid': protocolid,
|
||||
'name': item.get('name'),
|
||||
'product_code': item.get('model'),
|
||||
'reseller_orgid': sync_orgid,
|
||||
'label': item.get('catelogname') or category_list.get('catelogname'),
|
||||
'classify': 'A',
|
||||
'ptype': '21',
|
||||
'unit': 'hour',
|
||||
'discount': '1',
|
||||
'product_area': '北京'
|
||||
}
|
||||
product_res = await path_call('../product/productAdd.dspy', product_ns)
|
||||
if not product_res.get('status'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品同步失败, %s, %s' % (item.get('name'), product_res.get('msg'))
|
||||
}
|
||||
sync_products_count += 1
|
||||
|
||||
# 查找数据库中是否已经存在,不存在就插入
|
||||
exist_llm = await sor.R('llm', {'model': item.get('model')})
|
||||
if exist_llm:
|
||||
# 更新
|
||||
exits_id = exist_llm[0].get('id')
|
||||
await sor.U('llm', {'id': exits_id}, item)
|
||||
continue
|
||||
|
||||
new_llms = {
|
||||
'id': item.get('id'),
|
||||
'name': item.get('name'),
|
||||
'model': item.get('model'),
|
||||
'description': item.get('description'),
|
||||
'llmcatelogid': item.get('catelog_id') or item.get('catelogid'),
|
||||
'iconid': item.get('iconid'),
|
||||
'upappid': item.get('upappid'),
|
||||
'apiname': item.get('apiname'),
|
||||
'providerid': item.get('providerid'),
|
||||
'ownerid': item.get('ownerid') or '0',
|
||||
'ownerid': item.get('ownerid'),
|
||||
'enabled_date': item.get('enabled_date'),
|
||||
'expired_date': item.get('expired_date'),
|
||||
'query_apiname': item.get('query_apiname') or '',
|
||||
'min_balance': item.get('min_balance'),
|
||||
'status': item.get('status'),
|
||||
'catelogname': item.get('catelogname'),
|
||||
'catelog_id': item.get('catelog_id'),
|
||||
'apiname': item.get('apiname'),
|
||||
'query_apiname': item.get('query_apiname'),
|
||||
'query_period': item.get('query_period'),
|
||||
'ppid': item.get('ppid'),
|
||||
'provider_name': item.get('provider_name'),
|
||||
'pricing_display': item.get('pricing_display'),
|
||||
'provider_iconurl': item.get('provider_iconurl')
|
||||
}
|
||||
new_llms_count += 1
|
||||
new_llms_list.append(new_llms.get('model'))
|
||||
@ -63,7 +150,7 @@ async def sync_model_to_llm(ns={}):
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': f"sync_llm_list同步模型成功,共插入{new_llms_count}个模型,模型列表: {new_llms_list}"
|
||||
'msg': f"sync_llm_list同步模型成功,共同步{sync_products_count}个产品,共插入{new_llms_count}个模型,模型列表: {new_llms_list}"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
|
||||
145
b/llm.sql
Normal file
145
b/llm.sql
Normal file
@ -0,0 +1,145 @@
|
||||
# 创建表格命令
|
||||
CREATE TABLE llm (
|
||||
id VARCHAR(64) NOT NULL COMMENT '唯一标识',
|
||||
name VARCHAR(50) NOT NULL COMMENT '模型名称',
|
||||
model VARCHAR(50) NOT NULL COMMENT '模型代号',
|
||||
description TEXT COMMENT '模型描述',
|
||||
iconid VARCHAR(50) COMMENT '图标标识',
|
||||
upappid VARCHAR(50) COMMENT '上层应用ID',
|
||||
providerid VARCHAR(64) COMMENT '供应商ID',
|
||||
ownerid VARCHAR(20) DEFAULT '0' COMMENT '所有者ID',
|
||||
enabled_date DATE COMMENT '启用日期',
|
||||
expired_date DATE COMMENT '过期日期',
|
||||
min_balance INT DEFAULT 0 COMMENT '最低余额要求(元)',
|
||||
status VARCHAR(20) COMMENT '状态(如published)',
|
||||
catelogname VARCHAR(50) COMMENT '目录名称(如文生视频)',
|
||||
catelog_id VARCHAR(20) COMMENT '目录ID',
|
||||
apiname VARCHAR(50) COMMENT 'API名称',
|
||||
query_apiname VARCHAR(50) COMMENT '查询API名称',
|
||||
query_period INT COMMENT '查询周期(秒)',
|
||||
ppid VARCHAR(64) COMMENT '定价计划ID',
|
||||
provider_name VARCHAR(100) COMMENT '供应商名称',
|
||||
pricing_display TEXT COMMENT '定价显示文本',
|
||||
provider_iconurl VARCHAR(255) COMMENT '供应商图标URL',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='LLM模型信息表';
|
||||
|
||||
|
||||
# 厂商返回的部分数据示例
|
||||
[
|
||||
{
|
||||
"catelogid": "2i2v",
|
||||
"catelogname": "首尾帧生视频",
|
||||
"llms": [
|
||||
{
|
||||
"id": "r0ill7L0s6PtBS8mkmg-7",
|
||||
"name": "viduq3-pro",
|
||||
"model": "viduq3-pro",
|
||||
"description": "vidu文生视频,viduq3-pro模型",
|
||||
"iconid": "vidu",
|
||||
"upappid": "vidu",
|
||||
"providerid": "Bu3Z6OXANehbkD6OK5NJb",
|
||||
"ownerid": "0",
|
||||
"enabled_date": "2026-01-01",
|
||||
"expired_date": "9999-12-31",
|
||||
"min_balance": 10,
|
||||
"status": "published",
|
||||
"catelogname": "首尾帧生视频",
|
||||
"catelog_id": "2i2v",
|
||||
"apiname": "2i2v",
|
||||
"query_apiname": "taskStatus",
|
||||
"query_period": 30,
|
||||
"ppid": "sF2gcl7UeANKtnZv8hfvL",
|
||||
"provider_name": "北京生数科技有限公司",
|
||||
"pricing_display": " - duration: 0.56 元/秒 ",
|
||||
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=vidu"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"catelogid": "asr",
|
||||
"catelogname": "语音识别",
|
||||
"llms": [
|
||||
{
|
||||
"id": "9glv3S-JSzxholxAblU14",
|
||||
"name": "qwen3-asr-flash",
|
||||
"model": "qwen3-asr-flash",
|
||||
"description": "通义千问系列的录音文件识",
|
||||
"iconid": "qwen",
|
||||
"upappid": "tongyi-wan",
|
||||
"providerid": "6fadgewjraOyvxC_EkHou",
|
||||
"ownerid": "0",
|
||||
"enabled_date": "2025-12-01",
|
||||
"expired_date": "9999-12-31",
|
||||
"min_balance": 10,
|
||||
"status": "published",
|
||||
"catelogname": "语音识别",
|
||||
"catelog_id": "asr",
|
||||
"apiname": "short_asr",
|
||||
"query_apiname": null,
|
||||
"query_period": null,
|
||||
"ppid": "16pwEsQeHiOrxC0O6A2j6",
|
||||
"provider_name": "阿里云",
|
||||
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"catelogid": "digital_human",
|
||||
"catelogname": "数字人",
|
||||
"llms": [
|
||||
{
|
||||
"id": "KOsAo6YjTdU0KG7_sKUJF",
|
||||
"name": "wan2.2-s2v",
|
||||
"model": "wan2.2-s2v",
|
||||
"description": "模型:wan2.2-s2v,输入音频和照片,用照片中的人生成数字人",
|
||||
"iconid": "qwen",
|
||||
"upappid": "tongyi-wan",
|
||||
"providerid": "6fadgewjraOyvxC_EkHou",
|
||||
"ownerid": "0",
|
||||
"enabled_date": "2025-12-19",
|
||||
"expired_date": "9999-12-31",
|
||||
"min_balance": 10,
|
||||
"status": "published",
|
||||
"catelogname": "数字人",
|
||||
"catelog_id": "digital_human",
|
||||
"apiname": "avator",
|
||||
"query_apiname": "avatorstatus",
|
||||
"query_period": 10,
|
||||
"ppid": "0B6aldoAej1PpZ4ydtrEZ",
|
||||
"provider_name": "阿里云",
|
||||
"pricing_display": " - duration: 0.5 元/秒 [分辨率=480P]\n - duration: 0.9 元/秒 [分辨率=720P]",
|
||||
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"catelogid": "i2v",
|
||||
"catelogname": "图生视频",
|
||||
"llms": [
|
||||
{
|
||||
"id": "7y7kfYM0Xasizyi37WvAZ",
|
||||
"name": "happyhorse-1.0-i2v",
|
||||
"model": "happyhorse-1.0-i2v",
|
||||
"description": "HappyHorse图生视频模型,以首帧图片为基础,支持通过文本描述进行引导,生成物理真实、运动流畅的视频。",
|
||||
"iconid": "qwen",
|
||||
"upappid": "tongyi-wan",
|
||||
"providerid": "6fadgewjraOyvxC_EkHou",
|
||||
"ownerid": "0",
|
||||
"enabled_date": "2026-04-28",
|
||||
"expired_date": "9999-12-31",
|
||||
"min_balance": 10,
|
||||
"status": "published",
|
||||
"catelogname": "图生视频",
|
||||
"catelog_id": "i2v",
|
||||
"apiname": "i2v-happyhorse",
|
||||
"query_apiname": "t2vstatus",
|
||||
"query_period": 10,
|
||||
"ppid": "knEwDP35DEz5oMAXyvwN3",
|
||||
"provider_name": "阿里云",
|
||||
"pricing_display": " - duration: 0.9 元/秒 [SR=720]\n - duration: 1.6 元/秒 [SR=1080]",
|
||||
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -82,14 +82,6 @@ async def providerAdd(ns={}):
|
||||
'status': False,
|
||||
'msg': 'provider add failed, orgcode is empty'
|
||||
}
|
||||
# filter by orgcode
|
||||
res = await sor.R('organization', {})
|
||||
orgcodes = [orgc.get('orgcode') for orgc in res]
|
||||
if org_code in orgcodes:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'provider add failed, orgcode has already exist'
|
||||
}
|
||||
if not ns.get('orgid'):
|
||||
orgid_li = await sor.R('users', {'id': await get_user()})
|
||||
orgid = orgid_li[0].get('orgid') if orgid_li else ''
|
||||
@ -101,8 +93,33 @@ async def providerAdd(ns={}):
|
||||
else:
|
||||
orgid = ns.get('orgid')
|
||||
|
||||
# filter by orgcode; existing provider returns ids for idempotent callers
|
||||
exist_org_li = await sor.R('organization', {'orgcode': org_code, 'del_flg': '0'})
|
||||
if len(exist_org_li) >= 1:
|
||||
exist_org = exist_org_li[0]
|
||||
exist_provider_li = await sor.R('provider', {'orgid': exist_org.get('id'), 'del_flg': '0'})
|
||||
if not exist_provider_li:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'provider add failed, orgcode has already exist but provider not found'
|
||||
}
|
||||
exist_protocol_li = await sor.R('saleprotocol', {'offer_orgid': exist_org.get('id'), 'bid_orgid': orgid, 'del_flg': '0'})
|
||||
if not exist_protocol_li:
|
||||
exist_protocol_li = await sor.R('saleprotocol', {'offer_orgid': exist_org.get('id'), 'del_flg': '0'})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'provider already exist',
|
||||
'data': {
|
||||
'orgid': exist_org.get('id'),
|
||||
'provider_orgid': exist_org.get('id'),
|
||||
'provider_id': exist_provider_li[0].get('id'),
|
||||
'protocolid': exist_protocol_li[0].get('id') if exist_protocol_li else None
|
||||
}
|
||||
}
|
||||
|
||||
# 供应商parentid 和 运营机构id相同
|
||||
ns_org['parentid'] = orgid
|
||||
ns_sale_mode['bid_orgid'] = orgid
|
||||
|
||||
if not ns_provider.get('start_date'):
|
||||
ns_provider['start_date'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
@ -115,7 +132,13 @@ async def providerAdd(ns={}):
|
||||
await openProviderAccounts(sor, orgid, ns_org['id'])
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "provider add success"
|
||||
"msg": "provider add success",
|
||||
"data": {
|
||||
"orgid": ns_org['id'],
|
||||
"provider_orgid": ns_org['id'],
|
||||
"provider_id": ns_provider['id'],
|
||||
"protocolid": ns_sale_mode['id']
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
@ -46,7 +46,7 @@ async def get_ipc_logo(ns={}):
|
||||
if '?domain_name=' in url_link:
|
||||
domain_url = url_link.split('?domain_name=')[1]
|
||||
# 如果是业主机构
|
||||
if ('ncmatch' in domain_url or '9527' in domain_url or '8889' in domain_url or '8891' in domain_url or domain_url in ['xterm.kaiyuancloud.cn','www.kaiyuancloud.cn', 'dev.kaiyuancloud.cn', 'dev.opencomputing.cn', 'test.kaiyuancloud.cn', 'localhost', 'www.opencomputing.cn', 'opencomputing.cn']) and '/domain/' not in url_link:
|
||||
if ('ncmatch' in domain_url or 'zgcopc.opencomputing.cn' in domain_url or '9527' in domain_url or '8889' in domain_url or '8891' in domain_url or domain_url in ['xterm.kaiyuancloud.cn','www.kaiyuancloud.cn', 'dev.kaiyuancloud.cn', 'dev.opencomputing.cn', 'test.kaiyuancloud.cn', 'localhost', 'www.opencomputing.cn', 'opencomputing.cn']) and '/domain/' not in url_link:
|
||||
yezhu_info = (await sor.R('organization', {'org_type': '0'}))[0]
|
||||
domain_res = (await sor.R('params', {'pname': '业主机构域名'}))[0]['pvalue']
|
||||
# yezhu = {
|
||||
@ -91,6 +91,37 @@ async def get_ipc_logo(ns={}):
|
||||
]
|
||||
}
|
||||
}
|
||||
elif 'zgcopc.opencomputing.cn' in domain_url or '9527' in domain_url:
|
||||
yezhu['logo'] = "https://zgcopc.opencomputing.cn/idfile?path=logo_zgcopc.png"
|
||||
yezhu['additional_msg'] = {
|
||||
"home": {
|
||||
"logoImg": "https://zgcopc.opencomputing.cn/idfile?path=logo_zgcopc.png",
|
||||
"bannerTitle": "中关村国际孵化器",
|
||||
"adress": "北京市海淀区上地信息路2号",
|
||||
"footerTitle": "中关村国际孵化器有限公司",
|
||||
'qrCode': 'https://zgcopc.opencomputing.cn/idfile?path=firstpagehot/ncmatch_inquiry.jpg',
|
||||
'footer_info': '京ICP备13007859号-1 北京中关村国际孵化器有限公司',
|
||||
"copyright": "",
|
||||
"domain_name": "zgcopc.opencomputing.cn",
|
||||
"email": "zhangjian@bjzai.org.cn",
|
||||
"license": "京ICP备13007859号-1",
|
||||
"logo": "https://zgcopc.opencomputing.cn/idfile?path=logo_zgcopc.png",
|
||||
"mobile": "13601380912",
|
||||
"publicsecurity": "11010502054007",
|
||||
"businesslicense": "京ICP备13007859号-1"
|
||||
},
|
||||
"about": {
|
||||
"title": "开元数智",
|
||||
"logo": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
|
||||
"content": [
|
||||
"开元数智(北京)科技有限公司(以下简称“开元数智”)创立于2022年,总部位于北京中关村科技园区,现已形成以上海、南京、深圳、济南为区域枢纽的全国性服务网络。作为新型数字基础设施建设领域的创新企业,公司主营业务涵盖智能算力中心规划建设与运营、算力网络体系构建、企业级AI算力服务及大模型应用整体解决方案。",
|
||||
"公司自主研发的NCMatch智能算力公共服务平台,作为行业领先的一站式人工智能算力服务解决方案,已构建云网算数智“五位一体”的服务体系。该平台深度整合算力资源调度系统、智能算法模型库及行业应用矩阵,为高等院校、科研院所、政企机构及人工智能开发企业提供专业级算力云服务,全面覆盖基础算力供给、大模型训练调优及产业智能化升级等多维度需求。",
|
||||
"开元数智作为国家算力网络建设的重要参与单位,已获得工信部、教育部等部委直属机构指导,并与中关村数智人工智能产业联盟、国家超级计算中心、南京未来网络研究院等权威机构建立战略合作关系。公司深度参与全国超算互联网及全国一体化算力网国家级重点工程,在算力基础设施建设领域具备成熟的技术积累和项目实施经验。",
|
||||
"开元数智(北京)科技有限公司合作的客户有:中国联通、中国电信、中国移动、未来网络、中信网络、国家超级计算济南中心、华为、阿里云、百度智能云、腾讯云、火山、智谱·AI、衔远科技、创新工场、竹间智能、深言科技、澜舟科技、商汤科技、MINMAX、云从科技、第四范式、深度求索、百川智能、Moonshot AI、昆仑万维、深蓝等。",
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
elif 'kaiyuancloud' in domain_url or 'opencomputing' in domain_url or 'localhost' in domain_url:
|
||||
yezhu['additional_msg'] = {
|
||||
"home": {
|
||||
|
||||
90
b/user/get_user_and_role.dspy
Normal file
90
b/user/get_user_and_role.dspy
Normal file
@ -0,0 +1,90 @@
|
||||
def _parse_page(ns, default_page=1, default_size=20, max_size=200):
|
||||
try:
|
||||
current_page = int(ns.get('current_page') or ns.get('page') or default_page)
|
||||
except (TypeError, ValueError):
|
||||
current_page = default_page
|
||||
try:
|
||||
page_size = int(ns.get('page_size') or default_size)
|
||||
except (TypeError, ValueError):
|
||||
page_size = default_size
|
||||
current_page = max(1, current_page)
|
||||
page_size = max(1, min(page_size, max_size))
|
||||
return current_page, page_size, (current_page - 1) * page_size
|
||||
|
||||
|
||||
async def get_user_and_role(ns={}):
|
||||
"""获取机构下所有用户及用户对应的所有角色"""
|
||||
orgid = ns.get('orgid')
|
||||
if not orgid:
|
||||
return {'status': False, 'msg': '缺少 orgid'}
|
||||
|
||||
current_page, page_size, offset = _parse_page(ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
where_sql = """
|
||||
u.del_flg='0'
|
||||
AND (
|
||||
u.orgid=${orgid}$
|
||||
OR o.parentid=${orgid}$
|
||||
)
|
||||
"""
|
||||
if ns.get('username'):
|
||||
where_sql += " AND u.username LIKE '%%%%%s%%%%'" % ns.get('username')
|
||||
if ns.get('mobile'):
|
||||
where_sql += " AND u.mobile LIKE '%%%%%s%%%%'" % ns.get('mobile')
|
||||
count_rows = await sor.sqlExe(
|
||||
"""
|
||||
SELECT COUNT(*) AS total_count
|
||||
FROM users u
|
||||
LEFT JOIN organization o ON u.orgid = o.id AND o.del_flg='0'
|
||||
WHERE %s
|
||||
""" % where_sql,
|
||||
{'orgid': orgid},
|
||||
)
|
||||
total_count = count_rows[0]['total_count'] if count_rows else 0
|
||||
sql = """
|
||||
SELECT u.*
|
||||
FROM users u
|
||||
LEFT JOIN organization o ON u.orgid = o.id AND o.del_flg='0'
|
||||
LEFT JOIN (
|
||||
SELECT userid, MAX(create_at) AS userrole_create_at
|
||||
FROM userrole
|
||||
WHERE del_flg='0'
|
||||
GROUP BY userid
|
||||
) ur_sort ON u.id = ur_sort.userid
|
||||
WHERE %s
|
||||
ORDER BY ur_sort.userrole_create_at DESC, u.create_at DESC
|
||||
LIMIT %d OFFSET %d
|
||||
""" % (where_sql, page_size, offset)
|
||||
users = await sor.sqlExe(sql, {'orgid': orgid})
|
||||
for user in users:
|
||||
user['roles'] = []
|
||||
userroles = await sor.R('userrole', {'userid': user['id']})
|
||||
userroles = sorted(userroles, key=lambda item: item.get('create_at') or '', reverse=True)
|
||||
for userrole in userroles:
|
||||
if userrole.get('del_flg') == '1' or not userrole.get('roleid'):
|
||||
continue
|
||||
roles = await sor.R('role', {'id': userrole['roleid']})
|
||||
if len(roles) >= 1 and roles[0].get('del_flg') != '1':
|
||||
user['roles'].append({
|
||||
'id': roles[0].get('id'),
|
||||
'name': roles[0].get('role'),
|
||||
})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'ok',
|
||||
'data': {
|
||||
'total_count': total_count,
|
||||
'current_page': current_page,
|
||||
'page_size': page_size,
|
||||
'rows': users,
|
||||
},
|
||||
}
|
||||
except Exception as e:
|
||||
return {'status': False, 'msg': '获取用户角色失败, %s' % str(e)}
|
||||
|
||||
|
||||
ret = await get_user_and_role(params_kw)
|
||||
return ret
|
||||
Loading…
x
Reference in New Issue
Block a user