Compare commits
354 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b57a0267f4 | ||
| a922670038 | |||
| b6630aa2d7 | |||
|
|
4832d14814 | ||
| f487ed7a3e | |||
| 48bf9e6461 | |||
|
|
3ab1e55f4c | ||
|
|
8506d3e091 | ||
|
|
9e1997e3f3 | ||
|
|
0ce9836c0d | ||
| 921adcdb2b | |||
| 7cd64daeac | |||
|
|
3afe8b8f7e | ||
|
|
cc080e149a | ||
| f1a7dcc0e2 | |||
| f9e3edfc8c | |||
|
|
a90113851f | ||
| fe55450706 | |||
| 649f93e02a | |||
| b7f234f613 | |||
|
|
18e5021c64 | ||
|
|
d4c85a4db3 | ||
|
|
104a5b4bc5 | ||
|
|
2c52b062da | ||
|
|
af535e7c71 | ||
|
|
1c16423a98 | ||
|
|
9cbda277fb | ||
|
|
6045e8ec76 | ||
|
|
fcbbb6056f | ||
|
|
e9b0e01a53 | ||
| 013ce924bb | |||
| 3491eed86a | |||
|
|
21e9e9b08b | ||
|
|
a77cba4dfe | ||
|
|
f4aac1a3f2 | ||
|
|
ed9a33663e | ||
|
|
f87215b1df | ||
|
|
552f478e7d | ||
|
|
c01b49c43b | ||
|
|
e300eb7375 | ||
| 26ce699c60 | |||
| 0bb65da638 | |||
|
|
c3d61c2571 | ||
|
|
57313fc2e3 | ||
| 668da1b96a | |||
| 8f7f8abee8 | |||
|
|
3fa768f35a | ||
|
|
de9e3c56e7 | ||
|
|
4f3ba55d4e | ||
|
|
d6a54bca57 | ||
|
|
ea432c25f8 | ||
|
|
88b67eb595 | ||
| bcf186539c | |||
| 10c58a72ce | |||
| be99c8618d | |||
| efbbf63d7e | |||
| 07390bf6c7 | |||
| fb5c21c478 | |||
|
|
9e9dfae6d0 | ||
|
|
23e6aaea12 | ||
| 72a1659037 | |||
| 2382d3f671 | |||
| 11afca8596 | |||
|
|
5ecf944bc6 | ||
|
|
d1b116b70e | ||
| 80eec794d8 | |||
| fc80653a6f | |||
|
|
be9f5634d0 | ||
|
|
90795fc9b8 | ||
| 19e4a8276b | |||
| 5949af9ca2 | |||
| df354b3702 | |||
|
|
e417c3ffd1 | ||
|
|
6545c7cf5e | ||
|
|
f520194687 | ||
| 4ffad6521b | |||
| 9725528c8b | |||
|
|
9d190037b7 | ||
|
|
210b17a11e | ||
| e1ca0ebb64 | |||
| 03e3dec9cc | |||
| 94da3694a7 | |||
| 451766c3b6 | |||
|
|
c0a15392c4 | ||
|
|
883fc196ab | ||
| 7d6db715ba | |||
| fb8f4868f2 | |||
|
|
6b870c6bfc | ||
|
|
7ef7756126 | ||
| 98b51c4309 | |||
| 776344b39a | |||
| b5a7cf9b65 | |||
| be8e26c090 | |||
| 9fde58d1ec | |||
| 1e7a7e8f57 | |||
|
|
2bb52fc378 | ||
|
|
0e1c99a4ae | ||
| ddf377b23c | |||
| 0c6ea7ce18 | |||
| 0498c7910d | |||
| 41c55cbf44 | |||
| 43b372cf36 | |||
| 1a5e57a603 | |||
| 0acedc3543 | |||
| bf19a7b14d | |||
|
|
606dc59fe5 | ||
|
|
29d1b78fc3 | ||
|
|
2bb3bc26bd | ||
|
|
ff43af5647 | ||
|
|
1dca74e01f | ||
| f702d39c5b | |||
| 54e01453d5 | |||
| 2144f3dcbc | |||
| 057f564f1d | |||
| 02d1371928 | |||
| e0f5a7c06b | |||
|
|
1a173b4775 | ||
| 9561a142d9 | |||
| c1f987c145 | |||
|
|
ba3757dca2 | ||
|
|
a90849fece | ||
|
|
90ed7cc3fb | ||
|
|
88693d7196 | ||
|
|
a1f2d2d2ad | ||
| 129612605a | |||
|
|
33b48be461 | ||
|
|
3b9ddd0f8f | ||
| 834c11882c | |||
| 3e3aeb6b73 | |||
| d365c1ad62 | |||
| d653ca3107 | |||
| dad34ae571 | |||
| b8c117c1e8 | |||
| c31a87369c | |||
| 5b50e00e17 | |||
| 558eec6013 | |||
| e00c77ae0f | |||
| a4fe9999a4 | |||
|
|
7c5de0fe8a | ||
| 75967f3095 | |||
| bf38e76be0 | |||
| 98b1508d97 | |||
|
|
beb20e6676 | ||
|
|
d8f65b3dc5 | ||
| 90eb714995 | |||
|
|
f927fb4619 | ||
| 0d73cba8bf | |||
| a14b81318b | |||
|
|
8e3a34706c | ||
|
|
f9034f157a | ||
| 0fbccbea23 | |||
| 5e82b38f62 | |||
| 6383555556 | |||
| ef14559b87 | |||
| 403160b401 | |||
| 13e4b87a7e | |||
| 1fda8ff3d6 | |||
|
|
8cb0854397 | ||
|
|
fbbe06e248 | ||
| 8798abd05e | |||
| 8e507be803 | |||
| 861653ce8f | |||
|
|
687d888a4f | ||
|
|
d63343774e | ||
| 3d76e769c7 | |||
| b4509c6b02 | |||
| 92707a8eab | |||
|
|
3668499c20 | ||
|
|
234d1acedf | ||
|
|
901e6218d2 | ||
|
|
b60a73faec | ||
|
|
551afe9c3f | ||
|
|
5c3a9b847b | ||
|
|
59f23762f3 | ||
| dc514871b6 | |||
| 4aaec61876 | |||
|
|
70f2c06839 | ||
|
|
95b04e9349 | ||
|
|
2a980203a5 | ||
|
|
2f1450e96a | ||
|
|
5962e76399 | ||
| a4692cde9f | |||
| 9d7612c647 | |||
| 9b0f0282d4 | |||
| 92a231cacb | |||
|
|
53094c0a44 | ||
|
|
c85c520df9 | ||
|
|
d0b6c903ca | ||
| ef10dfdd69 | |||
| b8d88ec75d | |||
| 491bcd8d13 | |||
|
|
cbc37862fd | ||
|
|
f289e32b31 | ||
|
|
7917ac2d3d | ||
|
|
80821599ea | ||
|
|
81655628c2 | ||
|
|
3c335b6cf1 | ||
| 1ac734775d | |||
| ba100118c4 | |||
| 28e005c17e | |||
| fc3c5cfb02 | |||
|
|
340fc495a0 | ||
|
|
004f513e8c | ||
| c47dc76c05 | |||
| 1998ed5cf2 | |||
| ded931d01d | |||
| 385713aa5d | |||
| d0deabd832 | |||
|
|
c35ea79537 | ||
|
|
c950b4547b | ||
| ed5e271099 | |||
| 251d1a70f2 | |||
| 7b28be8131 | |||
| 289b8ffb5a | |||
| 2aeaeb23b5 | |||
| 3703b3b75b | |||
| 0312ae479f | |||
| ea954613f3 | |||
| 835e1bff46 | |||
| 278aa1465b | |||
| 16e9c78690 | |||
| 26f6b96971 | |||
| e8020c7e7d | |||
|
|
13fbbc6f5b | ||
| b0afba6de7 | |||
| 1b26e3e615 | |||
|
|
e248b1c3e5 | ||
| 3c1a5e5020 | |||
| 7eb378d70a | |||
| 7f03d56548 | |||
|
|
4fe5d049e4 | ||
|
|
1b4e379da6 | ||
|
|
9b4ea937f2 | ||
| 9e918d37e0 | |||
| 4b258baf41 | |||
|
|
d8b57bc6d2 | ||
|
|
2eb3255294 | ||
| 8f94f97555 | |||
| c7412fc2f7 | |||
| ededb5a3da | |||
| f91a860f9c | |||
| ff1a27a96f | |||
| 61ec823297 | |||
| 02e7e8f86f | |||
| 1d7b1cc219 | |||
| a5a11408b7 | |||
|
|
34edc89c95 | ||
|
|
9320b88f3f | ||
|
|
d9ce637e5e | ||
|
|
071f655349 | ||
|
|
bf1ed9aa13 | ||
|
|
7dfedf0824 | ||
|
|
1ba695c442 | ||
|
|
244775a9d7 | ||
|
|
c0671fb7e6 | ||
| c3d6beb8d7 | |||
|
|
79c4660dfd | ||
|
|
dea7edb058 | ||
|
|
2354d4fda7 | ||
|
|
b8ef2d19aa | ||
|
|
d24bd99fe2 | ||
|
|
508e3875ac | ||
|
|
90e00d7d4f | ||
| 0772dd8750 | |||
| a621c6402a | |||
| 086ccbff0d | |||
|
|
737878beb9 | ||
|
|
ada80cf936 | ||
| c969a62f63 | |||
|
|
962eb07685 | ||
|
|
15d135e2f5 | ||
|
|
31c8f26c44 | ||
| 2c18f68f2e | |||
| f0032a3fe8 | |||
| 4bef225e8c | |||
|
|
842f11b177 | ||
| 5a15e3e36f | |||
| 580182d548 | |||
| 4bcb3a6371 | |||
|
|
94c95d593e | ||
| 80be8d5e31 | |||
| a937a057bf | |||
|
|
7549206c19 | ||
| 415ae87cbc | |||
| 97d54661f0 | |||
|
|
d9647cf17e | ||
| 89bd3b6a23 | |||
|
|
a4e012dd9d | ||
| 3fc5a36988 | |||
| a5d62b47c3 | |||
| c05ed767b3 | |||
| c077930b30 | |||
| d5963a51fa | |||
| db76dd7302 | |||
|
|
cb831deeba | ||
| 3e1e2970f8 | |||
|
|
5c8993afc6 | ||
| 0b894ee93b | |||
|
|
b632da39e8 | ||
| b927c6d1ac | |||
| 79d1f8ab35 | |||
| 54c953d41f | |||
| b6585566b6 | |||
|
|
783e61b12a | ||
| 4ab2a5462f | |||
| b70b789919 | |||
| 968639f063 | |||
| 09348a2347 | |||
|
|
ba78af64aa | ||
| a21262bced | |||
|
|
7d80025171 | ||
| de745e2d52 | |||
| 285c9409d5 | |||
|
|
9bbaf61467 | ||
|
|
387c066aaf | ||
| 459aec92f9 | |||
| 9e7bb14499 | |||
| bad11ab8fb | |||
|
|
6ce0ebc210 | ||
|
|
11162aceaf | ||
|
|
8d5a0510bf | ||
| 80a16fcff8 | |||
|
|
cc6fcf03e9 | ||
| b61ef3ec54 | |||
|
|
22ccfb1cbf | ||
|
|
ac6b65d800 | ||
| 0f76206df4 | |||
|
|
a6d2c4166f | ||
| c3e268c640 | |||
| 3eedb6f8b4 | |||
| df63b46d58 | |||
| 8282768738 | |||
|
|
0e5aea5a1c | ||
| f55e8e9f20 | |||
| 3c83c608fc | |||
| f0e20310f7 | |||
| dc3543b80f | |||
|
|
f6941b1994 | ||
| b4c56acfe2 | |||
| 69d7fb2540 | |||
| e303b98fd1 | |||
|
|
fee984ea90 | ||
|
|
914fb01398 | ||
|
|
001aeacca8 | ||
|
|
a24c1d527a | ||
| 62ee057105 | |||
|
|
d0a0ea5e77 | ||
|
|
5f37837a59 | ||
| fa6c5d176b | |||
|
|
b28798bb6d | ||
| 7aeb47f941 | |||
| 5d867dc4ec | |||
|
|
0c7be40d64 | ||
| 019f47797e |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.idea/
|
||||
.DS_Store
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.rar
|
||||
__pycache__/
|
||||
@ -1 +1 @@
|
||||
https://www.kaiyuancloud.cn/pay/payhuidiao.dspy
|
||||
https://www.opencomputing.cn/pay/payhuidiao.dspy
|
||||
@ -90,7 +90,9 @@ async def email_info(msg, indent=0):
|
||||
index = find_data.index("<")
|
||||
name = find_data[:index]
|
||||
if price and name:
|
||||
mail_code = await sor.R('mail_code',{'mailcode':name,'del_flg':'0'})
|
||||
mail_code_sql = """SELECT * FROM mail_code WHERE LOCATE(mailcode, '%s') > 0 and del_flg = '0';""" % name
|
||||
mail_code = await sor.sqlExe(mail_code_sql, {})
|
||||
# mail_code = await sor.R('mail_code',{'mailcode':name,'del_flg':'0'})
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': mail_code[0]['customer_id'], 'recharge_amt': price,
|
||||
'action': 'RECHARGE', 'recharge_path': '2', 'recharge_date': date}
|
||||
|
||||
@ -4,7 +4,7 @@ async def jiajie_get_token_redirect(ns={}):
|
||||
:return:
|
||||
"""
|
||||
# target_host = 'https://testing.vstecscloud.shop'
|
||||
target_host = 'https://aliyun.kaiyuancloud.cn'
|
||||
target_host = 'https://aliyun.opencomputing.cn'
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
@ -39,7 +39,7 @@ async def jiajie_get_token_redirect(ns={}):
|
||||
# 发送HTTP请求
|
||||
url = "%s/api/blade-auth/oauth/token" % target_host
|
||||
|
||||
if 'kaiyuancloud' in target_host:
|
||||
if 'opencomputing' in target_host:
|
||||
tenantid = '502332'
|
||||
else:
|
||||
tenantid = '024060'
|
||||
|
||||
@ -15,7 +15,7 @@ async def jiajie_sync_user(ns={}):
|
||||
'msg': '用户还未登录'
|
||||
}
|
||||
# target_host = 'https://testing.vstecscloud.shop'
|
||||
target_host = 'https://aliyun.kaiyuancloud.cn'
|
||||
target_host = 'https://aliyun.opencomputing.cn'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
exits_user = await sor.R('weishijiajie_users', {'user_id': userid})
|
||||
@ -71,7 +71,7 @@ async def jiajie_sync_user(ns={}):
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"请求失败,状态码: {result.get('code')},响应内容: {result.get('msg')}"
|
||||
'msg': f"用户手机号:{phone}, 请求失败,状态码: {result.get('code')},响应内容: {result.get('msg')}"
|
||||
}
|
||||
|
||||
ret = await jiajie_sync_user(params_kw)
|
||||
|
||||
820
b/baiduc/baidu_confirm_auto_renew_order.dspy
Normal file
820
b/baiduc/baidu_confirm_auto_renew_order.dspy
Normal file
@ -0,0 +1,820 @@
|
||||
async def user_action_record(ns={}):
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'source': '百度智能云',
|
||||
'orderid': ns.get('orderid'),
|
||||
'ordertype': ns.get('ordertype'),
|
||||
'userid': ns.get('userid'),
|
||||
'reason': ns.get('reason')
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.C('user_action', ns_dic)
|
||||
|
||||
async def time_convert(resoucetime=None):
|
||||
if not resoucetime:
|
||||
return
|
||||
utc_time = datetime.datetime.strptime(resoucetime, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc)
|
||||
beijing_time = utc_time.astimezone(datetime.timezone(datetime.timedelta(hours=8)))
|
||||
return beijing_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
async def cal_expire_time(history_time=None, chargeduration=None, unit=None):
|
||||
chargeduration = int(chargeduration)
|
||||
# 当前时间
|
||||
# now = datetime.datetime.now()
|
||||
now = datetime.datetime.strptime(history_time, '%Y-%m-%d %H:%M:%S')
|
||||
if unit == 'MONTH':
|
||||
expire_time = now + dateutil.relativedelta.relativedelta(months=chargeduration)
|
||||
elif unit == 'YEAR':
|
||||
expire_time = now + dateutil.relativedelta.relativedelta(years=chargeduration)
|
||||
else:
|
||||
expire_time = None
|
||||
if expire_time:
|
||||
return str(expire_time)
|
||||
else:
|
||||
return None
|
||||
|
||||
async def affirmbz_order(ns={}):
|
||||
"""确认支付"""
|
||||
order_type = ns.get('order_type')
|
||||
sor = ns['sor']
|
||||
orgid = await sor.R('bz_order', {'id': ns['orderid']})
|
||||
|
||||
servicename = orgid[0]['servicename']
|
||||
product_url = None
|
||||
# if ('BCC' in servicename) or ('GPU' in servicename):
|
||||
# product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
|
||||
|
||||
date = await get_business_date(sor=None)
|
||||
# await sor.U('bz_order',{'id':ns['orderid'],'order_date': date})
|
||||
count = await getCustomerBalance(sor, orgid[0]['customerid'])
|
||||
if count == None:
|
||||
count = 0
|
||||
if count - float(orgid[0]['amount']) < 0:
|
||||
pricedifference = count - round(orgid[0]['amount'],2)
|
||||
return {'status': False, 'msg': '账户余额不足','pricedifference': round(pricedifference,2)}
|
||||
await order2bill(ns['orderid'], sor)
|
||||
bills = await sor.R('bill', {'orderid': ns['orderid'], 'del_flg': '0'})
|
||||
try:
|
||||
# 需要加事务
|
||||
for i in bills:
|
||||
ba = BillAccounting(i)
|
||||
r = await ba.accounting(sor)
|
||||
dates = datetime.datetime.now()
|
||||
await sor.U('bz_order', {'id': ns['orderid'], 'order_status': '1','create_at':dates})
|
||||
await sor.U('bill', {'id': ns['orderid'], 'bill_state': '1'})
|
||||
order_goods = await sor.R('order_goods', {'orderid': ns['orderid']})
|
||||
for j in order_goods:
|
||||
# 处理退订逻辑
|
||||
if order_type == 'REFUND':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where resourceid = '%s';""" % j['resourceids']
|
||||
resource_find_li = await sor.sqlExe(resource_find_sql, {})
|
||||
resource_find_id = resource_find_li[0]['id']
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'del_flg': '1'})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif order_type == 'RENEW':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where FIND_IN_SET('%s', resourceid) and del_flg = '0';""" % j['resourceids']
|
||||
resource_find_li = await sor.sqlExe(resource_find_sql, {})
|
||||
resource_find_id = resource_find_li[0]['id']
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'start_date': j['resourcestarttime'], 'expire_date': j['resourceendtime']})
|
||||
|
||||
# 处理购买逻辑
|
||||
else:
|
||||
product = await sor.R('product', {'id': j['productid']})
|
||||
nss = {}
|
||||
nss['id'] = uuid()
|
||||
# nss['id'] = UUID()
|
||||
nss['providerrid'] = product[0]['providerid']
|
||||
nss['productname'] = product[0]['name']
|
||||
nss['productdesc'] = product[0]['description']
|
||||
nss['customerid'] = orgid[0]['customerid']
|
||||
nss['productid'] = product[0]['id']
|
||||
nss['specdataid'] = j['spec_id']
|
||||
nss['orderid'] = orgid[0]['id']
|
||||
nss['start_date'] = j['resourcestarttime']
|
||||
nss['expire_date'] = j['resourceendtime']
|
||||
nss['resourceid'] = j['resourceids']
|
||||
nss['orderkey'] = j['orderkey']
|
||||
|
||||
if product_url:
|
||||
nss['product_url'] = product_url
|
||||
else:
|
||||
spec = json.loads(product[0]['spec_note']) if isinstance(product[0]['spec_note'], str) else product[0]['spec_note']
|
||||
spec_list_url = [item['value'] for item in spec if item['configName'] == 'listUrl']
|
||||
nss['product_url'] = spec_list_url[0] if spec_list_url else 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
|
||||
|
||||
await sor.C('customer_goods', nss)
|
||||
return {'status': True, 'msg': '支付成功'}
|
||||
except Exception as error:
|
||||
return {'status': False, 'msg': str(error)}
|
||||
|
||||
async def baidu_new_update_resouce(ns={}):
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(12)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
|
||||
user = await sor.R('users', {'id': ns.get('userid')})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=nss) as res:
|
||||
data_ = await res.json()
|
||||
with open('baidu_new_order_after_confirm.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
resourceids = ','.join(order_info['shortIds']) if order_info.get('shortIds') else ''
|
||||
if not resourceids:
|
||||
continue
|
||||
resourcestarttime = await time_convert(order_info.get('resourceStartTime')) if order_info.get(
|
||||
'resourceStartTime') else None
|
||||
resourceendtime = await time_convert(order_info.get('resourceEndTime')) if order_info.get(
|
||||
'resourceEndTime') else None
|
||||
|
||||
order_key = order_info['key']
|
||||
update_order_goods_sql = """ UPDATE order_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceids = '%s',
|
||||
og.resourcestarttime = '%s',
|
||||
og.resourceendtime = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_order_goods_sql, {})
|
||||
update_customer_goods_sql = """ UPDATE customer_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceid = '%s',
|
||||
og.start_date = '%s',
|
||||
og.expire_date = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_customer_goods_sql, {})
|
||||
|
||||
async def baidu_order_cancel(ns={}):
|
||||
baidu_id = ns['baidu_id']
|
||||
order_id = ns['order_id']
|
||||
paydata = {'queryAccountId': baidu_id, 'orderIds': [order_id]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'order cancel success'
|
||||
}
|
||||
|
||||
async def get_time_diff(time_old=None, time_new=None):
|
||||
|
||||
# # 定义两个时间字符串
|
||||
# time_old = '2023-12-01 09:40:00'
|
||||
# time_new = '2023-12-01 23:15:00'
|
||||
|
||||
# 将时间字符串解析为datetime对象
|
||||
time_dt1 = datetime.datetime.strptime(time_old, '%Y-%m-%d %H:%M:%S')
|
||||
time_dt2 = datetime.datetime.strptime(time_new, '%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 计算时间差
|
||||
time_difference = time_dt2 - time_dt1
|
||||
|
||||
# 提取时间差中的分钟数
|
||||
minutes_difference = time_difference.total_seconds() / 60
|
||||
# day = time_difference.days
|
||||
# hour = time_difference.total_seconds() / 3600
|
||||
return minutes_difference
|
||||
|
||||
async def diff_sms_send_save(sor=None, productname=None, time_interval=24*60, send_type='用户欠费通知', user_orgid=None, sms_send_dict=None):
|
||||
sms_should_send = False
|
||||
send_type = send_type
|
||||
# 记录到欠费表中
|
||||
# 首先查询欠费表中时间是否再范围内
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
print('引用发送短信...')
|
||||
customer_phone = (await sor.R('organization', {'id': user_orgid}))[0]['contactor_phone']
|
||||
# customer_name = (await sor.R('organization', {'id': user_orgid}))[0]['orgname']
|
||||
sms_exist_li = await sor.R('sms_record', {'mobile': customer_phone, 'send_type': send_type, 'send_status': '1',
|
||||
'sort': ['send_time desc']})
|
||||
if sms_exist_li:
|
||||
# 如果原来发送成功 时间范围大于24小时 再次发送
|
||||
if sms_exist_li[0]['send_status']:
|
||||
sms_exist_time = sms_exist_li[0]['send_time']
|
||||
time_diff = await get_time_diff(sms_exist_time, time.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
# 如果发送过的短信在一天范围内 不再发送短信
|
||||
if time_diff >= time_interval:
|
||||
sms_should_send = True
|
||||
else:
|
||||
print('%s %s短信已经发送过, 但是没有超过阈值时间, 不再发送...' % (send_type, customer_phone))
|
||||
else:
|
||||
print('%s %s短信没有发送过, 发送...' % (send_type, customer_phone))
|
||||
sms_should_send = True
|
||||
|
||||
if sms_should_send or not sms_exist_li:
|
||||
# 给个人发送短信
|
||||
await send_vcode(customer_phone, send_type, sms_send_dict)
|
||||
except Exception as e:
|
||||
print('发送短信失败: %s' % e)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '发送短信失败',
|
||||
'data': e
|
||||
}
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(2)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
|
||||
user = await sor.R('users', {'id': ns.get('userid')})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=nss) as res:
|
||||
data_ = await res.json()
|
||||
with open('baidu_new_order.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
serviceType = orders[0]['orderItems']
|
||||
|
||||
# 可能获取得到的是延迟订单
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delay_order'
|
||||
}
|
||||
|
||||
# 避免重复退订
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED':
|
||||
order_history = await sor.R('bz_order', {'provider_orderid': ns.get('order_id'), 'business_op': 'BUY_REVERSE', 'order_status': '1'})
|
||||
if order_history:
|
||||
print('此订单之前已经退费成功')
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '此订单之前已经退费成功'
|
||||
}
|
||||
|
||||
# 如果是退款 更新数据库状态
|
||||
if orders[0]['type'] == 'REFUND':
|
||||
updatetime = await time_convert(orders[0]['updateTime']) if orders[0].get('updateTime') else None
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(float(orders[0]['price']), orders[0]['status'], updatetime, ns.get('order_id'))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
|
||||
productType = 'prepay'
|
||||
# 判断订单item中productType是否有后付费的产品
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
postpay_price = order_info['itemFee']['price'] if order_info.get('itemFee') else order_info['catalogPrice']
|
||||
if not postpay_price:
|
||||
# cpt1Price: 固定配置,按分钟计费
|
||||
postpay_price = order_info['pricingDetail'].get('cpt1Price') if order_info.get('pricingDetail') else 0
|
||||
|
||||
# 确定是否是后付费订单
|
||||
if order_info['productType'] == 'postpay' and postpay_price != 0:
|
||||
productType = 'postpay'
|
||||
# 获取余额
|
||||
user_balance = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
# 判断余额是否大于50
|
||||
if user_balance < 50:
|
||||
await sor.rollback()
|
||||
paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '后付费 该账号余额不足50,无法完成购买'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值'
|
||||
}
|
||||
# 实付价格
|
||||
total_price = 0
|
||||
# productType = ''
|
||||
|
||||
# 买/续/退 字段映射
|
||||
order_type = orders[0]['type']
|
||||
if order_type == 'NEW':
|
||||
business_op = 'BUY'
|
||||
elif order_type == 'RENEW':
|
||||
business_op = 'RENEW'
|
||||
elif order_type == 'REFUND':
|
||||
business_op = 'BUY_REVERSE'
|
||||
else:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '支付形式目前仅包含购买,续费,退订'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '线上暂不支持, 请联系售后'
|
||||
}
|
||||
try:
|
||||
# 生成本地订单
|
||||
bz_ns = {}
|
||||
bz_ns['id'] = uuid()
|
||||
bz_ns['order_status'] = '0'
|
||||
bz_ns['business_op'] = business_op
|
||||
bz_ns['userid'] = ns.get('userid')
|
||||
bz_ns['customerid'] = orgid[0]['id']
|
||||
bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
bz_ns['thirdparty_order'] = ns.get('order_id')
|
||||
bz_ns['source'] = '百度智能云'
|
||||
# bz_ns['originalprice'] = orders[0]['price']
|
||||
bz_ns['originalprice'] = sum(i['catalogPrice'] for i in serviceType)
|
||||
bz_ns['provider_orderid'] = ns.get('order_id')
|
||||
bz_ns['ordertype'] = orders[0]['productType']
|
||||
bz_ns['servicename'] = orders[0]['serviceType']
|
||||
bz_ns['autoreneworder'] = '1' if orders[0]['autoRenewOrder'] else '0'
|
||||
if ns.get('specdataid'):
|
||||
bz_ns['specdataid'] = ns['specdataid']
|
||||
await sor.C('bz_order', bz_ns)
|
||||
for i in serviceType:
|
||||
# if i['productType'] == 'prepay':
|
||||
# # 预付费
|
||||
# productType = 'prepay'
|
||||
# financePrice = 0
|
||||
# 获取产品id
|
||||
product = await sor.R('product', {'providerpid': 'baidu_' + i['serviceType'], 'del_flg': '0'})
|
||||
if not product:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未配置该产品, 请联系售后处理'
|
||||
}
|
||||
# 获取协议
|
||||
saleprotocol_to_person = await sor.R('saleprotocol',
|
||||
{'bid_orgid': orgid[0]['id'], 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0'})
|
||||
# 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议
|
||||
saleprotocol_to_all = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0', 'salemode': '0'})
|
||||
|
||||
if saleprotocol_to_person:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_person[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
else:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '还未上线这个产品的协议配置'
|
||||
}
|
||||
supply_price = i['itemFee']['price'] if i.get('itemFee') else i['catalogPrice']
|
||||
financePrice = abs(supply_price * product_salemode[0]['discount'])
|
||||
total_price += financePrice
|
||||
|
||||
# 添加订单子表
|
||||
nss = {}
|
||||
nss['id'] = uuid()
|
||||
nss['orderid'] = bz_ns['id']
|
||||
nss['productid'] = product[0]['id']
|
||||
nss['providerid'] = product[0]['providerid']
|
||||
if i['count'] > 1:
|
||||
nss['list_price'] = abs(i['realCatalogPrice'] / i['count'])
|
||||
else:
|
||||
nss['list_price'] = abs(i['realCatalogPrice'])
|
||||
nss['discount'] = product_salemode[0]['discount']
|
||||
nss['quantity'] = i['count']
|
||||
nss['price'] = abs(round(nss['list_price'] * product_salemode[0]['discount'], 2))
|
||||
# 计算总价
|
||||
# nss['amount'] = round(total_price, 2)
|
||||
nss['amount'] = abs(round(nss['price'] * nss['quantity'], 2))
|
||||
nss['chargemode'] = i.get('productType')
|
||||
nss['servicename'] = i.get('serviceType')
|
||||
nss['chargeduration'] = i.get('time')
|
||||
nss['unit'] = i.get('timeUnit')
|
||||
nss['resourceids'] = ','.join(i['shortIds']) if i.get('shortIds') else ''
|
||||
nss['orderkey'] = i.get('key')
|
||||
|
||||
# 如果是续费订单 由于没有返回日期, 重新计算日期
|
||||
if order_type == 'RENEW':
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where FIND_IN_SET('%s', resourceids) order by resourceendtime desc;" % \
|
||||
nss['resourceids']
|
||||
history_time = await sor.sqlExe(history_time_sql, {})
|
||||
new_end_time = await cal_expire_time(history_time=history_time[0]['resourceendtime'],
|
||||
chargeduration=nss['chargeduration'], unit=nss['unit'])
|
||||
# 开始日期不变 更新到期日期
|
||||
nss['resourcestarttime'] = history_time[0]['resourcestarttime']
|
||||
nss['resourceendtime'] = new_end_time
|
||||
else:
|
||||
if i.get('resourceStartTime'):
|
||||
nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime'))
|
||||
else:
|
||||
nss['resourcestarttime'] = await time_convert(orders[0]['updateTime'])
|
||||
|
||||
if i.get('resourceEndTime'):
|
||||
nss['resourceendtime'] = await time_convert(i.get('resourceEndTime'))
|
||||
|
||||
# 后付费没有资源结束时间
|
||||
if i.get('productType') == 'prepay':
|
||||
end_time = await time_convert(orders[0]['updateTime'])
|
||||
nss['resourceendtime'] = await cal_expire_time(history_time=end_time,
|
||||
chargeduration=nss['chargeduration'],
|
||||
unit=nss['unit'])
|
||||
else:
|
||||
nss['resourceendtime'] = None
|
||||
|
||||
await sor.C('order_goods', nss)
|
||||
|
||||
# 循环后更新订单中总价
|
||||
await sor.U('bz_order', {'id': bz_ns['id'], 'amount': round(total_price, 2)})
|
||||
except Exception as e:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '发生错误, %s' % str(e)[:100]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 判断用户账户余额是否足够支付
|
||||
try:
|
||||
count = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
if order_type == 'REFUND':
|
||||
count = total_price + 0.1
|
||||
|
||||
if round(total_price,2) <= count:
|
||||
#判断预付费或者后付费
|
||||
if productType == 'prepay' or productType == 'postpay':
|
||||
# 调用扣费接口
|
||||
affirmbz_order_ns = {
|
||||
'sor': sor,
|
||||
'orderid': bz_ns['id'],
|
||||
'order_type': order_type
|
||||
}
|
||||
affirmbz_order_res = await affirmbz_order(affirmbz_order_ns)
|
||||
if not affirmbz_order_res['status']:
|
||||
# if True:
|
||||
await sor.rollback()
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '支付错误, 请联系售后, %s' % affirmbz_order_res.get('msg')
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '支付错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 预配置local_refund用于本地操作
|
||||
if order_type == 'REFUND' and not ns.get('local_refund'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '本地退费成功'
|
||||
}
|
||||
else:
|
||||
# 调用支付订单接口
|
||||
paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderId':ns.get('order_id')}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
data_ = await res.json()
|
||||
if data_ == {'success': True}:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '购买成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
ns_cron_job = {
|
||||
'id': uuid(),
|
||||
'source': 'baidu',
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': 'buy success'
|
||||
}
|
||||
await sor.C('baidu_cron_job', ns_cron_job)
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'orderid': bz_ns['id']
|
||||
# }
|
||||
else:
|
||||
await sor.rollback()
|
||||
await baidu_order_cancel(
|
||||
{'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '支付成功后, order_pay接口错误, 回滚, %s' % str(data_)[:400]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品分配排队中, 请联系售后详询'
|
||||
}
|
||||
else:
|
||||
# 取消订单
|
||||
await sor.rollback()
|
||||
paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '无法购买后付费产品'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {'status': False, 'msg': '无法购买后付费产品'}
|
||||
else:
|
||||
#取消订单
|
||||
await sor.rollback()
|
||||
# 余额不足不cancle订单
|
||||
# paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderIds':[ns.get('order_id')]}
|
||||
# ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
# url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
# method = 'POST'
|
||||
# header = {
|
||||
# "Host": "billing.baidubce.com"
|
||||
# }
|
||||
# header = await get_auth_header(method=method, url=url, header=header)
|
||||
# async with aiohttp_client.request(
|
||||
# method=method,
|
||||
# url=url,
|
||||
# headers=header,
|
||||
# json=paydata) as res:
|
||||
# await res.json()
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '该账号余额不足,无法完成购买'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
|
||||
# 发送短信
|
||||
sms_send_dict = {
|
||||
'time': time.strftime('%Y-%m-%d %H:') + '00:00',
|
||||
'productname': None
|
||||
}
|
||||
await diff_sms_send_save(sor=sor, time_interval=24*60, send_type='用户欠费通知', user_orgid=orgid, sms_send_dict=sms_send_dict)
|
||||
|
||||
return {'status': False,'msg': '该账号余额不足,无法完成购买'}
|
||||
except Exception as e:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
# 更新资源时间 资源id
|
||||
# if order_type == 'NEW':
|
||||
# await baidu_new_update_resouce(ns)
|
||||
return {
|
||||
'status': True,
|
||||
'orderid': bz_ns['id'],
|
||||
'originalprice': bz_ns.get('originalprice'),
|
||||
'servicename': bz_ns.get('servicename'),
|
||||
'amount': total_price
|
||||
}
|
||||
|
||||
async def get_order_list_base_page(baidu_id, pageNo=1, pageSize=500):
|
||||
ns = {'queryAccountId': baidu_id, 'pageNo': pageNo, 'pageSize': pageSize}
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/list?%s' % ns_format
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=ns) as res:
|
||||
data_orders = await res.json()
|
||||
return data_orders
|
||||
|
||||
|
||||
async def update_baidu_order_list(ns={}):
|
||||
"""
|
||||
ns = {'queryAccountId': '139fc7a23b314596ad78b6bb8e7c1503', 'orderType': 'REFUND'}
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
username = None
|
||||
# 更新机构下全部用户订单信息
|
||||
if ns.get('orgid'):
|
||||
users_find_sql = """SELECT DISTINCT b.baidu_id FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0';""" % ns.get('orgid')
|
||||
users = await sor.sqlExe(users_find_sql, {})
|
||||
|
||||
# 更新个人订单信息
|
||||
elif ns.get('userid'):
|
||||
users = await sor.R('baidu_users', {'user_id': ns['userid']})
|
||||
username_li = await sor.R('users', {'id': ns['userid']})
|
||||
username = username_li[0]['username'] if username_li else None
|
||||
else:
|
||||
users = []
|
||||
|
||||
update_count = 0
|
||||
add_count = 0
|
||||
for baidu_id in users:
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=1, pageSize=1000)
|
||||
page_num_count = int(data_orders['totalCount'] / data_orders['pageSize']) + 1
|
||||
for page_num in range(1, page_num_count + 1):
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=page_num, pageSize=1000)
|
||||
orders = data_orders['orders']
|
||||
for item in orders:
|
||||
updatetime = await time_convert(item.get('updateTime')) if item.get('updateTime') else None
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"orderid": item.get("uuid"),
|
||||
"ordertype": item.get("type"),
|
||||
"accountid": item.get("accountId"),
|
||||
"servicetype": item.get("serviceType"),
|
||||
"producttype": item.get("productType"),
|
||||
"shortids": ','.join(item['shortIds']) if item.get('shortIds') else '',
|
||||
"price": item.get("price"),
|
||||
"status": item.get("status"),
|
||||
"autoreneworder": '1' if item.get("autoRenewOrder") else '0',
|
||||
"createtime": await time_convert(item.get('createTime')) if item.get(
|
||||
'createTime') else None,
|
||||
"updatetime": updatetime
|
||||
}
|
||||
ns_exist_order = {
|
||||
'orderid': item.get("uuid")
|
||||
}
|
||||
exist_order = await sor.R('baidu_orders', ns_exist_order)
|
||||
if exist_order and exist_order[0]['updatetime'] != updatetime:
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(item.get("price"), item.get("status"), updatetime,
|
||||
item.get("uuid"))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
update_count += 1
|
||||
|
||||
if not exist_order:
|
||||
await sor.C('baidu_orders', ns_dic)
|
||||
add_count += 1
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '同步数据成功, 新增 %s 条, 更新 %s 条' % (add_count, update_count),
|
||||
'data': {
|
||||
'username': username
|
||||
}
|
||||
}
|
||||
|
||||
async def baidu_confirm_auto_renew_order(ns={}):
|
||||
if ns.get('domain_name'):
|
||||
orgid_li = await sor.R('reseller', {'domain_name': ns.get('domain_name'), 'del_flg': '0'})
|
||||
orgid = orgid_li[0]['orgid']
|
||||
else:
|
||||
orgid = 'mIWUHBeeDM8mwAFPIQ8pS'
|
||||
|
||||
# 读取baidu_orders表格 确定状态是renew的订单ID
|
||||
renew_results = []
|
||||
# return {'1': 2}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
renew_sql = """ SELECT bo.*, bs.user_id FROM baidu_orders AS bo LEFT JOIN baidu_users AS bs ON bo.accountid = bs.baidu_id WHERE bo.ordertype = 'RENEW' AND bo.status = 'NEED_CONFIRM' AND bo.del_flg = '0'; """
|
||||
# return {'1': renew_sql}
|
||||
renew_results = await sor.sqlExe(renew_sql, {})
|
||||
|
||||
renew_status_count = 0
|
||||
# 执行 get_baidu_orderlist sor分开运行
|
||||
for renew_res in renew_results:
|
||||
order_id = renew_res.get('orderid')
|
||||
user_id = renew_res.get('user_id')
|
||||
|
||||
renew_status = await get_baidu_orderlist({'order_id': order_id, 'userid': user_id})
|
||||
if renew_status.get('status'):
|
||||
renew_status_count += 1
|
||||
|
||||
|
||||
# 并触发update函数
|
||||
update_msg = await update_baidu_order_list({'orgid': orgid})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '续费订单执行结束, 触发了%s条数据' % len(renew_results),
|
||||
'data': {
|
||||
'renew_status_count': renew_status_count,
|
||||
'update_msg': update_msg,
|
||||
}
|
||||
}
|
||||
|
||||
ret = await baidu_confirm_auto_renew_order(params_kw)
|
||||
return ret
|
||||
@ -1,6 +1,7 @@
|
||||
async def user_action_record(ns={}):
|
||||
ns_dic_id = uuid() if not ns.get('id') else ns.get('id')
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'id': ns_dic_id,
|
||||
'source': '百度智能云',
|
||||
'orderid': ns.get('orderid'),
|
||||
'ordertype': ns.get('ordertype'),
|
||||
@ -42,8 +43,8 @@ async def affirmbz_order(ns={}):
|
||||
|
||||
servicename = orgid[0]['servicename']
|
||||
product_url = None
|
||||
if ('BCC' in servicename) or ('GPU' in servicename):
|
||||
product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
|
||||
# if ('BCC' in servicename) or ('GPU' in servicename):
|
||||
# product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
|
||||
|
||||
date = await get_business_date(sor=None)
|
||||
# await sor.U('bz_order',{'id':ns['orderid'],'order_date': date})
|
||||
@ -68,10 +69,23 @@ async def affirmbz_order(ns={}):
|
||||
# 处理退订逻辑
|
||||
if order_type == 'REFUND':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where resourceid = '%s';""" % j['resourceids']
|
||||
resource_find_sql = """select id, resourceid, expire_resourceid from customer_goods where FIND_IN_SET('%s', resourceid) and del_flg = '0';""" % j['resourceids']
|
||||
resource_find_li = await sor.sqlExe(resource_find_sql, {})
|
||||
resource_find_id = resource_find_li[0]['id']
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'del_flg': '1'})
|
||||
|
||||
expire_resourceid = resource_find_li[0]['expire_resourceid']
|
||||
if expire_resourceid:
|
||||
new_expire_resourceid = expire_resourceid + ',' + j['resourceids']
|
||||
else:
|
||||
new_expire_resourceid = j['resourceids']
|
||||
|
||||
items_refund = resource_find_li[0]['resourceid'].split(',') if resource_find_li[0]['resourceid'] else []
|
||||
filtered_items = [item for item in items_refund if item != j['resourceids']]
|
||||
result = ','.join(filtered_items)
|
||||
if not result:
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'del_flg': '1'})
|
||||
else:
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'resourceid': result, 'expire_resourceid': new_expire_resourceid})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif order_type == 'RENEW':
|
||||
@ -109,15 +123,18 @@ async def affirmbz_order(ns={}):
|
||||
return {'status': True, 'msg': '支付成功'}
|
||||
except Exception as error:
|
||||
await sor.rollback()
|
||||
raise error
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(error) + str(traceback.format_exc()))
|
||||
traceback.print_exc()
|
||||
return {'status': False, 'msg': str(error) + str(traceback.format_exc())}
|
||||
|
||||
async def baidu_new_update_resouce(ns={}):
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(12)
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
|
||||
@ -138,15 +155,107 @@ async def get_baidu_orderlist(ns={}):
|
||||
headers=header,
|
||||
json=nss) as res:
|
||||
data_ = await res.json()
|
||||
with open('baidu_new_order_after_confirm.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
resourceids = ','.join(order_info['shortIds']) if order_info.get('shortIds') else ''
|
||||
if not resourceids:
|
||||
continue
|
||||
resourcestarttime = await time_convert(order_info.get('resourceStartTime')) if order_info.get(
|
||||
'resourceStartTime') else None
|
||||
resourceendtime = await time_convert(order_info.get('resourceEndTime')) if order_info.get(
|
||||
'resourceEndTime') else None
|
||||
|
||||
order_key = order_info['key']
|
||||
update_order_goods_sql = """ UPDATE order_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceids = '%s',
|
||||
og.resourcestarttime = '%s',
|
||||
og.resourceendtime = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_order_goods_sql, {})
|
||||
update_customer_goods_sql = """ UPDATE customer_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceid = '%s',
|
||||
og.start_date = '%s',
|
||||
og.expire_date = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_customer_goods_sql, {})
|
||||
|
||||
async def baidu_order_cancel(ns={}):
|
||||
baidu_id = ns['baidu_id']
|
||||
order_id = ns['order_id']
|
||||
paydata = {'queryAccountId': baidu_id, 'orderIds': [order_id]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'order cancel success'
|
||||
}
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(1)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
|
||||
user = await sor.R('users', {'id': ns.get('userid')})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=nss) as res:
|
||||
data_ = await res.json()
|
||||
with open('baidu_new_order.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
serviceType = orders[0]['orderItems']
|
||||
|
||||
# 可能获取得到的是延迟订单
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delay_order'
|
||||
}
|
||||
# if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
# await update_baidu_order_list({'userid': ns.get('userid')})
|
||||
# res_refund = await baidu_confirm_refund_order({'order_id': ns.get('order_id'), 'baidu_id': baidu_users[0]['baidu_id'], 'user_id': ns.get('userid')})
|
||||
# return res_refund
|
||||
|
||||
# 避免重复退订
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED':
|
||||
@ -165,19 +274,52 @@ async def get_baidu_orderlist(ns={}):
|
||||
(float(orders[0]['price']), orders[0]['status'], updatetime, ns.get('order_id'))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
|
||||
productType = 'prepay'
|
||||
# 判断订单item中productType是否有后付费的产品
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
postpay_price = order_info['itemFee']['price'] if order_info.get('itemFee') else order_info['catalogPrice']
|
||||
if not postpay_price:
|
||||
# cpt1Price: 固定配置,按分钟计费
|
||||
postpay_price = order_info['pricingDetail'].get('cpt1Price') if order_info.get('pricingDetail') else 0
|
||||
|
||||
# 确定是否是后付费订单
|
||||
if order_info['productType'] == 'postpay' and postpay_price != 0:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '暂不支持后付费按量购买, 请联系后台开通'
|
||||
}
|
||||
productType = 'postpay'
|
||||
# 获取余额
|
||||
user_balance = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
# 判断余额是否大于50
|
||||
if user_balance < 50:
|
||||
await sor.rollback()
|
||||
paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '后付费 该账号余额不足50,无法完成购买'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值'
|
||||
}
|
||||
# 实付价格
|
||||
total_price = 0
|
||||
productType = ''
|
||||
# productType = ''
|
||||
|
||||
# 买/续/退 字段映射
|
||||
order_type = orders[0]['type']
|
||||
@ -210,7 +352,8 @@ async def get_baidu_orderlist(ns={}):
|
||||
bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
bz_ns['thirdparty_order'] = ns.get('order_id')
|
||||
bz_ns['source'] = '百度智能云'
|
||||
bz_ns['originalprice'] = orders[0]['price']
|
||||
# bz_ns['originalprice'] = orders[0]['price']
|
||||
bz_ns['originalprice'] = sum(i['catalogPrice'] for i in serviceType)
|
||||
bz_ns['provider_orderid'] = ns.get('order_id')
|
||||
bz_ns['ordertype'] = orders[0]['productType']
|
||||
bz_ns['servicename'] = orders[0]['serviceType']
|
||||
@ -219,23 +362,45 @@ async def get_baidu_orderlist(ns={}):
|
||||
bz_ns['specdataid'] = ns['specdataid']
|
||||
await sor.C('bz_order', bz_ns)
|
||||
for i in serviceType:
|
||||
if i['productType'] == 'prepay':
|
||||
# 预付费
|
||||
productType = 'prepay'
|
||||
# if i['productType'] == 'prepay':
|
||||
# # 预付费
|
||||
# productType = 'prepay'
|
||||
# financePrice = 0
|
||||
# 获取产品id
|
||||
product = await sor.R('product', {'providerpid': 'baidu_' + i['serviceType'], 'del_flg': '0'})
|
||||
if not product:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未配置该产品, 请联系售后处理'
|
||||
}
|
||||
# 获取协议
|
||||
saleprotocol = await sor.R('saleprotocol',
|
||||
saleprotocol_to_person = await sor.R('saleprotocol',
|
||||
{'bid_orgid': orgid[0]['id'], 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0'})
|
||||
if saleprotocol == []:
|
||||
# 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议
|
||||
saleprotocol = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0', 'salemode': '0'})
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol[0]['id'], 'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
# 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议
|
||||
saleprotocol_to_all = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0', 'salemode': '0'})
|
||||
|
||||
if saleprotocol_to_person:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_person[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
else:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '还未上线这个产品的协议配置'
|
||||
}
|
||||
supply_price = i['itemFee']['price'] if i.get('itemFee') else i['catalogPrice']
|
||||
financePrice = abs(supply_price * product_salemode[0]['discount'])
|
||||
total_price += financePrice
|
||||
@ -261,10 +426,27 @@ async def get_baidu_orderlist(ns={}):
|
||||
nss['chargeduration'] = i.get('time')
|
||||
nss['unit'] = i.get('timeUnit')
|
||||
nss['resourceids'] = ','.join(i['shortIds']) if i.get('shortIds') else ''
|
||||
nss['orderkey'] = i.get('key')
|
||||
|
||||
try:
|
||||
# 保存配置configurations 存入specdata表中
|
||||
if i.get('configurations'):
|
||||
specdata = json.dumps(i['configurations'], ensure_ascii=False)
|
||||
ns_specificdata = {
|
||||
'id': uuid(),
|
||||
'productid': product[0]['id'],
|
||||
'spec_data': specdata,
|
||||
}
|
||||
nss['spec_id'] = ns_specificdata['id']
|
||||
await sor.C('specificdata', ns_specificdata)
|
||||
except Exception as e:
|
||||
print('保存配置configurations失败', str(e))
|
||||
with open('baidu_error.log', 'a') as f:
|
||||
f.write('保存配置configurations失败' + str(e) + '\n')
|
||||
|
||||
# 如果是续费订单 由于没有返回日期, 重新计算日期
|
||||
if order_type == 'RENEW':
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where resourceids = '%s' order by resourceendtime desc;" % \
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where FIND_IN_SET('%s', resourceids) order by resourceendtime desc;" % \
|
||||
nss['resourceids']
|
||||
history_time = await sor.sqlExe(history_time_sql, {})
|
||||
new_end_time = await cal_expire_time(history_time=history_time[0]['resourceendtime'],
|
||||
@ -273,27 +455,45 @@ async def get_baidu_orderlist(ns={}):
|
||||
nss['resourcestarttime'] = history_time[0]['resourcestarttime']
|
||||
nss['resourceendtime'] = new_end_time
|
||||
else:
|
||||
nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime')) if i.get(
|
||||
'resourceStartTime') else None
|
||||
nss['resourceendtime'] = await time_convert(i.get('resourceEndTime')) if i.get(
|
||||
'resourceEndTime') else None
|
||||
if i.get('resourceStartTime'):
|
||||
nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime'))
|
||||
else:
|
||||
nss['resourcestarttime'] = await time_convert(orders[0]['updateTime'])
|
||||
|
||||
if i.get('resourceEndTime'):
|
||||
nss['resourceendtime'] = await time_convert(i.get('resourceEndTime'))
|
||||
|
||||
# 后付费没有资源结束时间
|
||||
if i.get('productType') == 'prepay':
|
||||
end_time = await time_convert(orders[0]['updateTime'])
|
||||
nss['resourceendtime'] = await cal_expire_time(history_time=end_time,
|
||||
chargeduration=nss['chargeduration'],
|
||||
unit=nss['unit'])
|
||||
else:
|
||||
nss['resourceendtime'] = None
|
||||
|
||||
await sor.C('order_goods', nss)
|
||||
|
||||
# 循环后更新订单中总价
|
||||
await sor.U('bz_order', {'id': bz_ns['id'], 'amount': round(total_price, 2)})
|
||||
except Exception as e:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
import traceback
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '发生错误, %s' % str(e)[:100]
|
||||
'reason': '发生错误, %s' % str(traceback.format_exc())
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
f.write(str(e) + str(traceback.format_exc()))
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 判断用户账户余额是否足够支付
|
||||
try:
|
||||
@ -303,7 +503,7 @@ async def get_baidu_orderlist(ns={}):
|
||||
|
||||
if round(total_price,2) <= count:
|
||||
#判断预付费或者后付费
|
||||
if productType == 'prepay':
|
||||
if productType == 'prepay' or productType == 'postpay':
|
||||
# 调用扣费接口
|
||||
affirmbz_order_ns = {
|
||||
'sor': sor,
|
||||
@ -318,12 +518,13 @@ async def get_baidu_orderlist(ns={}):
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '支付错误, 请联系售后'
|
||||
'reason': '支付错误, 请联系售后, %s' % affirmbz_order_res.get('msg')
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '支付错误, 请联系售后'
|
||||
'msg': '支付错误, 请联系售后,',
|
||||
'data': affirmbz_order_res
|
||||
}
|
||||
|
||||
# 预配置local_refund用于本地操作
|
||||
@ -334,22 +535,21 @@ async def get_baidu_orderlist(ns={}):
|
||||
}
|
||||
else:
|
||||
# 调用支付订单接口
|
||||
# paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderId':ns.get('order_id')}
|
||||
# ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
# url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
# method = 'POST'
|
||||
# header = {
|
||||
# "Host": "billing.baidubce.com"
|
||||
# }
|
||||
# header = await get_auth_header(method=method, url=url, header=header)
|
||||
# async with aiohttp_client.request(
|
||||
# method=method,
|
||||
# url=url,
|
||||
# headers=header,
|
||||
# json=paydata) as res:
|
||||
# data_ = await res.json()
|
||||
# if data_ == {'success': True}:
|
||||
if True:
|
||||
paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderId':ns.get('order_id')}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
data_ = await res.json()
|
||||
if data_ == {'success': True}:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
@ -357,12 +557,23 @@ async def get_baidu_orderlist(ns={}):
|
||||
'reason': '购买成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': True,
|
||||
'orderid': bz_ns['id']
|
||||
ns_cron_job = {
|
||||
'id': uuid(),
|
||||
'source': 'baidu',
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': 'buy success'
|
||||
}
|
||||
await sor.C('baidu_cron_job', ns_cron_job)
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'orderid': bz_ns['id']
|
||||
# }
|
||||
else:
|
||||
await sor.rollback()
|
||||
await baidu_order_cancel(
|
||||
{'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
@ -425,92 +636,240 @@ async def get_baidu_orderlist(ns={}):
|
||||
await user_action_record(ns_record)
|
||||
return {'status': False,'msg': '该账号余额不足,无法完成购买'}
|
||||
except Exception as e:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
# 更新资源时间 资源id
|
||||
# if order_type == 'NEW':
|
||||
# await baidu_new_update_resouce(ns)
|
||||
return {
|
||||
'status': True,
|
||||
'orderid': bz_ns.get('id'),
|
||||
'originalprice': bz_ns.get('originalprice'),
|
||||
'servicename': bz_ns.get('servicename'),
|
||||
'amount': total_price
|
||||
}
|
||||
|
||||
async def baidu_confirm_refund_order(ns={}):
|
||||
async def get_order_list_base_page(baidu_id, pageNo=1, pageSize=500):
|
||||
ns = {'queryAccountId': baidu_id, 'pageNo': pageNo, 'pageSize': pageSize}
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/list?%s' % ns_format
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=ns) as res:
|
||||
data_orders = await res.json()
|
||||
return data_orders
|
||||
|
||||
|
||||
async def update_baidu_order_list(ns={}):
|
||||
"""
|
||||
ns = {'queryAccountId': '139fc7a23b314596ad78b6bb8e7c1503', 'orderType': 'REFUND'}
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
refund_status_li = await sor.R('baidu_orders', {'orderid': ns.get('order_id')})
|
||||
refundstatus = refund_status_li[0]['refundstatus']
|
||||
refund_id = refund_status_li[0]['id']
|
||||
username = None
|
||||
# 更新机构下全部用户订单信息
|
||||
if ns.get('orgid'):
|
||||
users_find_sql = """SELECT DISTINCT b.baidu_id FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0';""" % ns.get('orgid')
|
||||
users = await sor.sqlExe(users_find_sql, {})
|
||||
|
||||
if not refundstatus:
|
||||
# data_ = {}
|
||||
# 调用支付订单接口
|
||||
paydata = {'queryAccountId': ns.get('baidu_id'), 'orderId':ns.get('order_id')}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
data_ = await res.json()
|
||||
if data_ == {'success': True}:
|
||||
# if True:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '远程退款成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '1'})
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(10)
|
||||
# 更新个人订单信息
|
||||
elif ns.get('userid'):
|
||||
users = await sor.R('baidu_users', {'user_id': ns['userid']})
|
||||
username_li = await sor.R('users', {'id': ns['userid']})
|
||||
username = username_li[0]['username'] if username_li else None
|
||||
else:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '产品退费失败, %s' % str(data_)[:400]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品退款出错!%s' % str(data_)[:400]
|
||||
}
|
||||
users = []
|
||||
|
||||
update_count = 0
|
||||
add_count = 0
|
||||
for baidu_id in users:
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=1, pageSize=1000)
|
||||
page_num_count = int(data_orders['totalCount'] / data_orders['pageSize']) + 1
|
||||
for page_num in range(1, page_num_count + 1):
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=page_num, pageSize=1000)
|
||||
orders = data_orders['orders']
|
||||
for item in orders:
|
||||
updatetime = await time_convert(item.get('updateTime')) if item.get('updateTime') else None
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"orderid": item.get("uuid"),
|
||||
"ordertype": item.get("type"),
|
||||
"accountid": item.get("accountId"),
|
||||
"servicetype": item.get("serviceType"),
|
||||
"producttype": item.get("productType"),
|
||||
"shortids": ','.join(item['shortIds']) if item.get('shortIds') else '',
|
||||
"price": item.get("price"),
|
||||
"status": item.get("status"),
|
||||
"autoreneworder": '1' if item.get("autoRenewOrder") else '0',
|
||||
"createtime": await time_convert(item.get('createTime')) if item.get(
|
||||
'createTime') else None,
|
||||
"updatetime": updatetime
|
||||
}
|
||||
ns_exist_order = {
|
||||
'orderid': item.get("uuid")
|
||||
}
|
||||
exist_order = await sor.R('baidu_orders', ns_exist_order)
|
||||
if exist_order and exist_order[0]['updatetime'] != updatetime:
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(item.get("price"), item.get("status"), updatetime,
|
||||
item.get("uuid"))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
update_count += 1
|
||||
|
||||
if not exist_order:
|
||||
await sor.C('baidu_orders', ns_dic)
|
||||
add_count += 1
|
||||
|
||||
if refundstatus == '2':
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '已退款成功'
|
||||
'msg': '同步数据成功, 新增 %s 条, 更新 %s 条' % (add_count, update_count),
|
||||
'data': {
|
||||
'username': username
|
||||
}
|
||||
}
|
||||
|
||||
# 获取created状态后再去退款
|
||||
local_refund_status = await get_baidu_orderlist({'order_id': ns.get('order_id'), 'userid': ns.get('user_id')})
|
||||
print('local_refund_status', local_refund_status)
|
||||
if local_refund_status.get('status'):
|
||||
async def baidu_confirm_refund_order(ns={}):
|
||||
# ns = {
|
||||
# 'order_id': ["2996f0baf34c4a0a98e1da0b4e290a35"],
|
||||
# 'userid': 'y_xQK0G62dtZT5EneMQFT'
|
||||
# }
|
||||
import asyncio
|
||||
# 把 NEED_CONFIRM的订单同步到本地库,用于后续状态更新
|
||||
await update_baidu_order_list({'userid': ns.get('userid')})
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
users = await sor.R('baidu_users', {'user_id': ns['userid']})
|
||||
ns['baidu_id'] = users[0]['baidu_id'] if users else None
|
||||
if not ns['baidu_id']:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '用户 %s 未绑定百度智能云账号' % ns.get('userid')
|
||||
}
|
||||
|
||||
orders = json.loads(ns.get('order_id')) if isinstance(ns.get('order_id'), str) else ns.get('order_id')
|
||||
|
||||
for order_id in orders:
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '2'})
|
||||
refund_status_li = await sor.R('baidu_orders', {'orderid': order_id})
|
||||
refundstatus = refund_status_li[0]['refundstatus']
|
||||
refund_id = refund_status_li[0]['id']
|
||||
|
||||
ns_record_li = await sor.R('user_action', {'orderid': order_id})
|
||||
ns_record_id = ns_record_li[0]['id'] if ns_record_li else None
|
||||
ns_record = {'id': ns_record_id} if ns_record_id else None
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '百度云给平台退款成功,平台给客户退款成功'
|
||||
}
|
||||
else:
|
||||
if local_refund_status.get('msg') == 'delay_order':
|
||||
if not refundstatus:
|
||||
# data_ = {}
|
||||
# 调用支付订单接口
|
||||
paydata = {'queryAccountId': ns.get('baidu_id'), 'orderId': order_id}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
data_ = await res.json()
|
||||
if data_ == {'success': True}:
|
||||
# if True:
|
||||
ns_record = {
|
||||
'id': uuid(),
|
||||
'orderid': order_id,
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '远程退款成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '1'})
|
||||
|
||||
# 增加延迟
|
||||
await asyncio.sleep(4)
|
||||
|
||||
# 延迟2-3秒还是获取到 ready状态的订单,那就重复请求一次,目的是尽快刷新状态
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
await res.json()
|
||||
|
||||
# 把 NEED_CONFIRM的本地库改为CREATED
|
||||
await update_baidu_order_list({'userid': ns.get('userid')})
|
||||
else:
|
||||
ns_record = {
|
||||
'orderid': order_id,
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '产品退费失败, %s' % str(data_)[:400]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品退款出错!%s' % str(data_)[:400]
|
||||
}
|
||||
|
||||
if refundstatus == '2':
|
||||
"""
|
||||
退款状态为2, 说明退款成功, 无需继续处理
|
||||
"""
|
||||
continue
|
||||
|
||||
# 获取created状态后再去退款
|
||||
local_refund_status = await get_baidu_orderlist({'order_id': order_id, 'userid': ns.get('userid')})
|
||||
print('local_refund_status', local_refund_status)
|
||||
if local_refund_status.get('status'):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_orders_status_update = """update baidu_orders set refundstatus='2' where id='%s';""" % refund_id
|
||||
await sor.sqlExe(baidu_orders_status_update, {})
|
||||
await sor.U('user_action', {'id': ns_record.get('id'), 'ordertype': 'REFUND', 'reason': '远程退款成功, 本地客户退款成功'})
|
||||
continue
|
||||
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'msg': '百度云给平台退款成功,平台给客户退款成功'
|
||||
# }
|
||||
else:
|
||||
if local_refund_status.get('msg') == 'delay_order':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度远程订单还未生成, 请十秒后重试, %s' % str(local_refund_status)
|
||||
}
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度远程订单还未生成, 请十秒后重试'
|
||||
'msg': '百度云退款成功,本机构给客户退款出错!, %s' % str(local_refund_status)
|
||||
}
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度云退款成功,本机构给客户退款出错!'
|
||||
}
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '退款处理完成'
|
||||
}
|
||||
|
||||
ret = await baidu_confirm_refund_order(params_kw)
|
||||
return ret
|
||||
29
b/baiduc/baidu_order_cancel.dspy
Normal file
29
b/baiduc/baidu_order_cancel.dspy
Normal file
@ -0,0 +1,29 @@
|
||||
async def baidu_order_cancel(ns={}):
|
||||
baidu_id = ns['baidu_id']
|
||||
order_id = ns['order_id']
|
||||
paydata = {'queryAccountId': baidu_id, 'orderIds': [order_id]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
res = await res.json()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if res.get('success'):
|
||||
sql_update = "update baidu_orders set status='CANCELLED' where order_id='%s'" % order_id
|
||||
await sor.sqlExe(sql_update, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'order cancel success, %s' % str(res)
|
||||
}
|
||||
|
||||
ret = await baidu_order_cancel(params_kw)
|
||||
return ret
|
||||
@ -6,143 +6,163 @@ async def time_convert(resoucetime=None):
|
||||
return beijing_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
async def baidu_sms_kafka_consumer(ns={}):
|
||||
consumer = BaiduKafKaConsumer({
|
||||
# 接入点
|
||||
'bootstrap.servers': '120.48.10.223:9095,180.76.96.108:9095,180.76.147.36:9095',
|
||||
# 接入协议
|
||||
'security.protocol': 'SASL_SSL',
|
||||
'ssl.endpoint.identification.algorithm': 'none',
|
||||
# 证书文件路径
|
||||
'ssl.ca.location': 'baidu_kafka_ca.pem',
|
||||
# SASL 机制
|
||||
'sasl.mechanism': 'SCRAM-SHA-512',
|
||||
# SASL 用户名
|
||||
'sasl.username': 'kaiyuanyun',
|
||||
# SASL 用户密码
|
||||
'sasl.password': 'Kyy250609#',
|
||||
# 消费组id
|
||||
'group.id': 'kaiyuanyun_msg_group',
|
||||
'auto.offset.reset': 'latest',
|
||||
'fetch.message.max.bytes': '1024*512',
|
||||
})
|
||||
# consumer = BaiduKafKaConsumer({
|
||||
# # 接入点
|
||||
# 'bootstrap.servers': '120.48.10.223:9095,180.76.96.108:9095,180.76.147.36:9095',
|
||||
# # 接入协议
|
||||
# 'security.protocol': 'SASL_SSL',
|
||||
# 'ssl.endpoint.identification.algorithm': 'none',
|
||||
# # 证书文件路径
|
||||
# 'ssl.ca.location': 'baidu_kafka_ca.pem',
|
||||
# # SASL 机制
|
||||
# 'sasl.mechanism': 'SCRAM-SHA-512',
|
||||
# # SASL 用户名
|
||||
# 'sasl.username': 'kaiyuanyun',
|
||||
# # SASL 用户密码
|
||||
# 'sasl.password': 'Kyy250609#',
|
||||
# # 消费组id
|
||||
# 'group.id': 'kaiyuanyun_msg_group',
|
||||
# 'auto.offset.reset': 'latest',
|
||||
# 'fetch.message.max.bytes': '1024*512',
|
||||
# })
|
||||
|
||||
# 订阅的主题名称
|
||||
consumer.subscribe(['kaiyuanyun_msg_topic'])
|
||||
|
||||
for i in range(30):
|
||||
msg = consumer.poll(0.1) # 单次轮询获取消息
|
||||
|
||||
if msg is None:
|
||||
continue
|
||||
elif msg.error():
|
||||
print(f"消费者错误: {msg.error()}")
|
||||
# # 订阅的主题名称
|
||||
# consumer.subscribe(['kaiyuanyun_msg_topic'])
|
||||
|
||||
import os
|
||||
|
||||
files = ["baidu_kafka_msg.txt", "baidu_kafka_id.txt", "baidu_kafka_error.txt"]
|
||||
for filename in files:
|
||||
if not os.path.exists(filename):
|
||||
with open(filename, 'w', encoding='utf-8') as f: # 'w' 模式会覆盖已有文件,但检查后使用是安全的
|
||||
pass # 创建空文件
|
||||
else:
|
||||
try:
|
||||
# 解析消息内容为字典(避免变量名冲突)
|
||||
msg_data_ori = json.loads(msg.value().decode('utf-8'))
|
||||
msg_data = msg_data_ori['messages'][0]
|
||||
messageid = msg_data.get('id')
|
||||
taskid = msg_data.get('taskId')
|
||||
pass
|
||||
|
||||
msg = ns.get('msg')
|
||||
|
||||
# if msg.error():
|
||||
# # 写入日志文件记录错误信息
|
||||
# with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f:
|
||||
# f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n")
|
||||
# else:
|
||||
try:
|
||||
# 解析消息内容为字典(避免变量名冲突)
|
||||
# msg_data_ori = json.loads(msg.value().decode('utf-8'))
|
||||
msg_data_ori = json.loads(msg)
|
||||
msg_data = msg_data_ori['messages'][0]
|
||||
messageid = msg_data.get('id')
|
||||
taskid = msg_data.get('taskId')
|
||||
|
||||
filename = 'baidu_kafka_msg.txt'
|
||||
# 检查文件是否存在,不存在则创建
|
||||
if not os.path.exists(filename):
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
print(f"文件不存在,已创建 {filename}")
|
||||
# 读取文件内容进行检查
|
||||
with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 读取文件内容进行检查
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
if messageid in content:
|
||||
print(f"文件中已存在 '{messageid}',跳过写入")
|
||||
return
|
||||
else:
|
||||
# 追加写入目标内容
|
||||
with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(messageid + '\n')
|
||||
print(f"已写入 '{messageid}' 到文件")
|
||||
|
||||
with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(str(msg_data) + '\n')
|
||||
|
||||
if messageid in content:
|
||||
print(f"文件中已存在 '{messageid}',跳过写入")
|
||||
continue
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 1. 去重检查(messageid和taskid)
|
||||
exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid})
|
||||
if exist_msg:
|
||||
print(f"消息id {messageid} 已存在,跳过处理")
|
||||
return
|
||||
|
||||
# 2. 构建小写key的ns字典(完整映射所有字段)
|
||||
ns_msg = {
|
||||
'id': uuid(),
|
||||
'messageid': messageid,
|
||||
'taskid': taskid,
|
||||
'userid': msg_data.get('userId'),
|
||||
'accountid': msg_data.get('accountId'),
|
||||
'usertype': msg_data.get('userType'),
|
||||
'receiverid': msg_data.get('receiverId'),
|
||||
'contentvar': msg_data.get('contentVar'),
|
||||
'sendchannel': msg_data.get('sendChannel'),
|
||||
'content': msg_data.get('content'),
|
||||
'messagetemplateid': msg_data.get('messageTemplateId'),
|
||||
'isvirtualstore': msg_data.get('isVirtualStore'),
|
||||
'channelmessageid': msg_data.get('channelMessageId'),
|
||||
'channelstatus': msg_data.get('channelStatus'),
|
||||
'majorcategory': msg_data.get('majorCategory'),
|
||||
'minorcategory': msg_data.get('minorCategory'),
|
||||
'status': msg_data.get('status'),
|
||||
'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None,
|
||||
'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None,
|
||||
'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None,
|
||||
'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None,
|
||||
'valid': msg_data.get('valid'),
|
||||
'complete': msg_data.get('complete'),
|
||||
'disturbhold': msg_data.get('disturbHold'),
|
||||
'sendcomplete': msg_data.get('sendComplete')
|
||||
}
|
||||
|
||||
# 3. 执行存库
|
||||
await sor.C('baidu_kafka_msg', ns_msg)
|
||||
print(f"消息id {messageid} 存储成功")
|
||||
|
||||
# 4. 触发短信发送(当sendChannel为MOBILE时)
|
||||
send_channel = msg_data.get('sendChannel')
|
||||
if send_channel == 'MOBILE':
|
||||
msg_content = msg_data.get('content')
|
||||
|
||||
# 判断验证码类短信 | 通知类短信
|
||||
if '验证码' in msg_content:
|
||||
sms_stype = '百度kafka普通验证码'
|
||||
else:
|
||||
# 追加写入目标内容
|
||||
with open(filename, 'a', encoding='utf-8') as f:
|
||||
f.write(messageid + '\n')
|
||||
print(f"已写入 '{messageid}' 到文件")
|
||||
sms_stype = '百度kafka普通通知'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 1. 去重检查(messageid和taskid)
|
||||
exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid})
|
||||
if exist_msg:
|
||||
print(f"消息id {messageid} 已存在,跳过处理")
|
||||
consumer.close()
|
||||
return
|
||||
# 查询用户手机号
|
||||
account_id = msg_data.get('accountId')
|
||||
user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id})
|
||||
if user_local_id_li:
|
||||
user_local_id = user_local_id_li[0]['user_id']
|
||||
user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'})
|
||||
mobile = user_mobile_li[0]['mobile']
|
||||
|
||||
# 2. 构建小写key的ns字典(完整映射所有字段)
|
||||
ns_msg = {
|
||||
'id': uuid(),
|
||||
'messageid': messageid,
|
||||
'taskid': taskid,
|
||||
'userid': msg_data.get('userId'),
|
||||
'accountid': msg_data.get('accountId'),
|
||||
'usertype': msg_data.get('userType'),
|
||||
'receiverid': msg_data.get('receiverId'),
|
||||
'contentvar': msg_data.get('contentVar'),
|
||||
'sendchannel': msg_data.get('sendChannel'),
|
||||
'content': msg_data.get('content'),
|
||||
'messagetemplateid': msg_data.get('messageTemplateId'),
|
||||
'isvirtualstore': msg_data.get('isVirtualStore'),
|
||||
'channelmessageid': msg_data.get('channelMessageId'),
|
||||
'channelstatus': msg_data.get('channelStatus'),
|
||||
'majorcategory': msg_data.get('majorCategory'),
|
||||
'minorcategory': msg_data.get('minorCategory'),
|
||||
'status': msg_data.get('status'),
|
||||
'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None,
|
||||
'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None,
|
||||
'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None,
|
||||
'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None,
|
||||
'valid': msg_data.get('valid'),
|
||||
'complete': msg_data.get('complete'),
|
||||
'disturbhold': msg_data.get('disturbHold'),
|
||||
'sendcomplete': msg_data.get('sendComplete')
|
||||
}
|
||||
|
||||
# 3. 执行存库
|
||||
await sor.C('baidu_kafka_msg', ns_msg)
|
||||
print(f"消息id {messageid} 存储成功")
|
||||
|
||||
# 4. 触发短信发送(当sendChannel为MOBILE时)
|
||||
send_channel = msg_data.get('sendChannel')
|
||||
if send_channel == 'MOBILE':
|
||||
msg_content = msg_data.get('content')
|
||||
|
||||
# 判断验证码类短信 | 通知类短信
|
||||
if '验证码' in msg_content:
|
||||
sms_stype = '百度kafka普通验证码'
|
||||
else:
|
||||
sms_stype = '百度kafka普通通知'
|
||||
|
||||
# 查询用户手机号
|
||||
account_id = msg_data.get('accountId')
|
||||
user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id})
|
||||
user_local_id = user_local_id_li[0]['user_id']
|
||||
user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'})
|
||||
mobile = user_mobile_li[0]['mobile']
|
||||
|
||||
# 调用短信发送接口
|
||||
kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content})
|
||||
if kyy_send_status.get('status'):
|
||||
await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'})
|
||||
print(f"已触发短信发送至 {mobile}")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print("错误:消息内容非有效JSON")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '错误:消息内容非有效JSON'
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"处理异常: {str(e)}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"处理异常: {str(e)}"
|
||||
}
|
||||
|
||||
consumer.close() # 确保消费者关闭
|
||||
# 调用短信发送接口
|
||||
kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content})
|
||||
if kyy_send_status.get('status'):
|
||||
await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'})
|
||||
else:
|
||||
# 记录错误日志 短信发送失败
|
||||
with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n")
|
||||
print(f"短信发送失败至 {mobile},状态: {kyy_send_status}")
|
||||
else:
|
||||
# 记录错误日志 用户未找到
|
||||
with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n")
|
||||
print(f"未找到百度用户ID {account_id} 对应的本地用户")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print("错误:消息内容非有效JSON")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '错误:消息内容非有效JSON'
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"处理异常: {str(e)}")
|
||||
import traceback
|
||||
with open('baidu_kafka_error.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
traceback.print_exc()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"处理异常: {str(e)}"
|
||||
}
|
||||
|
||||
# consumer.close() # 确保消费者关闭
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '获取信息执行结束'
|
||||
|
||||
@ -645,8 +645,8 @@ async def baidu_users_get_post_pay(ns={}):
|
||||
userid = baidu_user['user_id']
|
||||
baidu_id = baidu_user['baidu_id']
|
||||
|
||||
# if baidu_id != 'dcf0fa1519d24de893b186e52d733bd2':
|
||||
# continue
|
||||
if baidu_id != 'a6f0dbc20f074ea18b4d3ac3ec77d537':
|
||||
continue
|
||||
try:
|
||||
user_orgid = (await sor.R('users', {'id': userid}))[0]['orgid']
|
||||
user_parentid = (await sor.R('organization', {'id': user_orgid}))[0]['parentid']
|
||||
|
||||
53
b/baiduc/update_user_orders_interval.dspy
Normal file
53
b/baiduc/update_user_orders_interval.dspy
Normal file
@ -0,0 +1,53 @@
|
||||
async def update_user_orders_interval(ns={}):
|
||||
"""
|
||||
更新用户订单列表
|
||||
"""
|
||||
domain_name = ns.get('domain_name')
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
sql = """select bo.orderid, bs.user_id from baidu_orders as bo inner join baidu_users as bs on bo.accountid = bs.baidu_id inner join users as u on bs.user_id = u.id inner join organization as o on o.id = u.orgid where o.parentid = '%s' and bo.ordertype = 'RENEW' and bo.status = 'NEED_CONFIRM' and bo.del_flg = '0';""" % ns.get('orgid')
|
||||
order_list = await sor.sqlExe(sql, {})
|
||||
try:
|
||||
for order in order_list:
|
||||
orderid = order['orderid']
|
||||
user_id = order['user_id']
|
||||
url = 'https://%s/baiducloud/get_baidu_orderlist.dspy' % domain_name
|
||||
params = {
|
||||
'order_id': orderid,
|
||||
'userid': user_id
|
||||
}
|
||||
method = 'POST'
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
json=params) as res:
|
||||
order_result = await res.text()
|
||||
with open('update_baidu_renew.log', 'a+') as f:
|
||||
# 行首添加时间
|
||||
f.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ' ' + orderid + ':' + order_result + '\n')
|
||||
|
||||
url_update = 'https://%s/baiduc/update_baidu_order_list.dspy' % domain_name
|
||||
params_update = {
|
||||
'orgid': ns.get('orgid')
|
||||
}
|
||||
method = 'POST'
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url_update,
|
||||
json=params_update) as res:
|
||||
data_text = await res.text()
|
||||
with open('update_baidu_renew.log', 'a+') as f:
|
||||
# 行首添加时间
|
||||
f.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ' ' + data_text + '\n')
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '更新成功'
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
with open('update_baidu_renew.log', 'a+') as f:
|
||||
f.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ' ' + str(e) + traceback.format_exc() + '\n')
|
||||
traceback.print_exc()
|
||||
|
||||
ret = await update_user_orders_interval(params_kw)
|
||||
return ret
|
||||
@ -1,7 +1,68 @@
|
||||
async def create_baiduuser(ns):
|
||||
"""
|
||||
ns = {
|
||||
"name": "用户名",
|
||||
"email": "邮箱",
|
||||
"mobilePhone": "手机号",
|
||||
"accountType": "0"为个人|“1”为企业
|
||||
}
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
user = await sor.R('users',{'id':ns.get('userid')})
|
||||
data = {'name':user[0]['username'],'mobilePhone':user[0]['mobile'],'accountType':'0'}
|
||||
method = "POST"
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://iam.bj.baidubce.com/v1/vs/account?%s' % ns_format
|
||||
header = {
|
||||
"Host": "iam.bj.baidubce.com",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=data) as res:
|
||||
data_ = await res.json()
|
||||
if not data_.get('userId'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '创建用户失败',
|
||||
'data': data_
|
||||
}
|
||||
else:
|
||||
#用户创建成功
|
||||
userdata = {
|
||||
'id' : uuid(),
|
||||
# 'id' : UUID(),
|
||||
'user_id' : ns.get('userid'),
|
||||
'baidu_id' : data_.get('userId'),
|
||||
'baidu_username' : data_.get('name'),
|
||||
}
|
||||
await sor.C('baidu_users',userdata)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '创建用户成功',
|
||||
'data': data_
|
||||
}
|
||||
|
||||
|
||||
async def get_baiduQualifyInfo(ns):
|
||||
"""
|
||||
获取百度实名认证接口
|
||||
"""
|
||||
db_baidu = DBPools()
|
||||
async with db_baidu.sqlorContext('kboss') as sor:
|
||||
user = await sor.R('baidu_users', {'user_id': ns.get('user_id'), 'del_flg': '0'})
|
||||
if not user:
|
||||
res = await create_baiduuser({'userid': ns.get('user_id')})
|
||||
if not res.get('status'):
|
||||
return res
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
user = await sor.R('baidu_users',{'user_id':ns.get('user_id')})
|
||||
@ -23,11 +84,11 @@ async def get_baiduQualifyInfo(ns):
|
||||
json=ns) as res:
|
||||
data_ = await res.json()
|
||||
if data_['qualifyType'] != None and data_['status'] == 'PASS':
|
||||
return {'status': True, 'msg': '实名认证通过'}
|
||||
return {'status': True, 'msg': '实名认证通过', 'data': data_}
|
||||
else:
|
||||
return {'status': False, 'msg': '实名认证未通过'}
|
||||
return {'status': False, 'msg': '实名认证未通过', 'data': data_}
|
||||
else:
|
||||
return {'status': False, 'msg': '百度用户创建失败'}
|
||||
return {'status': False, 'msg': 'user not exist, please create baidu user first'}
|
||||
|
||||
ret = await get_baiduQualifyInfo(params_kw)
|
||||
return ret
|
||||
@ -1,6 +1,7 @@
|
||||
async def user_action_record(ns={}):
|
||||
ns_dic_id = uuid() if not ns.get('id') else ns.get('id')
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'id': ns_dic_id,
|
||||
'source': '百度智能云',
|
||||
'orderid': ns.get('orderid'),
|
||||
'ordertype': ns.get('ordertype'),
|
||||
@ -41,7 +42,7 @@ async def affirmbz_order(ns={}):
|
||||
orgid = await sor.R('bz_order', {'id': ns['orderid']})
|
||||
|
||||
servicename = orgid[0]['servicename']
|
||||
# product_url = None
|
||||
product_url = None
|
||||
# if ('BCC' in servicename) or ('GPU' in servicename):
|
||||
# product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
|
||||
|
||||
@ -76,13 +77,17 @@ async def affirmbz_order(ns={}):
|
||||
# 处理续费逻辑
|
||||
elif order_type == 'RENEW':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where resourceid = '%s' and del_flg = '0';""" % j['resourceids']
|
||||
resource_find_sql = """select id from customer_goods where FIND_IN_SET('%s', resourceid) and del_flg = '0';""" % j['resourceids']
|
||||
resource_find_li = await sor.sqlExe(resource_find_sql, {})
|
||||
resource_find_id = resource_find_li[0]['id']
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'start_date': j['resourcestarttime'], 'expire_date': j['resourceendtime']})
|
||||
|
||||
# 处理购买逻辑
|
||||
else:
|
||||
if j.get('chargemode') == 'postpay' and j.get('orderkey') == 'snapshot':
|
||||
# 快照后付费不创建客户产品记录
|
||||
continue
|
||||
|
||||
product = await sor.R('product', {'id': j['productid']})
|
||||
nss = {}
|
||||
nss['id'] = uuid()
|
||||
@ -109,7 +114,7 @@ async def affirmbz_order(ns={}):
|
||||
await sor.C('customer_goods', nss)
|
||||
return {'status': True, 'msg': '支付成功'}
|
||||
except Exception as error:
|
||||
raise error
|
||||
return {'status': False, 'msg': str(error)}
|
||||
|
||||
async def baidu_new_update_resouce(ns={}):
|
||||
|
||||
@ -197,6 +202,178 @@ async def baidu_order_cancel(ns={}):
|
||||
'status': True,
|
||||
'msg': 'order cancel success'
|
||||
}
|
||||
|
||||
async def baidu_confirm_refund_order(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
refund_status_li = await sor.R('baidu_orders', {'orderid': ns.get('order_id')})
|
||||
refundstatus = refund_status_li[0]['refundstatus']
|
||||
refund_id = refund_status_li[0]['id']
|
||||
|
||||
if not refundstatus:
|
||||
# data_ = {}
|
||||
# 调用支付订单接口
|
||||
paydata = {'queryAccountId': ns.get('baidu_id'), 'orderId':ns.get('order_id')}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
|
||||
method = 'POST'
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=paydata) as res:
|
||||
data_ = await res.json()
|
||||
if data_ == {'success': True}:
|
||||
# if True:
|
||||
ns_record = {
|
||||
'id': uuid(),
|
||||
'orderid': order_id,
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '远程退款成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '1'})
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(1)
|
||||
else:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '产品退费失败, %s' % str(data_)[:400]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品退款出错!%s' % str(data_)[:400]
|
||||
}
|
||||
|
||||
if refundstatus == '2':
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '已退款成功'
|
||||
}
|
||||
|
||||
# 获取created状态后再去退款
|
||||
local_refund_status = await get_baidu_orderlist({'order_id': ns.get('order_id'), 'userid': ns.get('user_id')})
|
||||
print('local_refund_status', local_refund_status)
|
||||
if local_refund_status.get('status'):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '2'})
|
||||
await sor.U('user_action', {'id': ns_record.get('id'), 'ordertype': 'REFUND', 'reason': '远程退款成功, 本地客户退款成功'})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '百度云给平台退款成功,平台给客户退款成功'
|
||||
}
|
||||
else:
|
||||
if local_refund_status.get('msg') == 'delay_order':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度远程订单还未生成, 请十秒后重试'
|
||||
}
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度云退款成功,本机构给客户退款出错!, %s' % str(local_refund_status)
|
||||
}
|
||||
|
||||
async def get_order_list_base_page(baidu_id, pageNo=1, pageSize=500):
|
||||
ns = {'queryAccountId': baidu_id, 'pageNo': pageNo, 'pageSize': pageSize}
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/list?%s' % ns_format
|
||||
header = {
|
||||
"Host": "billing.baidubce.com",
|
||||
"ContentType": "application/json;charset=UTF-8"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=ns) as res:
|
||||
data_orders = await res.json()
|
||||
return data_orders
|
||||
|
||||
|
||||
async def update_baidu_order_list(ns={}):
|
||||
"""
|
||||
ns = {'queryAccountId': '139fc7a23b314596ad78b6bb8e7c1503', 'orderType': 'REFUND'}
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
username = None
|
||||
# 更新机构下全部用户订单信息
|
||||
if ns.get('orgid'):
|
||||
users_find_sql = """SELECT DISTINCT b.baidu_id FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0';""" % ns.get('orgid')
|
||||
users = await sor.sqlExe(users_find_sql, {})
|
||||
|
||||
# 更新个人订单信息
|
||||
elif ns.get('userid'):
|
||||
users = await sor.R('baidu_users', {'user_id': ns['userid']})
|
||||
username_li = await sor.R('users', {'id': ns['userid']})
|
||||
username = username_li[0]['username'] if username_li else None
|
||||
else:
|
||||
users = []
|
||||
|
||||
update_count = 0
|
||||
add_count = 0
|
||||
for baidu_id in users:
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=1, pageSize=1000)
|
||||
page_num_count = int(data_orders['totalCount'] / data_orders['pageSize']) + 1
|
||||
for page_num in range(1, page_num_count + 1):
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=page_num, pageSize=1000)
|
||||
orders = data_orders['orders']
|
||||
for item in orders:
|
||||
updatetime = await time_convert(item.get('updateTime')) if item.get('updateTime') else None
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"orderid": item.get("uuid"),
|
||||
"ordertype": item.get("type"),
|
||||
"accountid": item.get("accountId"),
|
||||
"servicetype": item.get("serviceType"),
|
||||
"producttype": item.get("productType"),
|
||||
"shortids": ','.join(item['shortIds']) if item.get('shortIds') else '',
|
||||
"price": item.get("price"),
|
||||
"status": item.get("status"),
|
||||
"autoreneworder": '1' if item.get("autoRenewOrder") else '0',
|
||||
"createtime": await time_convert(item.get('createTime')) if item.get(
|
||||
'createTime') else None,
|
||||
"updatetime": updatetime
|
||||
}
|
||||
ns_exist_order = {
|
||||
'orderid': item.get("uuid")
|
||||
}
|
||||
exist_order = await sor.R('baidu_orders', ns_exist_order)
|
||||
if exist_order and exist_order[0]['updatetime'] != updatetime:
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(item.get("price"), item.get("status"), updatetime,
|
||||
item.get("uuid"))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
update_count += 1
|
||||
|
||||
if not exist_order:
|
||||
await sor.C('baidu_orders', ns_dic)
|
||||
add_count += 1
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '同步数据成功, 新增 %s 条, 更新 %s 条' % (add_count, update_count),
|
||||
'data': {
|
||||
'username': username
|
||||
}
|
||||
}
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
@ -207,7 +384,7 @@ async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(2)
|
||||
await asyncio.sleep(1)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
|
||||
@ -235,10 +412,9 @@ async def get_baidu_orderlist(ns={}):
|
||||
|
||||
# 可能获取得到的是延迟订单
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delay_order'
|
||||
}
|
||||
await update_baidu_order_list({'userid': ns.get('userid')})
|
||||
res_refund = await baidu_confirm_refund_order({'order_id': ns.get('order_id'), 'baidu_id': baidu_users[0]['baidu_id'], 'user_id': ns.get('userid')})
|
||||
return res_refund
|
||||
|
||||
# 避免重复退订
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED':
|
||||
@ -273,7 +449,7 @@ async def get_baidu_orderlist(ns={}):
|
||||
# 获取余额
|
||||
user_balance = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
# 判断余额是否大于50
|
||||
if user_balance < 50:
|
||||
if user_balance < 5000000:
|
||||
await sor.rollback()
|
||||
paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]}
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
@ -293,12 +469,14 @@ async def get_baidu_orderlist(ns={}):
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '后付费 该账号余额不足50,无法完成购买'
|
||||
# 'reason': '后付费 该账号余额不足50,无法完成购买'
|
||||
'reason': '后付费 功能暂未开放,请您联系售后人员协助购买'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值'
|
||||
'msg': '后付费 功能暂未开放,请您联系售后人员协助购买'
|
||||
# 'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值'
|
||||
}
|
||||
# 实付价格
|
||||
total_price = 0
|
||||
@ -410,10 +588,26 @@ async def get_baidu_orderlist(ns={}):
|
||||
nss['unit'] = i.get('timeUnit')
|
||||
nss['resourceids'] = ','.join(i['shortIds']) if i.get('shortIds') else ''
|
||||
nss['orderkey'] = i.get('key')
|
||||
|
||||
|
||||
try:
|
||||
# 保存配置configurations 存入specdata表中
|
||||
if i.get('configurations'):
|
||||
specdata = json.dumps(i['configurations'], ensure_ascii=False)
|
||||
ns_specificdata = {
|
||||
'id': uuid(),
|
||||
'productid': product[0]['id'],
|
||||
'spec_data': specdata,
|
||||
}
|
||||
nss['spec_id'] = ns_specificdata['id']
|
||||
await sor.C('specificdata', ns_specificdata)
|
||||
except Exception as e:
|
||||
print('保存配置configurations失败', str(e))
|
||||
with open('baidu_error.log', 'a') as f:
|
||||
f.write('保存配置configurations失败' + str(e) + '\n')
|
||||
|
||||
# 如果是续费订单 由于没有返回日期, 重新计算日期
|
||||
if order_type == 'RENEW':
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where resourceids = '%s' order by resourceendtime desc;" % \
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where FIND_IN_SET('%s', resourceids) order by resourceendtime desc;" % \
|
||||
nss['resourceids']
|
||||
history_time = await sor.sqlExe(history_time_sql, {})
|
||||
new_end_time = await cal_expire_time(history_time=history_time[0]['resourceendtime'],
|
||||
@ -445,16 +639,16 @@ async def get_baidu_orderlist(ns={}):
|
||||
await sor.U('bz_order', {'id': bz_ns['id'], 'amount': round(total_price, 2)})
|
||||
except Exception as e:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
import traceback
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '发生错误, %s' % str(e)[:100]
|
||||
'reason': '发生错误, %s' % str(traceback.format_exc())
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
f.write(str(e) + str(traceback.format_exc()))
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
@ -485,7 +679,7 @@ async def get_baidu_orderlist(ns={}):
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '支付错误, 请联系售后'
|
||||
'reason': '支付错误, 请联系售后, %s' % affirmbz_order_res.get('msg')
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
|
||||
54
b/bz_order/cumulative_order.dspy
Normal file
54
b/bz_order/cumulative_order.dspy
Normal file
@ -0,0 +1,54 @@
|
||||
async def cumulative_order(ns={}):
|
||||
"""查询订单商品详情,带分页功能"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
users_id = await get_user()
|
||||
if not users_id:
|
||||
server_error(401)
|
||||
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
customerid = orgid[0]['id']
|
||||
|
||||
# 统计全部 累计支付金额和累计优惠金额 不包含各种筛选条件
|
||||
# 累计支付金额=BUY+RENEW-BUY_REVERSE并且对应order_status=1是实际支付金额 累计优惠金额=BUY+RENEW-BUY_REVERSE并且对应order_status=1是优惠金额
|
||||
total_amount_sql = """
|
||||
SELECT
|
||||
COALESCE(SUM(
|
||||
CASE
|
||||
WHEN bo.order_status = 1 AND bo.business_op IN ('BUY', 'RENEW') THEN og.amount
|
||||
WHEN bo.order_status = 1 AND bo.business_op = 'BUY_REVERSE' THEN -og.amount
|
||||
ELSE 0
|
||||
END
|
||||
), 0) AS total_paid_amount,
|
||||
COALESCE(SUM(
|
||||
CASE
|
||||
WHEN bo.order_status = 1 AND bo.business_op IN ('BUY', 'RENEW') THEN (og.list_price * og.quantity - og.amount)
|
||||
WHEN bo.order_status = 1 AND bo.business_op = 'BUY_REVERSE' THEN -(og.list_price * og.quantity - og.amount)
|
||||
ELSE 0
|
||||
END
|
||||
), 0) AS total_discount_amount
|
||||
FROM order_goods og
|
||||
JOIN bz_order bo ON og.orderid = bo.id
|
||||
WHERE og.del_flg = '0'
|
||||
AND bo.del_flg = '0'
|
||||
AND bo.customerid = ${customerid}$
|
||||
"""
|
||||
total_amount_result = await sor.sqlExe(total_amount_sql, {'customerid': customerid})
|
||||
total_paid_amount = float(total_amount_result[0]['total_paid_amount']) if total_amount_result else 0.0
|
||||
total_discount_amount = float(total_amount_result[0]['total_discount_amount']) if total_amount_result else 0.0
|
||||
# 将累计支付金额和累计优惠金额添加到返回结果中
|
||||
ns['total_paid_amount'] = total_paid_amount
|
||||
ns['total_discount_amount'] = total_discount_amount
|
||||
return {
|
||||
'status': True,
|
||||
'data': ns
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'status': False, 'msg': '信息错误: %s' % str(e) + traceback.format_exc()}
|
||||
|
||||
ret = await cumulative_order(params_kw)
|
||||
return ret
|
||||
@ -1,110 +1,198 @@
|
||||
async def getbz_order(ns={}):
|
||||
"""查询订单详情/我的所有订单"""
|
||||
"""查询订单商品详情,带分页功能"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
users_id = await get_user()
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
if ns.get('id') and not ns.get('type'):
|
||||
# 查询订单详情
|
||||
reacs = await sor.R('bz_order', ns)
|
||||
if not users_id:
|
||||
server_error(401)
|
||||
|
||||
# 兼容第三范式产品展示 这段代码可注释
|
||||
if reacs and reacs[0].get('specdataid'):
|
||||
specdata = await sor.R('specificdata', {'id': reacs[0].get('specdataid'), 'del_flg': '0'})
|
||||
if specdata:
|
||||
specdata_dumps = json.dumps(specdata[0]) if isinstance(specdata[0], dict) else specdata[0]
|
||||
if 'internalip' in specdata_dumps and 'externalip' in specdata_dumps:
|
||||
reacs[0]['spec_data'] = json.loads(json.loads(specdata_dumps)['spec_data'])
|
||||
# 分页参数
|
||||
page = int(ns.get('page', 1))
|
||||
size = int(ns.get('size', 10))
|
||||
offset = (page - 1) * size
|
||||
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
customerid = orgid[0]['id']
|
||||
|
||||
params = {'customerid': customerid, 'del_flg': '0'}
|
||||
|
||||
# 构建查询SQL,主要查询order_goods并关联bz_order的部分字段
|
||||
sql = """
|
||||
SELECT
|
||||
og.*,
|
||||
bo.customerid,
|
||||
bo.order_date,
|
||||
bo.source,
|
||||
bo.order_status,
|
||||
bo.business_op,
|
||||
bo.ordertype,
|
||||
bo.originalprice,
|
||||
bo.autoreneworder
|
||||
FROM order_goods og
|
||||
JOIN bz_order bo ON og.orderid = bo.id
|
||||
WHERE og.del_flg = '0'
|
||||
AND bo.del_flg = '0'
|
||||
AND bo.customerid = ${customerid}$
|
||||
"""
|
||||
|
||||
# 构建计数SQL
|
||||
count_sql = """
|
||||
SELECT COUNT(*) as total_count
|
||||
FROM order_goods og
|
||||
JOIN bz_order bo ON og.orderid = bo.id
|
||||
WHERE og.del_flg = '0'
|
||||
AND bo.del_flg = '0'
|
||||
AND bo.customerid = ${customerid}$
|
||||
"""
|
||||
|
||||
# # 统计全部 累计支付金额和累计优惠金额 不包含各种筛选条件
|
||||
# # 累计支付金额=BUY+RENEW-BUY_REVERSE实际支付金额 累计优惠金额=BUY+RENEW-BUY_REVERSE优惠金额
|
||||
# total_amount_sql = """
|
||||
# SELECT
|
||||
# COALESCE(SUM(
|
||||
# CASE
|
||||
# WHEN bo.business_op IN ('BUY', 'RENEW') THEN og.amount
|
||||
# WHEN bo.business_op = 'BUY_REVERSE' THEN -og.amount
|
||||
# ELSE 0
|
||||
# END
|
||||
# ), 0) AS total_paid_amount,
|
||||
# COALESCE(SUM(
|
||||
# CASE
|
||||
# WHEN bo.business_op IN ('BUY', 'RENEW') THEN (og.list_price * og.quantity - og.amount)
|
||||
# WHEN bo.business_op = 'BUY_REVERSE' THEN -(og.list_price * og.quantity - og.amount)
|
||||
# ELSE 0
|
||||
# END
|
||||
# ), 0) AS total_discount_amount
|
||||
# FROM order_goods og
|
||||
# JOIN bz_order bo ON og.orderid = bo.id
|
||||
# WHERE og.del_flg = '0'
|
||||
# AND bo.del_flg = '0'
|
||||
# AND bo.customerid = ${customerid}$
|
||||
# """
|
||||
# total_amount_result = await sor.sqlExe(total_amount_sql, {'customerid': customerid})
|
||||
# total_paid_amount = float(total_amount_result[0]['total_paid_amount']) if total_amount_result else 0.0
|
||||
# total_discount_amount = float(total_amount_result[0]['total_discount_amount']) if total_amount_result else 0.0
|
||||
# # 将累计支付金额和累计优惠金额添加到返回结果中
|
||||
# ns['total_paid_amount'] = total_paid_amount
|
||||
# ns['total_discount_amount'] = total_discount_amount
|
||||
# ns['total_count'] = total_count[0]['total_count'] if total_count else 0
|
||||
|
||||
|
||||
# 根据订单号搜索
|
||||
if ns.get('id'):
|
||||
sql += " AND bo.id LIKE ${order_id}$"
|
||||
count_sql += " AND bo.id LIKE ${order_id}$"
|
||||
params['order_id'] = f"%{ns.get('id')}%"
|
||||
|
||||
# 时间范围查询
|
||||
if ns.get('start_time'):
|
||||
sql += " AND bo.order_date >= ${start_time}$"
|
||||
count_sql += " AND bo.order_date >= ${start_time}$"
|
||||
params['start_time'] = ns.get('start_time') + ' 00:00:00'
|
||||
|
||||
if ns.get('end_time'):
|
||||
sql += " AND bo.order_date <= ${end_time}$"
|
||||
count_sql += " AND bo.order_date <= ${end_time}$"
|
||||
params['end_time'] = ns.get('end_time') + ' 23:59:59'
|
||||
|
||||
# 订单状态查询
|
||||
if ns.get('order_status'):
|
||||
sql += " AND bo.order_status = ${order_status}$"
|
||||
count_sql += " AND bo.order_status = ${order_status}$"
|
||||
params['order_status'] = ns.get('order_status')
|
||||
|
||||
# 业务操作筛选business_op BUY, RENEW, BUY_REVERSE
|
||||
if ns.get('business_op'):
|
||||
sql += " AND bo.business_op = ${business_op}$"
|
||||
count_sql += " AND bo.business_op = ${business_op}$"
|
||||
params['business_op'] = ns.get('business_op')
|
||||
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': ns['id'], 'del_flg': '0'})
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
i['discount'] = i['discount'] * 10 if i.get('discount') else None
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
reacs[0]['order_goods'] = reacsgoods
|
||||
return {'status': True, 'data': reacs}
|
||||
elif ns.get('type') == '200':
|
||||
#筛选支付类型
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
if ns.get('id'):
|
||||
#根据订单号搜索
|
||||
reacs = await sor.R('bz_order', {'id': ns['id']})
|
||||
elif ns.get('start_time'):
|
||||
sql = """select * from bz_order where del_flg = 0 AND customerid = ${customerid}$ AND order_date >= ${start_time}$ AND order_date <= ${end_time}$ ORDER BY order_date DESC """
|
||||
start_time = ns.get('start_time') + ' 00:00:00'
|
||||
end_time = ns.get('end_time') + ' 23:59:59'
|
||||
reacs = await sor.sqlExe(sql, {'start_time': start_time,'end_time': end_time,'customerid' :ns['customerid']})
|
||||
# 添加排序
|
||||
sql += " ORDER BY bo.order_date DESC"
|
||||
|
||||
# 获取总记录数
|
||||
total_result = await sor.sqlExe(count_sql, params)
|
||||
total_count = total_result[0]['total_count'] if total_result else 0
|
||||
|
||||
# 添加分页
|
||||
sql += " LIMIT ${size}$ OFFSET ${offset}$"
|
||||
params['size'] = size
|
||||
params['offset'] = offset
|
||||
|
||||
# 执行查询
|
||||
order_goods_list = await sor.sqlExe(sql, params)
|
||||
|
||||
if not order_goods_list:
|
||||
return {
|
||||
'status': True,
|
||||
'data': [],
|
||||
'pagination': {'page': page, 'size': size, 'total': 0}
|
||||
}
|
||||
|
||||
# 处理数据
|
||||
for item in order_goods_list:
|
||||
# 清理折扣数据
|
||||
if item['discount'] is None or item['discount'] == 1.0:
|
||||
del item['discount']
|
||||
else:
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'order_date desc','order_status':ns.get('order_status'),'del_flg':'0'})
|
||||
all_price = 0
|
||||
if len(reacs) >= 1:
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
countlist_price = 0
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price += i['list_price']
|
||||
countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
j['countprice'] = round(countlist_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs, 'all_price': round(all_price, 2)}
|
||||
else:
|
||||
# 我的所有订单
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'create_at desc','del_flg':'0'})
|
||||
actual_all_price = 0
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
all_price = 0
|
||||
countlist_price = 0
|
||||
business_op = j['business_op']
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
i['discount'] = i['discount'] * 10 if i.get('discount') else None
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) < 1:
|
||||
continue
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price = i['list_price'] * i['quantity']
|
||||
actual_price = i['price'] * i['quantity']
|
||||
# countlist_price += i['list_price']
|
||||
# countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
if business_op != 'BUY_REVERSE':
|
||||
actual_all_price += actual_price
|
||||
j['countprice'] = round(all_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs,'all_price': round(actual_all_price,2)}
|
||||
item['discount'] = item['discount'] * 10 # 转换为百分比显示
|
||||
|
||||
# 处理结果中原价list_price和数量quantity 计算总价
|
||||
if item['list_price'] is None:
|
||||
item['list_price'] = 0
|
||||
if item['quantity'] is None:
|
||||
item['quantity'] = 0
|
||||
item['origin_amout'] = float(item['list_price']) * float(item['quantity'])
|
||||
|
||||
|
||||
# 获取产品名称
|
||||
goods = await sor.R('product', {'id': item['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
item['product_name'] = goods[0]['name']
|
||||
item['product_type'] = goods[0]['ptype']
|
||||
|
||||
# 获取产品配置详情
|
||||
item['spec_data'] = None
|
||||
if item.get('spec_id'):
|
||||
specdata_list = await sor.R('specificdata', {'id': item['spec_id'], 'del_flg': '0'})
|
||||
if specdata_list and specdata_list[0]['spec_data']:
|
||||
item['spec_data'] = json.loads(specdata_list[0]['spec_data'])
|
||||
|
||||
# 格式化订单状态
|
||||
status_mapping = {
|
||||
'0': '未支付',
|
||||
'1': '已支付',
|
||||
'2': '已关闭',
|
||||
'3': '已取消',
|
||||
'4': '后付费'
|
||||
}
|
||||
item['order_status_text'] = status_mapping.get(item['order_status'], '未知状态')
|
||||
|
||||
# 格式化业务操作
|
||||
business_op_mapping = {
|
||||
'BUY': '购买',
|
||||
'RENEW': '续费',
|
||||
'BUY_REVERSE': '退款',
|
||||
# 'UPGRADE': '升级'
|
||||
}
|
||||
item['business_op_text'] = business_op_mapping.get(item['business_op'], item['business_op'])
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'data': order_goods_list,
|
||||
'pagination': {
|
||||
'page': page,
|
||||
'size': size,
|
||||
'total': total_count
|
||||
}
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '信息错误'}
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'status': False, 'msg': '信息错误: %s' % str(e) + traceback.format_exc()}
|
||||
|
||||
ret = await getbz_order(params_kw)
|
||||
return ret
|
||||
110
b/bz_order/getbz_order_old.dspy
Normal file
110
b/bz_order/getbz_order_old.dspy
Normal file
@ -0,0 +1,110 @@
|
||||
async def getbz_order(ns={}):
|
||||
"""查询订单详情/我的所有订单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
users_id = await get_user()
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
if ns.get('id') and not ns.get('type'):
|
||||
# 查询订单详情
|
||||
reacs = await sor.R('bz_order', ns)
|
||||
|
||||
# 兼容第三范式产品展示 这段代码可注释
|
||||
if reacs and reacs[0].get('specdataid'):
|
||||
specdata = await sor.R('specificdata', {'id': reacs[0].get('specdataid'), 'del_flg': '0'})
|
||||
if specdata:
|
||||
specdata_dumps = json.dumps(specdata[0]) if isinstance(specdata[0], dict) else specdata[0]
|
||||
if 'internalip' in specdata_dumps and 'externalip' in specdata_dumps:
|
||||
reacs[0]['spec_data'] = json.loads(json.loads(specdata_dumps)['spec_data'])
|
||||
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': ns['id'], 'del_flg': '0'})
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
i['discount'] = i['discount'] * 10 if i.get('discount') else None
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
reacs[0]['order_goods'] = reacsgoods
|
||||
return {'status': True, 'data': reacs}
|
||||
elif ns.get('type') == '200':
|
||||
#筛选支付类型
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
if ns.get('id'):
|
||||
#根据订单号搜索
|
||||
reacs = await sor.R('bz_order', {'id': ns['id']})
|
||||
elif ns.get('start_time'):
|
||||
sql = """select * from bz_order where del_flg = 0 AND customerid = ${customerid}$ AND order_date >= ${start_time}$ AND order_date <= ${end_time}$ ORDER BY order_date DESC """
|
||||
start_time = ns.get('start_time') + ' 00:00:00'
|
||||
end_time = ns.get('end_time') + ' 23:59:59'
|
||||
reacs = await sor.sqlExe(sql, {'start_time': start_time,'end_time': end_time,'customerid' :ns['customerid']})
|
||||
|
||||
else:
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'order_date desc','order_status':ns.get('order_status'),'del_flg':'0'})
|
||||
all_price = 0
|
||||
if len(reacs) >= 1:
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
countlist_price = 0
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price += i['list_price']
|
||||
countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
j['countprice'] = round(countlist_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs, 'all_price': round(all_price, 2)}
|
||||
else:
|
||||
# 我的所有订单
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'create_at desc','del_flg':'0'})
|
||||
actual_all_price = 0
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
all_price = 0
|
||||
countlist_price = 0
|
||||
business_op = j['business_op']
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
i['discount'] = i['discount'] * 10 if i.get('discount') else None
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) < 1:
|
||||
continue
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price = i['list_price'] * i['quantity']
|
||||
actual_price = i['price'] * i['quantity']
|
||||
# countlist_price += i['list_price']
|
||||
# countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
if business_op != 'BUY_REVERSE':
|
||||
actual_all_price += actual_price
|
||||
j['countprice'] = round(all_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs,'all_price': round(actual_all_price,2)}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '信息错误'}
|
||||
|
||||
ret = await getbz_order(params_kw)
|
||||
return ret
|
||||
39
b/bz_order/todo_info.dspy
Normal file
39
b/bz_order/todo_info.dspy
Normal file
@ -0,0 +1,39 @@
|
||||
async def todo_info(ns={}):
|
||||
"""查询订单待支付,待续费,处理中的信息"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
users_id = await get_user()
|
||||
if not users_id:
|
||||
server_error(401)
|
||||
|
||||
user = await sor.R('users', {'id': users_id, 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
customerid = orgid[0]['id']
|
||||
print(customerid)
|
||||
|
||||
# 查询订单待支付,待续费,处理中的信息
|
||||
pending_payment_orders = await sor.sqlExe(
|
||||
"SELECT COUNT(*) AS count FROM bz_order WHERE customerid = '%s' AND order_status = '0' AND del_flg = '0';" % customerid, {}
|
||||
)
|
||||
ns['pending_payment_orders'] = pending_payment_orders[0]['count'] if pending_payment_orders else 0
|
||||
pending_renew_orders = await sor.sqlExe(
|
||||
"SELECT COUNT(*) AS count FROM bz_order WHERE customerid = '%s' AND order_status = '0' AND del_flg = '0';" % customerid, {}
|
||||
)
|
||||
ns['pending_renew_orders'] = pending_renew_orders[0]['count'] if pending_renew_orders else 0
|
||||
processing_orders = await sor.sqlExe(
|
||||
"SELECT COUNT(*) AS count FROM bz_order WHERE customerid = '%s' AND order_status = '1000' AND del_flg = '0';" % customerid, {}
|
||||
)
|
||||
ns['processing_orders'] = processing_orders[0]['count'] if processing_orders else 0
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'data': ns
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return {'status': False, 'msg': '信息错误: %s' % str(e) + traceback.format_exc()}
|
||||
|
||||
ret = await todo_info(params_kw)
|
||||
return ret
|
||||
@ -1,21 +1,111 @@
|
||||
async def getNoinvitationcode(ns):
|
||||
async def getNoinvitationcode(ns={}):
|
||||
"""展示所有没有销售的客户"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
orgs = await sor.R('organization', {"org_type": '0'})
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
ns['parentid'] = orgs[0]['id']
|
||||
datalist = []
|
||||
prc = await sor.R('customer', {'del_flg': '0'})
|
||||
for i in prc:
|
||||
if not i['salemanid']:
|
||||
customer_id_parentid_li = await sor.R('organization', {'id': i['customerid']})
|
||||
customer_id_parentid = customer_id_parentid_li[0]['parentid']
|
||||
if customer_id_parentid == ns.get('orgid'):
|
||||
datalist.append(customer_id_parentid_li[0])
|
||||
data = {'rows':datalist}
|
||||
return {'status': True, 'data': data}
|
||||
try:
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 获取组织信息
|
||||
orgs = await sor.R('organization', {"org_type": '0'})
|
||||
if not orgs:
|
||||
return {'status': False, 'message': '未找到组织信息'}
|
||||
|
||||
# 获取目标组织ID,优先使用ns中的orgid,否则使用第一个组织的ID
|
||||
target_org_id = ns.get('orgid') or orgs[0]['id']
|
||||
|
||||
# 获取分页参数
|
||||
page = int(ns.get('page', 1)) # 当前页码,默认为1
|
||||
page_size = int(ns.get('size', 10)) # 每页数量,默认为10
|
||||
offset = (page - 1) * page_size # 计算偏移量
|
||||
|
||||
# 获取筛选条件
|
||||
orgname = ns.get('orgname', '').strip() # 组织名称
|
||||
contactor_phone = ns.get('contactor_phone', '').strip() # 联系人电话
|
||||
|
||||
# 构建WHERE条件
|
||||
where_conditions = [
|
||||
"(c.salemanid IS NULL OR c.salemanid = '')",
|
||||
"o.parentid = '%s'",
|
||||
"c.del_flg = '0'",
|
||||
"o.del_flg = '0'"
|
||||
]
|
||||
params = [target_org_id]
|
||||
|
||||
# 添加组织名称模糊查询条件
|
||||
if orgname:
|
||||
where_conditions.append("o.orgname LIKE '%s'")
|
||||
params.append(f"%%{orgname}%%")
|
||||
|
||||
# 添加联系人电话条件
|
||||
if contactor_phone:
|
||||
where_conditions.append("o.contactor_phone LIKE '%s'")
|
||||
params.append(f"%%{contactor_phone}%%")
|
||||
|
||||
where_clause = " AND ".join(where_conditions)
|
||||
|
||||
# 构建查询总数的SQL
|
||||
count_sql = f"""
|
||||
SELECT COUNT(*) as total
|
||||
FROM customer c
|
||||
JOIN organization o ON c.customerid = o.id
|
||||
WHERE {where_clause}
|
||||
"""
|
||||
count_sql = count_sql % tuple(params)
|
||||
# 执行总数查询
|
||||
count_result = await sor.sqlExe(count_sql,{})
|
||||
total = count_result[0]['total'] if count_result else 0
|
||||
|
||||
# 构建查询数据的SQL(添加分页)
|
||||
data_sql = f"""
|
||||
SELECT o.*
|
||||
FROM customer c
|
||||
JOIN organization o ON c.customerid = o.id
|
||||
WHERE {where_clause}
|
||||
ORDER BY o.create_at DESC
|
||||
LIMIT %s OFFSET %s
|
||||
"""
|
||||
|
||||
# 添加分页参数
|
||||
params.extend([page_size, offset])
|
||||
|
||||
data_sql = data_sql % tuple(params)
|
||||
|
||||
# 执行数据查询
|
||||
result = await sor.sqlExe(data_sql, {})
|
||||
|
||||
# 返回结果,包含分页信息
|
||||
return {
|
||||
'status': True,
|
||||
'data': {
|
||||
'rows': result
|
||||
},
|
||||
'pagination': {
|
||||
'page': page,
|
||||
'size': page_size,
|
||||
'total': total
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
# 记录错误日志(可根据实际情况添加日志记录)
|
||||
return {'status': False, 'message': f'查询失败: {str(e)}'}
|
||||
|
||||
|
||||
# async def getNoinvitationcode(ns):
|
||||
# """展示所有没有销售的客户"""
|
||||
# db = DBPools()
|
||||
# async with db.sqlorContext('kboss') as sor:
|
||||
# orgs = await sor.R('organization', {"org_type": '0'})
|
||||
# ns['del_flg'] = '0'
|
||||
# ns['sort'] = 'create_at desc'
|
||||
# ns['parentid'] = orgs[0]['id']
|
||||
# datalist = []
|
||||
# prc = await sor.R('customer', {'del_flg': '0'})
|
||||
# for i in prc:
|
||||
# if not i['salemanid']:
|
||||
# customer_id_parentid_li = await sor.R('organization', {'id': i['customerid']})
|
||||
# customer_id_parentid = customer_id_parentid_li[0]['parentid']
|
||||
# if customer_id_parentid == ns.get('orgid'):
|
||||
# datalist.append(customer_id_parentid_li[0])
|
||||
# data = {'rows':datalist}
|
||||
# return {'status': True, 'data': data}
|
||||
|
||||
ret = await getNoinvitationcode(params_kw)
|
||||
return ret
|
||||
@ -1,54 +1,155 @@
|
||||
async def getcustomer_goods(ns={}):
|
||||
"""
|
||||
获取客户产品列表,支持产品名称筛选、日期范围筛选和分页功能
|
||||
|
||||
参数:
|
||||
ns: 参数字典,包含:
|
||||
- userid: 用户ID (可选)
|
||||
- productname: 产品名称筛选关键字 (可选)
|
||||
- start_date: 开始日期 (格式: YYYY-MM-DD, 可选)
|
||||
- end_date: 结束日期 (格式: YYYY-MM-DD, 可选)
|
||||
- page: 页码 (默认1)
|
||||
- page_size: 每页条数 (默认20)
|
||||
|
||||
返回:
|
||||
dict: 包含状态、数据列表、总条数、当前页、总页数的信息
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 获取用户ID
|
||||
if ns.get('userid'):
|
||||
users_id = ns.get('userid')
|
||||
else:
|
||||
users_id = await get_user()
|
||||
|
||||
user = await sor.R('users', {'id': users_id})
|
||||
date = datetime.datetime.now().date()
|
||||
if not user:
|
||||
return {'status': False, 'msg': '用户不存在'}
|
||||
|
||||
customerid = user[0]['orgid']
|
||||
current_date = datetime.datetime.now().date()
|
||||
|
||||
# 更新过期产品的删除标志
|
||||
sql = """update customer_goods SET del_flg = '1' where expire_date < ${date}$ and customerid = ${customerid}$"""
|
||||
await sor.sqlExe(sql, {'date': date, 'customerid': user[0]['orgid']})
|
||||
customer_goods = await sor.R('customer_goods', {'customerid': user[0]['orgid'],'sort':'create_at desc','del_flg':'0'})
|
||||
for i in customer_goods:
|
||||
ordergoods = await sor.R('order_goods', {'orderid':i['orderid']})
|
||||
# jnorg = await sor.R('organization', {'id': i['providerrid'], 'orgname': '济南超算'})
|
||||
# if len(jnorg) >= 1:
|
||||
# i['org'] = 'jinan'
|
||||
for j in ordergoods:
|
||||
if j['end_date']:
|
||||
await sor.U('customer_goods',{'id':i['id'],'expire_date':j['end_date']})
|
||||
await sor.sqlExe(sql, {'date': date, 'customerid': user[0]['orgid']})
|
||||
customer = await sor.R('customer_goods',
|
||||
{'customerid': user[0]['orgid'], 'sort': 'create_at desc', 'del_flg': '0'})
|
||||
for cu in customer:
|
||||
await sor.sqlExe(sql, {'date': current_date, 'customerid': customerid})
|
||||
|
||||
# 获取筛选参数
|
||||
product_name_filter = ns.get('productname', '').strip()
|
||||
start_date = ns.get('start_date')
|
||||
end_date = ns.get('end_date')
|
||||
page = max(1, int(ns.get('page', 1)))
|
||||
page_size = max(1, min(100, int(ns.get('page_size', 20)))) # 限制每页最多100条
|
||||
|
||||
# 构建基础查询条件
|
||||
base_conditions = {
|
||||
'customerid': customerid,
|
||||
'del_flg': '0',
|
||||
'sort': 'create_at desc'
|
||||
}
|
||||
|
||||
# 先获取所有有效的产品数据
|
||||
all_customer_goods = await sor.R('customer_goods', base_conditions)
|
||||
|
||||
# 处理订单商品数据并更新过期日期
|
||||
for item in all_customer_goods:
|
||||
ordergoods = await sor.R('order_goods', {'orderid': item['orderid']})
|
||||
for order_item in ordergoods:
|
||||
if order_item['end_date']:
|
||||
await sor.U('customer_goods', {'id': item['id'], 'expire_date': order_item['end_date']})
|
||||
|
||||
# 重新获取更新后的数据
|
||||
all_customer_goods = await sor.R('customer_goods', base_conditions)
|
||||
|
||||
# 处理产品数据并应用筛选
|
||||
processed_goods = []
|
||||
for cu in all_customer_goods:
|
||||
provider_id_li = await sor.R('product', {'id': cu['productid'], 'del_flg': '0'})
|
||||
if provider_id_li:
|
||||
cu['classify'] = provider_id_li[0]['classify']
|
||||
|
||||
# 处理k8s资源
|
||||
if cu.get('classify') and 'CPCC' in cu['classify']:
|
||||
cu['classify'] = 'CPCC'
|
||||
prd_name = cu['productname'].split('.')[0]
|
||||
if '-' == prd_name or 'STANDARD' == prd_name:
|
||||
cu['productname'] = 'CPU计算型'
|
||||
else:
|
||||
cu['productname'] = prd_name
|
||||
spec_note_li = await sor.R('specificdata', {'id': cu['specdataid']})
|
||||
if not provider_id_li:
|
||||
continue
|
||||
|
||||
cu['classify'] = provider_id_li[0]['classify']
|
||||
|
||||
# 处理k8s资源
|
||||
if cu.get('classify') and 'CPCC' in cu['classify']:
|
||||
cu['classify'] = 'CPCC'
|
||||
prd_name = cu['productname'].split('.')[0]
|
||||
if '-' == prd_name or 'STANDARD' == prd_name:
|
||||
cu['productname'] = 'CPU计算型'
|
||||
else:
|
||||
cu['productname'] = prd_name
|
||||
|
||||
spec_note_li = await sor.R('specificdata', {'id': cu['specdataid']})
|
||||
if spec_note_li:
|
||||
cu['instance_info'] = json.loads(spec_note_li[0]['spec_data'])
|
||||
external_ip_li = await sor.R('cpcnode', {'cpcid': cu['instance_info']['cpcid'], 'clusterid': cu['instance_info']['clusterid'], 'role': 'master'})
|
||||
cu['instance_info']['source_externalip'] = external_ip_li[0]['external_ip']
|
||||
|
||||
provider_id = provider_id_li[0]['providerid']
|
||||
jnorg = await sor.R('organization', {'id': provider_id, 'del_flg': '0'})
|
||||
external_ip_li = await sor.R('cpcnode', {
|
||||
'cpcid': cu['instance_info']['cpcid'],
|
||||
'clusterid': cu['instance_info']['clusterid'],
|
||||
'role': 'master'
|
||||
})
|
||||
if external_ip_li:
|
||||
cu['instance_info']['source_externalip'] = external_ip_li[0]['external_ip']
|
||||
|
||||
provider_id = provider_id_li[0]['providerid']
|
||||
jnorg = await sor.R('organization', {'id': provider_id, 'del_flg': '0'})
|
||||
if jnorg:
|
||||
cu['providername'] = jnorg[0]['orgname']
|
||||
if jnorg[0]['orgname'] == '优刻得科技股份有限公司':
|
||||
cu['region'] = 'cn-wlcb'
|
||||
return {'status': True, 'data': customer}
|
||||
|
||||
# 应用筛选条件
|
||||
# 产品名称筛选
|
||||
if product_name_filter and product_name_filter.lower() not in cu.get('productname', '').lower():
|
||||
continue
|
||||
|
||||
# 日期范围筛选
|
||||
# create_at字段存在且在指定范围内 格式是:"2025-10-05 22:57:05"
|
||||
if start_date and cu.get('create_at'):
|
||||
try:
|
||||
start_dt = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
|
||||
create_at_dt = datetime.datetime.strptime(cu['create_at'], '%Y-%m-%d %H:%M:%S')
|
||||
if create_at_dt.date() < start_dt:
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"开始日期解析错误: {e}")
|
||||
|
||||
if end_date and cu.get('create_at'):
|
||||
try:
|
||||
end_dt = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
|
||||
create_at_dt = datetime.datetime.strptime(cu['create_at'], '%Y-%m-%d %H:%M:%S')
|
||||
if create_at_dt.date() > end_dt:
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"结束日期解析错误: {e}")
|
||||
|
||||
# 通过specdataid读取规格数据
|
||||
cu['spec_data'] = None
|
||||
if cu.get('specdataid'):
|
||||
specdata_li = await sor.R('specificdata', {'id': cu['specdataid']})
|
||||
if specdata_li:
|
||||
cu['spec_data'] = json.loads(specdata_li[0]['spec_data'])
|
||||
|
||||
processed_goods.append(cu)
|
||||
|
||||
# 分页处理
|
||||
total_count = len(processed_goods)
|
||||
|
||||
# 计算当前页的数据
|
||||
start_index = (page - 1) * page_size
|
||||
end_index = start_index + page_size
|
||||
paginated_data = processed_goods[start_index:end_index]
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'data': paginated_data,
|
||||
'pagination': {
|
||||
'total': total_count,
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '错误'}
|
||||
return {'status': False, 'msg': '%s' % str(e)}
|
||||
|
||||
ret = await getcustomer_goods(params_kw)
|
||||
return ret
|
||||
@ -5,20 +5,46 @@ async def registerUser(ns):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
userns = {'username': ns['username']}
|
||||
isuser = await sor.R('users', userns)
|
||||
if len(isuser) >= 1:
|
||||
return {'status': False, 'msg': '用户名已注册'}
|
||||
useremai = {'email': ns['email']}
|
||||
isuser = await sor.R('users', useremai)
|
||||
if len(isuser) >= 1:
|
||||
return {'status': False, 'msg': '该邮箱已注册'}
|
||||
if ns.get('username'):
|
||||
userns = {'username': ns['username']}
|
||||
isuser = await sor.R('users', userns)
|
||||
if len(isuser) >= 1:
|
||||
return {'status': False, 'msg': '用户名已注册'}
|
||||
|
||||
if ns.get('email'):
|
||||
useremai = {'email': ns['email']}
|
||||
isuser = await sor.R('users', useremai)
|
||||
if len(isuser) >= 1:
|
||||
return {'status': False, 'msg': '该邮箱已注册'}
|
||||
|
||||
usermobile = {'mobile':ns['mobile']}
|
||||
isuser = await sor.R('users', usermobile)
|
||||
if len(isuser) >= 1:
|
||||
return {'status': False, 'msg': '该手机号已注册'}
|
||||
if len(ns.get('password')) < 6:
|
||||
return {'status': False, 'msg': '密码必须6位数以上'}
|
||||
# 用户名没有 则用手机号作为用户名
|
||||
if not ns.get('username'):
|
||||
ns['username'] = ns['mobile']
|
||||
|
||||
if ns.get('password'):
|
||||
if len(ns.get('password')) < 6:
|
||||
return {'status': False, 'msg': '密码必须6位数以上'}
|
||||
|
||||
if not ns.get('codeid'):
|
||||
return {'status': False, 'msg': '验证码ID不能为空'}
|
||||
|
||||
if ns.get('codeid'):
|
||||
code = await sor.R('validatecode', {'id': ns.get('codeid'), 'vcode': ns.get('vcode')})
|
||||
# 验证码五分钟内才有效 create_at是字符串 格式是"2025-11-05 16:00:19"
|
||||
if code:
|
||||
create_at = code[0]['create_at']
|
||||
now = datetime.datetime.now()
|
||||
create_at_dt = datetime.datetime.strptime(create_at, "%Y-%m-%d %H:%M:%S")
|
||||
if (now - create_at_dt).seconds > 500:
|
||||
return {'status': False, 'msg': '验证码过期'}
|
||||
|
||||
else:
|
||||
return {'status': False, 'msg': '验证码不正确'}
|
||||
|
||||
#通过邀请码注册
|
||||
if ns.get('invitecode'):
|
||||
invitecodens = {}
|
||||
@ -95,37 +121,64 @@ async def registerUser(ns):
|
||||
return {'status': False, 'msg': '邀请码不正确'}
|
||||
else:
|
||||
try:
|
||||
# 用户orgid
|
||||
ns['id'] = uuid()
|
||||
org_id = ns['id']
|
||||
ns['contactor_phone'] = ns.get('mobile')
|
||||
# 通过域名注册
|
||||
if ns.get('domain_name'):
|
||||
# 通过域名查找分销商信息
|
||||
reseller = await sor.R('reseller', {'domain_name': ns.get('domain_name')})
|
||||
if len(reseller) >= 1:
|
||||
# 分销商机构ID 即orgid
|
||||
org = await sor.R('organization', {'id': reseller[0]['orgid'], 'del_flg': '0'})
|
||||
else:
|
||||
# 分销商不存在 则查找业主机构ID
|
||||
org = await sor.R('organization', {'org_type': '0', 'del_flg': '0'})
|
||||
else:
|
||||
# 没有通过域名 则默认是获取业主机构ID
|
||||
org = await sor.R('organization', {'org_type': '0', 'del_flg': '0'})
|
||||
|
||||
# 获取所在机构父级ID
|
||||
ns['parentid'] = org[0]['id']
|
||||
await sor.C('organization', ns)
|
||||
|
||||
# 新增用户机构信息
|
||||
ns_org = {
|
||||
'id': ns['id'],
|
||||
'orgname': ns['username'],
|
||||
'parentid': ns['parentid'],
|
||||
'org_type': ns['org_type'],
|
||||
'contactor_phone': ns.get('mobile'),
|
||||
}
|
||||
await sor.C('organization', ns_org)
|
||||
|
||||
# 生成用户userid
|
||||
ns['id'] = uuid()
|
||||
userid = ns['id']
|
||||
ns['password'] = password_encode(ns['password'])
|
||||
|
||||
# 加密用户密码
|
||||
if ns.get('password'):
|
||||
ns['password'] = password_encode(ns['password'])
|
||||
ns['orgid'] = org_id
|
||||
|
||||
# 新增用户信息
|
||||
await sor.C('users', ns)
|
||||
|
||||
# 新增用户角色信息
|
||||
listrole = ['管理员', '客户']
|
||||
for i in listrole:
|
||||
role = await sor.R('role', {'role': i, 'org_type': ns['org_type']})
|
||||
await sor.C('userrole', {'id': uuid(), 'userid': userid, 'roleid': role[0]['id']})
|
||||
|
||||
# 新增客户信息并使用openCustomerAccounts为客户开账
|
||||
ns['id'] = uuid()
|
||||
ns['customerid'] = org_id
|
||||
await sor.C('customer', ns)
|
||||
await openCustomerAccounts(sor, org[0]['id'], org_id)
|
||||
return {'status': True, 'msg': '注册成功'}
|
||||
except Exception as error:
|
||||
raise error
|
||||
return {'status': False, 'msg': '注册失败'}
|
||||
# raise error
|
||||
return {'status': False, 'msg': '注册失败, %s' % str(error)}
|
||||
|
||||
|
||||
ret = await registerUser(params_kw)
|
||||
|
||||
@ -15,9 +15,9 @@ async def contact(ns={}):
|
||||
# contactor_phone = sales_info[0]['mobile']
|
||||
# contactor_image = sales_info[0]['picture']
|
||||
# if domain == 'www':
|
||||
# picture_urls = f"https://www.kaiyuancloud.cn/idfile?path={contactor_image}"
|
||||
# picture_urls = f"https://www.opencomputing.cn/idfile?path={contactor_image}"
|
||||
# else:
|
||||
# picture_urls = f"https://xterm.kaiyuancloud.cn/idfile?path={contactor_image}"
|
||||
# picture_urls = f"https://xterm.opencomputing.cn/idfile?path={contactor_image}"
|
||||
#
|
||||
# return {'status': True, 'msg': '展示成功', 'contactor_phone': contactor_phone,
|
||||
# 'picture_url': picture_urls}
|
||||
@ -26,9 +26,9 @@ async def contact(ns={}):
|
||||
# ss = await sor.R('organization', {'id': orgid, 'del_flg': 0})
|
||||
#
|
||||
# if domain == 'www':
|
||||
# picture_url = f"https://www.kaiyuancloud.cn/idfile?path={ss[0]['picture']}"
|
||||
# picture_url = f"https://www.opencomputing.cn/idfile?path={ss[0]['picture']}"
|
||||
# else:
|
||||
# picture_url = f"https://xterm.kaiyuancloud.cn/idfile?path={ss[0]['picture']}"
|
||||
# picture_url = f"https://xterm.opencomputing.cn/idfile?path={ss[0]['picture']}"
|
||||
#
|
||||
# return {'status': True, 'msg': '展示成功', 'contactor_phone': ss[0]["contactor_phone"],
|
||||
# 'picture_url': picture_url}
|
||||
@ -37,11 +37,11 @@ async def contact(ns={}):
|
||||
# ss = await sor.R('organization', {'id': orgid, 'del_flg': 0})
|
||||
#
|
||||
# if domain == 'www':
|
||||
# picture_url = f"https://www.kaiyuancloud.cn/idfile?path={ss[0]['picture']}"
|
||||
# picture_url = f"https://www.opencomputing.cn/idfile?path={ss[0]['picture']}"
|
||||
# else:
|
||||
# picture_url = f"https://xterm.kaiyuancloud.cn/idfile?path={ss[0]['picture']}"
|
||||
# picture_url = f"https://xterm.opencomputing.cn/idfile?path={ss[0]['picture']}"
|
||||
|
||||
picture_url = 'https://www.kaiyuancloud.cn/idfile?path=firstpagehot/wechat_person.png'
|
||||
picture_url = 'https://www.opencomputing.cn/idfile?path=firstpagehot/wechat_person.png'
|
||||
return {'status': True, 'msg': '展示成功', 'contactor_phone': ' 400-6150805, 010-65917875',
|
||||
'picture_url': picture_url}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ async def get_recharge_record(ns={}):
|
||||
try:
|
||||
user_id = await get_user()
|
||||
if not user_id:
|
||||
return {'status': False, 'message': 'user_id is missing'}
|
||||
server_error(401)
|
||||
|
||||
result = await sor.R('users', {'id': user_id})
|
||||
if not result:
|
||||
@ -28,17 +28,35 @@ async def get_recharge_record(ns={}):
|
||||
# recharge_path = 0
|
||||
recharge_path = ns.get('recharge_path')
|
||||
params = {'start_time': start_time, 'end_time': end_time, 'recharge_path': recharge_path, 'orgid': orgid}
|
||||
|
||||
|
||||
# 增加分页功能
|
||||
page = ns.get('page', 1)
|
||||
size = ns.get('size', 20)
|
||||
offset = (page - 1) * size
|
||||
|
||||
# 构建COUNT查询
|
||||
total_sql = "SELECT COUNT(*) AS total_count FROM recharge_log WHERE del_flg = 0 AND customerid = ${orgid}$"
|
||||
|
||||
sql = "SELECT * FROM recharge_log WHERE del_flg = 0 AND customerid = ${orgid}$"
|
||||
if start_time and end_time:
|
||||
sql += " AND create_at BETWEEN ${start_time}$ AND ${end_time}$"
|
||||
total_sql += " AND create_at BETWEEN ${start_time}$ AND ${end_time}$"
|
||||
if recharge_path is not None:
|
||||
sql += " AND recharge_path = ${recharge_path}$"
|
||||
total_sql += " AND recharge_path = ${recharge_path}$"
|
||||
|
||||
# 添加排序但不添加分页限制到主查询
|
||||
sql += " ORDER BY create_at DESC"
|
||||
|
||||
# 执行COUNT查询获取总记录数
|
||||
total_result = await sor.sqlExe(total_sql, params)
|
||||
total_count = total_result[0]['total_count'] if total_result else 0
|
||||
|
||||
# 执行查询获取所有匹配记录
|
||||
reacs = await sor.sqlExe(sql, params)
|
||||
|
||||
if not reacs:
|
||||
return {'status': True, 'message': 'No recharge records'}
|
||||
return {'status': True, 'message': 'No recharge records', 'pagination': {'page': page, 'size': size, 'total': 0}}
|
||||
|
||||
for recharge in reacs:
|
||||
if recharge['recharge_sno']:
|
||||
@ -75,7 +93,11 @@ async def get_recharge_record(ns={}):
|
||||
recharge_amount += round(float(recharge['recharge_amt']), 2)
|
||||
elif recharge['action'] in ['RECHARGE_REVERSE', 'RECHARGE_ALIPAY_REVERSE']:
|
||||
recharge_reverse_amount += round(float(recharge['recharge_amt']), 2)
|
||||
|
||||
# 在过滤后应用分页
|
||||
recharge_records.sort(key=lambda x: x['create_at'], reverse=True)
|
||||
# 应用分页
|
||||
paginated_records = recharge_records[offset:offset + size]
|
||||
except Exception as e:
|
||||
raise
|
||||
|
||||
@ -83,10 +105,15 @@ async def get_recharge_record(ns={}):
|
||||
return {
|
||||
'status': True,
|
||||
'message': 'ok',
|
||||
'recharge_records': recharge_records,
|
||||
'recharge_records': paginated_records,
|
||||
'actual_amount': round(total_amount, 2),
|
||||
'recharge_amount': round(recharge_amount, 2),
|
||||
'charged_amount': round(recharge_reverse_amount, 2)
|
||||
'charged_amount': round(recharge_reverse_amount, 2),
|
||||
'pagination': {
|
||||
'page': page,
|
||||
'size': size,
|
||||
'total': len(recharge_records) # 使用过滤后的总记录数
|
||||
}
|
||||
}
|
||||
|
||||
ret = await get_recharge_record(params_kw)
|
||||
|
||||
@ -19,7 +19,7 @@ async def bb(ns={}):
|
||||
# raise ValueError("供应商没有配置产品")
|
||||
|
||||
# 获取当前日期
|
||||
current_date = datetime.datetime.now()
|
||||
# current_date = datetime.datetime.now()
|
||||
|
||||
# 计算两个月后的日期
|
||||
# future_date = current_date + dateutil.relativedelta.relativedelta(months=6)
|
||||
@ -31,9 +31,21 @@ async def bb(ns={}):
|
||||
# }
|
||||
# users_id = await get_user()
|
||||
# await asyncio.sleep(10)
|
||||
import os
|
||||
current_path = os.getcwd()
|
||||
return {'current_date': current_path}
|
||||
# import os
|
||||
# current_path = os.getcwd()
|
||||
# return {'current_date': current_path}
|
||||
|
||||
# db = DBPools()
|
||||
# async with db.sqlorContext('kboss') as sor:
|
||||
# await sor.U('white_list', {'id': ns.get('id'), 'user_id': ns.get('user_id')})
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'msg': 'Data inserted successfully',
|
||||
# 'data': ''
|
||||
# }
|
||||
if True:
|
||||
server_error(401)
|
||||
|
||||
|
||||
ret = await bb(params_kw)
|
||||
return ret
|
||||
@ -4,12 +4,20 @@ async def get_unreadmsg(ns={}):
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
ns['userid'] = ns.get('userid')
|
||||
else:
|
||||
ns['userid'] = await get_user()
|
||||
if not ns.get('userid'):
|
||||
server_error(401)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# if 'userid' not in ns or not ns['userid']:
|
||||
# return {'status': False, 'msg': '收件人 userid 未提供'}
|
||||
|
||||
mas = await sor.R('message', {'receiverid': await get_user(), 'del_flg': 0, 'msgstatus': 0})
|
||||
mas = await sor.R('message', {'receiverid': ns['userid'], 'del_flg': 0, 'msgstatus': 0})
|
||||
|
||||
if not mas:
|
||||
return {'status': True, 'count': 0}
|
||||
|
||||
@ -21,7 +21,7 @@ async def payhuidiao(ns):
|
||||
'action': 'RECHARGE_ALIPAY', 'recharge_path': '0', 'recharge_date': date,'fee_amt':fee_amte}
|
||||
ra = AlipayRechargeAccounting(recharge_log)
|
||||
await ra.accounting(sor)
|
||||
await redirect('https://www.kaiyuancloud.cn/#/paySuccess')
|
||||
await redirect('https://www.opencomputing.cn/#/paySuccess')
|
||||
|
||||
ret = await payhuidiao(params_kw)
|
||||
return ret
|
||||
@ -3,7 +3,8 @@ async def delpermission(ns):
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('permission', ns)
|
||||
update_sql = """update permission set del_flg = '1' where id = '%s'""" % ns['id']
|
||||
await sor.sqlExe(update_sql, {})
|
||||
dictns = {'parentid': ns['id']}
|
||||
reacs = await sor.R('permission', dictns)
|
||||
for i in reacs:
|
||||
|
||||
@ -1,8 +1,20 @@
|
||||
async def add_user_inquiry(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递url_link'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
ns_c = {
|
||||
'id': uuid(),
|
||||
'domain_name': domain_name,
|
||||
'publish_type': ns.get('publish_type'),
|
||||
'relate_id': ns.get('relate_id'),
|
||||
'content': ns.get('content'),
|
||||
'custom_type': ns.get('custom_type'),
|
||||
'name': ns.get('name'),
|
||||
|
||||
82
b/product/baidu_resource_query.dspy
Normal file
82
b/product/baidu_resource_query.dspy
Normal file
@ -0,0 +1,82 @@
|
||||
async def baidu_resource_query(ns={}):
|
||||
"""
|
||||
用户资源查询
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baiduids = await sor.R('baidu_users', {'user_id': userid})
|
||||
if baiduids:
|
||||
baiduid = baiduids[0]['baidu_id']
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'User not synchronized'
|
||||
}
|
||||
ns['queryAccountId'] = baiduid
|
||||
ns['pageSize'] = 200
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/resource/query?%s' % ns_format
|
||||
header = {
|
||||
"Host": "billing.baidubce.com"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=ns) as res:
|
||||
result = await res.json()
|
||||
return {'1': result}
|
||||
|
||||
result_new = []
|
||||
for i in result['result']:
|
||||
if i.get('status') != 'STOPPED':
|
||||
result_new.append(i)
|
||||
|
||||
result['result'] = result_new
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get resource success',
|
||||
'data': result
|
||||
}
|
||||
|
||||
async def resource_overview(ns={}):
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
init_data = [
|
||||
{'id': 1, 'name': '云服务器', 'count': 0, 'unit': '实例'},
|
||||
{'id': 2, 'name': '私有网络', 'count': 0, 'unit': 'VPC'},
|
||||
{'id': 3, 'name': '负载均衡', 'count': 0, 'unit': '负载均衡'},
|
||||
{'id': 4, 'name': '弹性块存储', 'count': 0, 'unit': '云盘'},
|
||||
{'id': 5, 'name': 'NAT网关', 'count': 0, 'unit': '实例'},
|
||||
{'id': 6, 'name': 'VPN连接', 'count': 0, 'unit': 'VPN网关'},
|
||||
]
|
||||
baidu_resource_data = await baidu_resource_query({'userid': userid})
|
||||
print(baidu_resource_data)
|
||||
if baidu_resource_data and baidu_resource_data.get('data') and baidu_resource_data['data'].get('result'):
|
||||
for baidu_resource in baidu_resource_data['data']['result']:
|
||||
if baidu_resource.get('serviceType') == 'CDS' and baidu_resource['status'] == 'RUNNING':
|
||||
init_data[3]['count'] += 1
|
||||
elif baidu_resource.get('serviceType') == 'EIP' and baidu_resource['status'] == 'RUNNING':
|
||||
init_data[1]['count'] += 1
|
||||
elif (baidu_resource.get('serviceType') == 'BCC' or baidu_resource.get('serviceType') == 'LS') and baidu_resource['status'] == 'RUNNING':
|
||||
init_data[0]['count'] += 1
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get resource success',
|
||||
'data': init_data
|
||||
}
|
||||
|
||||
ret = await baidu_resource_query(params_kw)
|
||||
return ret
|
||||
46
b/product/company_category_add.dspy
Normal file
46
b/product/company_category_add.dspy
Normal file
@ -0,0 +1,46 @@
|
||||
async def company_category_add(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递url_link'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'domain_name': domain_name,
|
||||
'company_category': ns.get('company_category')
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
ns_dic['orgid'] = orgid
|
||||
try:
|
||||
await sor.C('user_publish_company_category', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Company category created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create company category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await company_category_add(params_kw)
|
||||
return ret
|
||||
18
b/product/company_category_delete.dspy
Normal file
18
b/product/company_category_delete.dspy
Normal file
@ -0,0 +1,18 @@
|
||||
async def company_category_delete(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """update user_publish_company_category set del_flg = '1' where id = '%s';""" % ns.get('id')
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Company category deleted successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to delete company category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await company_category_delete(params_kw)
|
||||
return ret
|
||||
27
b/product/company_category_search.dspy
Normal file
27
b/product/company_category_search.dspy
Normal file
@ -0,0 +1,27 @@
|
||||
async def company_category_search(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递url_link'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
result = await sor.R('user_publish_company_category', {'domain_name': domain_name, 'del_flg': '0'})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Company categories retrieved successfully',
|
||||
'data': result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve company categories, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await company_category_search(params_kw)
|
||||
return ret
|
||||
18
b/product/company_category_update.dspy
Normal file
18
b/product/company_category_update.dspy
Normal file
@ -0,0 +1,18 @@
|
||||
async def company_category_update(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """update user_publish_company_category set company_category = '%s' where id = '%s';""" % (ns.get('company_category'), ns.get('id'))
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Company category updated successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to update company category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await company_category_update(params_kw)
|
||||
return ret
|
||||
@ -14,14 +14,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"discount": 7.5,
|
||||
"url": "https://console.vcp.baidu.com/bcc/#/bcc/instance/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bcc/#/bcc/instance/list",
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/5.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/5.png",
|
||||
"list": [
|
||||
{"id": 23, "name": "CPU", "content": "16/32/64核", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 24, "name": "内存", "content": "64/128/256GiB", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 25, "name": "内网带宽", "content": "6/12/14/18Gbps", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 26, "name": "网络收发包", "content": "120/250/450万pps", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 27, "name": "GPU", "content": "1/2/4张", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 28, "name": "处理器", "content": "Intel Xeon Platinum 8350C,主频2.6GHz", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 23, "name": "CPU", "content": "16/32/64核", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 24, "name": "内存", "content": "64/128/256GiB", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 25, "name": "内网带宽", "content": "6/12/14/18Gbps", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 26, "name": "网络收发包", "content": "120/250/450万pps", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 27, "name": "GPU", "content": "1/2/4张", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 28, "name": "处理器", "content": "Intel Xeon Platinum 8350C,主频2.6GHz", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"computing": {
|
||||
@ -33,14 +33,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"discount": 7.5,
|
||||
"url": "https://console.vcp.baidu.com/bcc/#/bcc/instance/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bcc/#/bcc/instance/list",
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/2.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/2.png",
|
||||
"list": [
|
||||
{"id": 7, "name": "vCPU", "content": "2核", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"},
|
||||
{"id": 8, "name": "购买配额", "content": "1台 * 12个月", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 9, "name": "内存", "content": "8GB", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 10, "name": "公网带宽", "content": "8Mbps", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 11, "name": "磁盘", "content": "100GB SSD", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 12, "name": "地域", "content": "华北 - 北京", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"}
|
||||
{"id": 7, "name": "vCPU", "content": "2核", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"},
|
||||
{"id": 8, "name": "购买配额", "content": "1台 * 12个月", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 9, "name": "内存", "content": "8GB", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 10, "name": "公网带宽", "content": "8Mbps", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 11, "name": "磁盘", "content": "100GB SSD", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 12, "name": "地域", "content": "华北 - 北京", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
@ -52,12 +52,12 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"discount": 7.5,
|
||||
"url": "https://console.vcp.baidu.com/bos/#/bos/package/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bos/#/bos/package",
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/3.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/3.png",
|
||||
"list": [
|
||||
{"id": 13, "name": "稳定可靠", "content": "自主可控的冗余存储架构,为数据持久存储提供可靠保障。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 14, "name": "智能存储", "content": "提供多种数据处理能力,满足企业数据管理需求。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 15, "name": "安全合规", "content": "全方位安全措施,满足企业数据安全与合规要求。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 16, "name": "数据沉降", "content": "全方位分级存储,智能业务分析,提供智能化数据沉降建议。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
{"id": 13, "name": "稳定可靠", "content": "自主可控的冗余存储架构,为数据持久存储提供可靠保障。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 14, "name": "智能存储", "content": "提供多种数据处理能力,满足企业数据管理需求。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 15, "name": "安全合规", "content": "全方位安全措施,满足企业数据安全与合规要求。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 16, "name": "数据沉降", "content": "全方位分级存储,智能业务分析,提供智能化数据沉降建议。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
]
|
||||
},
|
||||
"database": {
|
||||
@ -69,14 +69,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"discount": 7.5,
|
||||
"url": "https://console.vcp.baidu.com/rds/#/rds/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/rds/#/rds/list",
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{"id": 17, "name": "高可用", "content": "跨地域多可用区部署;数据实时复制,故障秒级切换;双机热备秒级自动切换,RTO<60s", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 18, "name": "高可靠", "content": "支持高频、稀疏备份,满足多样化需求;数据恢复至原实例、指定实例、新实例;库表恢复到任意实例,RPO范围0-5分钟", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 19, "name": "性能提升4倍", "content": "100%兼容原生MySQL,自研内核特性,相比自建数据库,高并发下性能提升4倍", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 20, "name": "高可用99.99%", "content": "跨地域高可用部署,通过专线网络实时数据复制,同时支持边缘、混合云部署场景", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 21, "name": "高可靠99.9999%+", "content": "故障秒级切换,满足跨地域灾备、高频备份、稀疏备份等多样化需求", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 22, "name": "智能运维80%", "content": "大模型能力赋能数据库,相比人工节约80%异常定位时间,大幅降低运维成本", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 17, "name": "高可用", "content": "跨地域多可用区部署;数据实时复制,故障秒级切换;双机热备秒级自动切换,RTO<60s", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 18, "name": "高可靠", "content": "支持高频、稀疏备份,满足多样化需求;数据恢复至原实例、指定实例、新实例;库表恢复到任意实例,RPO范围0-5分钟", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 19, "name": "性能提升4倍", "content": "100%兼容原生MySQL,自研内核特性,相比自建数据库,高并发下性能提升4倍", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 20, "name": "高可用99.99%", "content": "跨地域高可用部署,通过专线网络实时数据复制,同时支持边缘、混合云部署场景", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 21, "name": "高可靠99.9999%+", "content": "故障秒级切换,满足跨地域灾备、高频备份、稀疏备份等多样化需求", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 22, "name": "智能运维80%", "content": "大模型能力赋能数据库,相比人工节约80%异常定位时间,大幅降低运维成本", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"container": {
|
||||
@ -88,14 +88,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"discount": 7.5,
|
||||
"url": "https://console.vcp.baidu.com/ai/xs.html#/ai/face/overview/index",
|
||||
"listUrl": "https://console.vcp.baidu.com/ai/xs.html#/ai/face/overview/index",
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/1.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/1.png",
|
||||
"list": [
|
||||
{"id": 1, "name": None, "content": "领先活体检测方案 假体无所遁形", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": None, "content": "权威机构可信数据 多数据角度验证", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": None, "content": "高通过率、低客诉 保障C端用户体验", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": None, "content": "高并发/高性能/高可用 弹性应对各类业务体量", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": None, "content": "按需定制行业方案 保障风控后审无忧", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": None, "content": "丰富端云活体方式 业务灵活选配", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 1, "name": None, "content": "领先活体检测方案 假体无所遁形", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": None, "content": "权威机构可信数据 多数据角度验证", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": None, "content": "高通过率、低客诉 保障C端用户体验", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": None, "content": "高并发/高性能/高可用 弹性应对各类业务体量", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": None, "content": "按需定制行业方案 保障风控后审无忧", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": None, "content": "丰富端云活体方式 业务灵活选配", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
},
|
||||
@ -105,14 +105,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"title": "DCI业务",
|
||||
"description": "凭借先进的SDN技术,及覆盖全国网络资源优势,满足客户办公场所至云数据中心、数据中心至云数据中心、云数据中心至云数据中心、数据中心至数据中心的互联需求。解决企业上云最后一公里连接需求,实现多云互联的场景,满足用户数据传送高带宽、高质量、内网化的需求。",
|
||||
"advantageList": [
|
||||
{"id": 29, "name": "大范围", "content": "凭借高质量的全国网,满足用户多地,多区域上云需求。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 30, "name": "优质的网络资源", "content": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 31, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术,SDN技术实现业务可控质量可控。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 32, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
{"id": 29, "name": "大范围", "content": "凭借高质量的全国网,满足用户多地,多区域上云需求。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 30, "name": "优质的网络资源", "content": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 31, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术,SDN技术实现业务可控质量可控。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 32, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
],
|
||||
"tagList": [
|
||||
{"id": 33, "name": "互联网电商", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 34, "name": "在线教育", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 33, "name": "互联网电商", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 34, "name": "在线教育", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"hlzx": {
|
||||
@ -120,14 +120,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"title": "互联网专线业务",
|
||||
"description": "开元云互联网接入业务,凭借多年的互联网运营经验,通过搭建新一代的宽带网络及综合电信业务平台,应用最先进的国际通信技术、提供最完美的通信手段,以服务品质和创新能力树立核心竞争力,通过全方位的、电信级的整合通信服务,更好的为我们的客户提供全方位的通信网络一体化解决方案,为企业客户提供一级运营商品质的互联网接入产品与增值服务。",
|
||||
"advantageList": [
|
||||
{"id": 35, "name": "7*24技术支持", "content": "运维团队7* 24小时守护,快速处理突发事件。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 36, "name": "优质的网络资源", "content": "提供电信、联通、移动、多线、BGP等优质网络资源。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 37, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 38, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
{"id": 35, "name": "7*24技术支持", "content": "运维团队7* 24小时守护,快速处理突发事件。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 36, "name": "优质的网络资源", "content": "提供电信、联通、移动、多线、BGP等优质网络资源。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 37, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 38, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
],
|
||||
"tagList": [
|
||||
{"id": 39, "name": "单线接入服务", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 40, "name": "多线接入服务", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 39, "name": "单线接入服务", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 40, "name": "多线接入服务", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"SDWAN": {
|
||||
@ -135,14 +135,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"title": "SD-WAN业务",
|
||||
"description": "开元SD-WAN云网融合一体化解决方案基于SDN软件定义广域网技术为企业提供高效的智能广域网接入、跨地域组网及智能调度与管理服务。帮助企业客户零部署 快速连云与组网,访问云端应用。同时,还可分钟级构建云、数据中心、企业分支之间的专属网络,实现三者的任意互联、灵活配置和智能调度, 以更低地TCO(总拥有成本)享受到高质量网络连接与 云端应用访问体验,真正意义上实现云与网的高效融合与协同。",
|
||||
"advantageList": [
|
||||
{"id": 41, "name": "稳定可靠", "content": "⽹络定义软件化, 软、硬件解耦,service-chain,多路径优化。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 42, "name": "灵活接入", "content": "多种接⼊类型及⽅式,连接随业务⽽动,⽆缝接⼊云应⽤与云数据中⼼。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 43, "name": "精细调度", "content": "应⽤调度 通过DPI协议识别,动态多链路,以及FEC技术,可以在公⽹上保证应⽤的QOE质量", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 44, "name": "敏捷部署", "content": "⼀键部署,部署时间由“周”缩⼩⾄“⼩时”。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
{"id": 41, "name": "稳定可靠", "content": "⽹络定义软件化, 软、硬件解耦,service-chain,多路径优化。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 42, "name": "灵活接入", "content": "多种接⼊类型及⽅式,连接随业务⽽动,⽆缝接⼊云应⽤与云数据中⼼。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 43, "name": "精细调度", "content": "应⽤调度 通过DPI协议识别,动态多链路,以及FEC技术,可以在公⽹上保证应⽤的QOE质量", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 44, "name": "敏捷部署", "content": "⼀键部署,部署时间由“周”缩⼩⾄“⼩时”。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
],
|
||||
"tagList": [
|
||||
{"id": 45, "name": "企业组⽹", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 46, "name": "业务多样性", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 45, "name": "企业组⽹", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 46, "name": "业务多样性", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"DCI": {
|
||||
@ -150,14 +150,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"title": "DCI业务",
|
||||
"description": "凭借先进的SDN技术,及覆盖全国网络资源优势,满足客户办公场所至云数据中心、数据中心至云数据中心、云数据中心至云数据中心、数据中心至数据中心的互联需求。解决企业上云最后一公里连接需求,实现多云互联的场景,满足用户数据传送高带宽、高质量、内网化的需求。",
|
||||
"advantageList": [
|
||||
{"id": 47, "name": "大范围", "content": "凭借高质量的全国网,满足用户多地,多区域上云需求。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 48, "name": "优质的网络资源", "content": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 49, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术,SDN技术实现业务可控质量可控。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 50, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
{"id": 47, "name": "大范围", "content": "凭借高质量的全国网,满足用户多地,多区域上云需求。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 48, "name": "优质的网络资源", "content": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 49, "name": "安全稳定的网络结构", "content": "核心网、传输网、接入网采用毫秒级环保护技术,SDN技术实现业务可控质量可控。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 50, "name": "专业化服务", "content": "客户需求第一时间快速响应为您打造便捷的客户服务体系。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"}
|
||||
],
|
||||
"tagList": [
|
||||
{"id": 51, "name": "互联网电商", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id":52, "name": "在线教育", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 51, "name": "互联网电商", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id":52, "name": "在线教育", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"AI": {
|
||||
@ -165,13 +165,13 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"title": "AI专线",
|
||||
"description": "依托国家骨干光缆,建设覆盖全国40个核心城市的40*100G ROADM平台,同时覆盖沿途约100+二级节点城市,除部分边缘省份节点外,其他节点均全部具备多路由的保护。累计光缆资源3万+公里高速主干光纤,4500+公里引接光缆",
|
||||
"advantageList": [
|
||||
{"id": 53, "name": "全国覆盖", "content": "覆盖全国40个核心城市100+二级节点可为全国客户提供大数据量互联互通业务。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 54, "name": "高品质大带宽", "content": "核心传输带宽80*100G,具备80*400G演进能力。", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 55, "name": "定制网络", "content": "基于可编程交换芯片,突破流水线固化结构,建立协议无关的全流水线可编程体系,核心设备软件定义、能力开放精细调度","icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 53, "name": "全国覆盖", "content": "覆盖全国40个核心城市100+二级节点可为全国客户提供大数据量互联互通业务。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 54, "name": "高品质大带宽", "content": "核心传输带宽80*100G,具备80*400G演进能力。", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 55, "name": "定制网络", "content": "基于可编程交换芯片,突破流水线固化结构,建立协议无关的全流水线可编程体系,核心设备软件定义、能力开放精细调度","icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
],
|
||||
"tagList": [
|
||||
{"id": 56, "name": "超算互联", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 57, "name": "AI智算组网", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 56, "name": "超算互联", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 57, "name": "AI智算组网", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
},
|
||||
@ -183,14 +183,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"pre_price": "7143",
|
||||
"price_unit": "台/月",
|
||||
"discount": 8.4,
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/1.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/1.png",
|
||||
"list": [
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7542 32 C * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-4090-24GB * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2 (Raid)", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "Mellanox Connect4 25G SFP28 2-port * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7542 32 C * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-4090-24GB * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2 (Raid)", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "Mellanox Connect4 25G SFP28 2-port * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"4090": {
|
||||
@ -200,14 +200,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"pre_price": "7143",
|
||||
"price_unit": "台/月",
|
||||
"discount": 8.4,
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/2.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/2.png",
|
||||
"list": [
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7542 32 C * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-4090-24GB * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2 (Raid)", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "Mellanox Connect4 25G SFP28 2-port * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7542 32 C * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-4090-24GB * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2 (Raid)", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "Mellanox Connect4 25G SFP28 2-port * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"A100": {
|
||||
@ -217,14 +217,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/3.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/3.png",
|
||||
"list": [
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7543 32 C * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 32", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-A100-80GB-Nvlink * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "MCX653105A - HDAT CX6 200G 1P HDR * 4", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 1, "name": "CPU", "content": "AMD EPYC 7543 32 C * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content": "64G DDR4-3200 * 32", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-A100-80GB-Nvlink * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "MCX653105A - HDAT CX6 200G 1P HDR * 4", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"A800": {
|
||||
@ -234,14 +234,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{"id": 1, "name": "CPU", "content": "Intel (R) Xeon (R) Platinum 8358 32 C * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content":"64G DDR4-3200 * 32", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-A800-80GB-Nvlink * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "MCX653105A - HDAT CX6 200G 1P HDR *4", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 1, "name": "CPU", "content": "Intel (R) Xeon (R) Platinum 8358 32 C * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 2, "name": "内存", "content":"64G DDR4-3200 * 32", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 3, "name": "GPU", "content": "NVIDIA-A800-80GB-Nvlink * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 4, "name": "系统盘", "content": "960G SATA SSD * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 5, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 6, "name": "网卡", "content": "MCX653105A - HDAT CX6 200G 1P HDR *4", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
"910B": {
|
||||
@ -251,14 +251,14 @@ async def get_firstpage_jizuonet(ns={}):
|
||||
"pre_price": "27500",
|
||||
"price_unit": "台/月",
|
||||
"discount": 8,
|
||||
"bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/5.png",
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/5.png",
|
||||
"list": [
|
||||
{"id": 23, "name": "CPU", "content": "鲲鹏920 * 4", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 24, "name": "内存", "content": "32G DDR4-3200 * 32", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 25, "name": "GPU", "content": "昇腾-910B-64GB * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 26, "name": "系统盘", "content": "480G SATA SSD * 2", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 27, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 28, "name": "网卡", "content": "200G QSFP ROCE * 8", "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
{"id": 23, "name": "CPU", "content": "鲲鹏920 * 4", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"},
|
||||
{"id": 24, "name": "内存", "content": "32G DDR4-3200 * 32", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"},
|
||||
{"id": 25, "name": "GPU", "content": "昇腾-910B-64GB * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"},
|
||||
{"id": 26, "name": "系统盘", "content": "480G SATA SSD * 2", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"},
|
||||
{"id": 27, "name": "数据盘", "content": "3.84T U.2 NVMe SSD * 1", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"},
|
||||
{"id": 28, "name": "网卡", "content": "200G QSFP ROCE * 8", "icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"}
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
@ -5,25 +5,25 @@ detailDataDCI = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "大范围",
|
||||
"description": "凭借高质量的全国网,满足用户多地,多区域上云需求。"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "优质的网络资源",
|
||||
"description": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "安全稳定的网络结构",
|
||||
"description": "核心网、传输网、接入网采用毫秒级环保护技术。"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "专业化服务",
|
||||
"description": "客户需求第一时间快速响应为您打造便捷的客户服务体系。"
|
||||
}
|
||||
@ -80,7 +80,7 @@ detailDataDCI = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "互联网电商",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/DCI_hlwds.jpeg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/DCI_hlwds.jpeg",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为互联网电商客户,客户的网站平台部署在各大公有云上,客户要经常更新商品图片、视频、链接、上架、下架等操作。客户要求解决办公网不稳定,带宽不足的问题。",
|
||||
"provide": [
|
||||
@ -117,7 +117,7 @@ detailDataDCI = {
|
||||
{
|
||||
"id": "15",
|
||||
"memuName": "在线教育",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/zxjy.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/zxjy.webp",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为在线教育客户,客户的网站平台部署在各大公有云上,客户要经常更新同步课件、视频、网站等操作。客户要求云厂商之间互访问题,解决使用云厂商出口带宽昂贵的问题。",
|
||||
"provide": [
|
||||
@ -151,7 +151,8 @@ detailDataDCI = {
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataHL = {
|
||||
@ -161,25 +162,25 @@ detailDataHL = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "7*24技术支持",
|
||||
"description": "运维团队7* 24小时守护,快速处理突发事件。"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "优质的网络资源",
|
||||
"description": "结合高质量的传输网及先进的SDN技术,提供优质的网络资源。"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "安全稳定的网络结构",
|
||||
"description": "核心网、传输网、接入网采用毫秒级环保护技术,SDN技术实现业务可控质量可控。"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "专业化服务",
|
||||
"description": "客户需求第一时间快速响应为您打造便捷的客户服务体系。"
|
||||
}
|
||||
@ -241,7 +242,7 @@ detailDataHL = {
|
||||
{
|
||||
"id": "13",
|
||||
"memuName": "单线接入服务",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/HL_dxjr.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/HL_dxjr.webp",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户需求单线接入业务,500Mbit带宽,公司100至300人办公,楼宇物业允许光纤接入红线内,客户要求95计费。要求3跳内进入一级运营商核心网络。",
|
||||
"provide": [
|
||||
@ -274,7 +275,7 @@ detailDataHL = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "多线接入服务",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/HL_dxjr.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/HL_dxjr.jpg",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为集团性质公司,有多地多个办公地点,在业务高峰期,办公总部与其他分公司,分部之间常有因互联网跨运营商访问不畅的问题。需求额解决跨运营商访问问题。200Mbit带宽,公司100至300人办公,各地分公司50至100人不等。楼宇物业允许光纤接入红线内,客户要求95计费。要求跨运营商分公司与总部访问时延均低于50ms,丢包率<1%。",
|
||||
"provide": [
|
||||
@ -316,7 +317,8 @@ detailDataHL = {
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataS = {
|
||||
@ -326,25 +328,25 @@ detailDataS = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "稳定可靠",
|
||||
"description": "⽹络定义软件化, 软、硬件解耦,service-chain,多路径优化。"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "灵活接入",
|
||||
"description": "多种接⼊类型及⽅式,连接随业务⽽动,⽆缝接⼊云应⽤与云数据中⼼。"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "精细调度",
|
||||
"description": "应⽤调度 通过DPI协议识别,动态多链路,以及FEC技术,可以在公⽹上保证应⽤的QOE质量。"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "敏捷部署",
|
||||
"description": "⼀键部署 ,部署时间由“周”缩⼩⾄“⼩时”。"
|
||||
}
|
||||
@ -404,7 +406,7 @@ detailDataS = {
|
||||
{
|
||||
"id": "13",
|
||||
"memuName": "企业组⽹",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/wan_qyzw.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/wan_qyzw.jpg",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为集团化企业,各地拥有分公司,公司业务系统CRM、OA、等内部系统实现内网互联,解决各地组网,降低组网成本的问题。",
|
||||
"provide": [
|
||||
@ -437,7 +439,7 @@ detailDataS = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "企业业务多样性",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/wan_qydyx.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/wan_qydyx.jpg",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户业务分布在公有云,私有云,数据中⼼、海外分⽀节点、办公地点。需求提供企业到各云节点,数据中心,应⽤加速的全业务连通。",
|
||||
"provide": [
|
||||
@ -471,7 +473,8 @@ detailDataS = {
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataAI = {
|
||||
@ -481,19 +484,19 @@ detailDataAI = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "全国覆盖",
|
||||
"description": "覆盖全国40个核心城市100+二级节点可为全国客户提供大数据量互联互通业务。"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "高品质大带宽",
|
||||
"description": "核心传输带宽80*100G,具备80*400G演进能力。"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "定制网络",
|
||||
"description": "服务定制网络(SCN)新型体系架构,在网络承载、网络控制、网络服务三个平面实现多项核心技术突破,突破流水线固化结构,建立协议无关的全流水线可编程体系。"
|
||||
}
|
||||
@ -550,7 +553,7 @@ detailDataAI = {
|
||||
{
|
||||
"id": "13",
|
||||
"memuName": "超算互联",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ai_cshl.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ai_cshl.jpg",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为超算应用企业,全国各大超算中心均有算力应用,公司对超算中心间互联有大带宽高稳定性的需求。",
|
||||
"provide": [
|
||||
@ -583,7 +586,7 @@ detailDataAI = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "AI智算组网",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ai_zszw.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ai_zszw.webp",
|
||||
"title_r": "客户需求",
|
||||
"description_r": "客户为AI大模型应用企业,各地采购了智算中心算力,智算中心间部分业务需要高稳定性,高可靠性,低延迟,低抖动的互联,为关键业务提供链路支撑。",
|
||||
"provide": [
|
||||
@ -609,7 +612,8 @@ detailDataAI = {
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataYITI = {
|
||||
@ -619,37 +623,37 @@ detailDataYITI = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "GPU架构",
|
||||
"description": "通用CPU"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "内存",
|
||||
"description": "64GB DRAMHBM2e"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "半精浮点算力",
|
||||
"description": "256 TFLOPS"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"title": "接口",
|
||||
"description": "PCIeGen4.0x16lane"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "功耗板级功耗",
|
||||
"description": "600W"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"title": "虚拟化",
|
||||
"description": "支持"
|
||||
},
|
||||
@ -701,7 +705,7 @@ detailDataYITI = {
|
||||
{
|
||||
"id": "13",
|
||||
"memuName": "AI4Science",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_ai.jpeg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_ai.jpeg",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [
|
||||
@ -718,7 +722,7 @@ detailDataYITI = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": " 智能客服",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [
|
||||
@ -735,7 +739,7 @@ detailDataYITI = {
|
||||
{
|
||||
"id": "15",
|
||||
"memuName": "智能报告",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [
|
||||
@ -752,7 +756,7 @@ detailDataYITI = {
|
||||
{
|
||||
"id": "16",
|
||||
"memuName": "智慧检务",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [
|
||||
@ -766,7 +770,8 @@ detailDataYITI = {
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataLJS = {
|
||||
@ -776,37 +781,37 @@ detailDataLJS = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "CPU",
|
||||
"description": "AMD EPYC 7542 32Core * 2"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "内存",
|
||||
"description": "512G/64G 4800 MT/s DDR4 * 8"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "系统盘",
|
||||
"description": "960G SATA SSD * 2 (Raid)"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"title": "数据盘",
|
||||
"description": "3.84T U.2 NVMe SSD * 1"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "GPU",
|
||||
"description": "NVIDIA GeForce RTX 4090 * 8"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"title": "光速网卡",
|
||||
"description": "Mellanox ConnectX-4 Lx 25G SFP28 2-port"
|
||||
},
|
||||
@ -847,7 +852,7 @@ detailDataLJS = {
|
||||
"id": "13",
|
||||
# 场景名称
|
||||
"memuName": "AI 深度学习与推理",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ljs_znfx.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ljs_znfx.webp",
|
||||
# 场景的优点
|
||||
"title_r": "模型训练",
|
||||
"description_r": "训练垂类小模型、金融行业文本分类模型微调训练,语料微调。",
|
||||
@ -860,7 +865,7 @@ detailDataLJS = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "智能分析",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ljs_sdxx.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ljs_sdxx.jpg",
|
||||
"title_r": "特效与动画制作",
|
||||
"description_r": "多 GPU 裸金属集群支持大规模并行渲染,无虚拟化损耗让算力 100% 释放,大幅压缩渲染时间。",
|
||||
"provide": [{
|
||||
@ -868,7 +873,432 @@ detailDataLJS = {
|
||||
"content": "2.GPU 加速 AI 推理,裸金属低延迟保障实时分析(如监控画面秒级报警);资源独占确保视频数据安全,符合安防 / 工业合规。"
|
||||
}]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"title": "NVIDIA-4090",
|
||||
"description": "轻量应用服务器(Light server)是一种内置应用型镜像或系统型镜像的小规格云服务器, 绑定适配大小的磁盘和带宽,为中小型企业和个人用户提供官网搭建、web应用搭建、云上学习和测试等场景的服务。",
|
||||
"price": "6000",
|
||||
"pre_price": "7143",
|
||||
"price_unit": "台/月",
|
||||
"discount": 8.4,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/2.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "AMD EPYC 7542 32 C * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G DDR4-3200 * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "NVIDIA-4090-24GB * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "960G SATA SSD * 2 (Raid)",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "3.84T U.2 NVMe SSD * 1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "Mellanox Connect4 25G SFP28 2-port * 1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-A100",
|
||||
"description": "对象存储BOS(Baidu Object Storage)是一款稳定、安全、高效、高可拓展的云存储服务,支持标准、低频、冷和归档存储等多种存储类型满足多场景的存储需求。用户可以将任意数量和形式的非结构化数据存入BOS,并对数据进行管理和处理。",
|
||||
"price": "31000",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/3.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "AMD EPYC 7543 32 C * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G DDR4-3200 * 32",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "NVIDIA-A100-80GB-Nvlink * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "960G SATA SSD * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "3.84T U.2 NVMe SSD * 1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "MCX653105A - HDAT CX6 200G 1P HDR * 4",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-A800",
|
||||
"description": "云数据库 RDS为用户提供高性价比、安全可靠、性能卓越、易于维护的企业级云数据库服务。",
|
||||
"price": "32000",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "Intel (R) Xeon (R) Platinum 8358 32 C * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G DDR4-3200 * 32",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "NVIDIA-A800-80GB-Nvlink * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "960G SATA SSD * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "3.84T U.2 NVMe SSD * 1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "MCX653105A - HDAT CX6 200G 1P HDR *4",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "昇腾-910B",
|
||||
"description": "裸金属服务器是一种融合了高性能 GPU 计算能力、裸金属服务器物理资源独占性及云计算弹性扩展特性的新型服务器形态。它既具备传统裸金属服务器的强劲性能与安全性,又能像云服务器一样按需灵活调整资源,适用于对算力、资源独占性和弹性要求极高的场景。",
|
||||
"price": "22000",
|
||||
"pre_price": "27500",
|
||||
"price_unit": "台/月",
|
||||
"discount": 8,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/5.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 23,
|
||||
"name": "CPU",
|
||||
"content": "鲲鹏920 * 4",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "内存",
|
||||
"content": "32G DDR4-3200 * 32",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "GPU",
|
||||
"content": "昇腾-910B-64GB * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "系统盘",
|
||||
"content": "480G SATA SSD * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "数据盘",
|
||||
"content": "3.84T U.2 NVMe SSD * 1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "网卡",
|
||||
"content": "200G QSFP ROCE * 8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-4090",
|
||||
"description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.",
|
||||
"price": "9000",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "Intel Xeon Gold 6430*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G-DDR5 ECC*16",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "4090-24G 涡轮版*8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "SATA-SSD-480G*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "NVMe-SSD 3.84T*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "25G 光口双口CX5*1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-4090-48G",
|
||||
"description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.",
|
||||
"price": "8800",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "Intel Xeon 6530/32核心/2.1GHz;*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G DDR5 4800MHZ ECC REG*16",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "8*RTX4090(48g)涡轮;(直通模式)",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "SATA-SSD-960G*1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "NVMe-SSD 3.84T*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "25G 光口双口CX5*1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-4090",
|
||||
"description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.",
|
||||
"price": "8000",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "Intel Xeon 6530/32核心/2.1GHz *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "64G DDR5 4800MHZ ECC REG*16",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "8*RTX4090(24g)涡轮;(直通模式)",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "SATA-SSD-960G*1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "NVMe-SSD 3.84T*2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "25G 光口双口CX5*1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-4090",
|
||||
"description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.",
|
||||
"price": "7200",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "Intel Xeon 6530/32核心/2.1GHz *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "32GB DDR4-3200ECCREG RDIMM *16",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "Geforce RTX4090 24GPCI-e 涡轮GPU卡 *8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "2.5\"480G SATA 读取密集 SSD *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "NVMe-SSD 1.92T *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "25G 光口双口CX5 *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "NVIDIA-4090",
|
||||
"description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.",
|
||||
"price": "6200",
|
||||
"pre_price": None,
|
||||
"price_unit": "台/月",
|
||||
"discount": None,
|
||||
"bgImgUrl": "https://www.opencomputing.cn/idfile?path=firstpagebg/4.png",
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "CPU",
|
||||
"content": "AMD EPYC 7542 32Core * 2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "内存",
|
||||
"content": "512G / 64G 3200 MT/s DDR4*8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "GPU",
|
||||
"content": "Geforce RTX4090 24GPCI-e *8",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "系统盘",
|
||||
"content": "960G SATA SSD *2",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "数据盘",
|
||||
"content": "NVMe-SSD 3.84T *1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "网卡",
|
||||
"content": "25G 光口双口CX5 *1",
|
||||
"icon": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
detailDataRQY = {
|
||||
@ -878,19 +1308,19 @@ detailDataRQY = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "极简易用,快速上手",
|
||||
"description": "容器与资源一体化,开发者无需运维管理集群和 节点。通过控制台简单配置,即可快速创建部署 业务,大幅降低使用 容器算力的门槛。"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "按需弹性,灵活付费",
|
||||
"description": "支持灵活的 Pod 资源规格,秒级弹性,提供按需 弹性秒级按量付费和包年包月付费。"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "灵活调配,高性价比",
|
||||
"description": "支持灵活的 Pod 资源规格,秒级弹性,提供按需 弹性秒级按量付费和包年包月付费。"
|
||||
},
|
||||
@ -948,7 +1378,7 @@ detailDataRQY = {
|
||||
"id": "13",
|
||||
# 场景名称
|
||||
"memuName": " 混合云和多云环境",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/rqy_hhy.jpeg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/rqy_hhy.jpeg",
|
||||
# 场景的优点
|
||||
"title_r": "模型训练",
|
||||
"description_r": "训练垂类小模型、金融行业文本分类模型微调训练,语料微调。",
|
||||
@ -961,7 +1391,7 @@ detailDataRQY = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "大规模计算和数据处理",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/rqy_js.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/rqy_js.webp",
|
||||
"title_r": "大规模并行渲染",
|
||||
"description_r": "多GPU裸金属集群支持大规模并行渲染,无虚拟化损耗让算力 100% 释放,大幅压缩渲染时间。",
|
||||
"provide": [{
|
||||
@ -969,7 +1399,8 @@ detailDataRQY = {
|
||||
"content": "在处理大规模计算任务时,容器可以帮助管理和调度大量的计算任务,确保资源的高效利用"
|
||||
}]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
detailDataLJS910B = {
|
||||
@ -979,37 +1410,37 @@ detailDataLJS910B = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "CPU",
|
||||
"description": "4 * 鲲鹏920"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "内存",
|
||||
"description": "32个DDR4"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "显存",
|
||||
"description": "64 GB"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"title": "存储",
|
||||
"description": "8 * 2.5 SATA+2 * 2.5 NVMe"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "接口",
|
||||
"description": "8 * 200GE QSFP"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"title": "协议",
|
||||
"description": "支持RoCE"
|
||||
},
|
||||
@ -1067,7 +1498,7 @@ detailDataLJS910B = {
|
||||
"id": "13",
|
||||
# 场景名称
|
||||
"memuName": "AI 深度学习与推理",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ljs_znfx.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ljs_znfx.webp",
|
||||
# 场景的优点
|
||||
"title_r": "模型训练",
|
||||
"description_r": "训练垂类小模型、金融行业文本分类模型微调训练,语料微调。",
|
||||
@ -1080,7 +1511,7 @@ detailDataLJS910B = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "智能分析",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ljs_sdxx.jpg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ljs_sdxx.jpg",
|
||||
"title_r": "特效与动画制作",
|
||||
"description_r": "多 GPU 裸金属集群支持大规模并行渲染,无虚拟化损耗让算力 100% 释放,大幅压缩渲染时间。",
|
||||
"provide": [{
|
||||
@ -1088,7 +1519,8 @@ detailDataLJS910B = {
|
||||
"content": "2.GPU 加速 AI 推理,裸金属低延迟保障实时分析(如监控画面秒级报警);资源独占确保视频数据安全,符合安防 / 工业合规。"
|
||||
}]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
|
||||
@ -1099,37 +1531,37 @@ detailDataYITIKUNLUN = {
|
||||
"adList": [
|
||||
{
|
||||
"id": "1",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssc2x.png",
|
||||
"title": "产品型号",
|
||||
"description": "P800 OAM 模组"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/cpu2x.png",
|
||||
"title": "支持精度",
|
||||
"description": "FP32/FP16/BF16;INT8"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/sdcard2x.png",
|
||||
"title": "显存",
|
||||
"description": "96GB"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/ssdr2x.png",
|
||||
"title": "主机设备互联",
|
||||
"description": "PCIe 5.0x16"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/servermini2x.png",
|
||||
"title": "节点内互联",
|
||||
"description": "XPU Link"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/serverpath2x.png",
|
||||
"title": "服务器集成",
|
||||
"description": "单机内集成8个OAM 模组"
|
||||
},
|
||||
@ -1191,7 +1623,7 @@ detailDataYITIKUNLUN = {
|
||||
{
|
||||
"id": "13",
|
||||
"memuName": "训练集群、生态建设",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_ai.jpeg",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_ai.jpeg",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [
|
||||
@ -1216,7 +1648,7 @@ detailDataYITIKUNLUN = {
|
||||
{
|
||||
"id": "14",
|
||||
"memuName": "与运营商深度合作",
|
||||
"img": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"img": "https://www.opencomputing.cn/idfile?path=firstpagehot/yitiji_znkf.webp",
|
||||
"title_r": None,
|
||||
"description_r": None,
|
||||
"provide": [{
|
||||
@ -1224,7 +1656,8 @@ detailDataYITIKUNLUN = {
|
||||
"content": "与某运营商深度合作—— 技术测评领先、共建实验室、商业化落地,制定智能计算技术架构、评估AI 芯片功能/性能等指标、打造算力原生平台、为实验室提供强大算力底座,携手运营商解决智算发展中面临的挑战,共同实现智算技术引领。"
|
||||
}]
|
||||
}
|
||||
]
|
||||
],
|
||||
"products": []
|
||||
}
|
||||
|
||||
async def get_firstpage_net_detail(ns={}):
|
||||
|
||||
@ -582,7 +582,7 @@ async def get_firstpage_product_tree(ns={}):
|
||||
{
|
||||
'id': '211',
|
||||
'thrTitle': None,
|
||||
'value': [{'id': '2111', 'name': '容器云'},
|
||||
'value': [#{'id': '2111', 'name': '容器云'},
|
||||
{'id': '2113', 'name': '裸金属'},
|
||||
#{'id': '2114', 'name': '裸金属-910B'},
|
||||
{'id': '2115', 'name': '一体机-昆仑芯'},
|
||||
@ -660,7 +660,7 @@ async def get_firstpage_product_tree(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if ns.get('url_link') and 'kaiyuancloud' in ns.get('url_link'):
|
||||
if ns.get('url_link') and ('kaiyuancloud' in ns.get('url_link') or 'opencomputing' in ns.get('url_link')):
|
||||
data_baidu = {
|
||||
"id": "12",
|
||||
"secTitle": "阿里云",
|
||||
|
||||
@ -21,6 +21,8 @@ async def baidu_query_by_expire_time(ns={}):
|
||||
'msg': 'User not synchronized'
|
||||
}
|
||||
ns['queryAccountId'] = baiduid
|
||||
ns['pageNo'] = int(ns.get('pageno', 1))
|
||||
ns['pageSize'] = int(ns.get('pagesize', 100))
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/resource/queryByExpireTime?%s' % ns_format
|
||||
@ -35,11 +37,18 @@ async def baidu_query_by_expire_time(ns={}):
|
||||
json=ns) as res:
|
||||
data_ = await res.json()
|
||||
print('data_', data_)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get baidu resource expire time success',
|
||||
'data': data_
|
||||
}
|
||||
if data_.get('pageSize'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get baidu resource expire time success',
|
||||
'data': data_
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'get baidu resource expire time failed',
|
||||
'data': data_
|
||||
}
|
||||
|
||||
async def calculate_time_diff(time_str=None):
|
||||
# 将字符串时间转换为 datetime 对象
|
||||
@ -63,22 +72,46 @@ async def get_resource_expire_time(ns={}):
|
||||
else:
|
||||
userid = await get_user()
|
||||
data = []
|
||||
baidu_resource_data = await baidu_query_by_expire_time({'userid': userid})
|
||||
baidu_resource_data = await baidu_query_by_expire_time(ns)
|
||||
if baidu_resource_data.get('data'):
|
||||
for baidubaidu_resource in baidu_resource_data['data']['result']:
|
||||
baidu_r = {
|
||||
'id': uuid(),
|
||||
'name': baidubaidu_resource['serviceTypeName'],
|
||||
'instanceid': baidubaidu_resource['instanceId'],
|
||||
'status': baidubaidu_resource['status'],
|
||||
'expiretime': await time_convert(baidubaidu_resource['expireTime']),
|
||||
'days': await calculate_time_diff(baidubaidu_resource['expireTime'])
|
||||
}
|
||||
data.append(baidu_r)
|
||||
data_result = baidu_resource_data['data']['result'] if baidu_resource_data['data'].get('result') else []
|
||||
# if not data_result:
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'msg': '无资源数据',
|
||||
# 'data': str(baidu_resource_data['data'])
|
||||
# }
|
||||
for baidubaidu_resource in data_result:
|
||||
baidubaidu_resource['id'] = uuid()
|
||||
baidubaidu_resource['name'] = baidubaidu_resource['serviceTypeName']
|
||||
baidubaidu_resource['instanceid'] = baidubaidu_resource['shortId']
|
||||
baidubaidu_resource['expiretime'] = await time_convert(baidubaidu_resource['expireTime'])
|
||||
baidubaidu_resource['days'] = await calculate_time_diff(baidubaidu_resource['expireTime'])
|
||||
|
||||
# 读取数据库表product,匹配跳转链接
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
find_sql = """select * from product where providerpid='baidu_%s' and del_flg='0';""" % baidubaidu_resource['serviceType']
|
||||
product_li = await sor.sqlExe(find_sql, {})
|
||||
spec_note_li = json.loads(product_li[0]['spec_note']) if product_li else []
|
||||
for spec_note in spec_note_li:
|
||||
if spec_note.get('configName') == 'listUrl':
|
||||
baidubaidu_resource['list_url'] = spec_note.get('value')
|
||||
break
|
||||
else:
|
||||
baidubaidu_resource['list_url'] = ''
|
||||
|
||||
data.append(baidubaidu_resource)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get resouce expire time success',
|
||||
'data': data
|
||||
'data': data,
|
||||
# 分页
|
||||
'pagination': {
|
||||
'total': baidu_resource_data['data'].get('totalCount'),
|
||||
'page_size': baidu_resource_data['data'].get('pageSize'),
|
||||
'current_page': baidu_resource_data['data'].get('pageNo')
|
||||
}
|
||||
}
|
||||
|
||||
ret = await get_resource_expire_time(params_kw)
|
||||
|
||||
80
b/product/global_search.dspy
Normal file
80
b/product/global_search.dspy
Normal file
@ -0,0 +1,80 @@
|
||||
async def global_search(ns={}):
|
||||
if not ns.get('url_link') or not ns.get('publish_type'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递路由链接(url_link)和发布类型(publish_type)'
|
||||
}
|
||||
if not ns.get('keyword'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递搜索关键词'
|
||||
}
|
||||
if not ns.get('display_page'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递回显页面(display_page)'
|
||||
}
|
||||
|
||||
# 增加分页功能
|
||||
current_page = int(ns.get('current_page')) if ns.get('current_page') else 1
|
||||
page_size = int(ns.get('page_size')) if ns.get('page_size') else 8
|
||||
|
||||
# 分页查询
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 增加分页条件
|
||||
# 分页条件
|
||||
find_sql = """SELECT * FROM user_publish_product WHERE publish_type = '%s' AND domain_name = '%s' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' ORDER BY priority DESC LIMIT %s OFFSET %s;"""
|
||||
find_sql = find_sql % (ns.get('publish_type'), domain_name, page_size, offset)
|
||||
|
||||
# 添加keyword模糊查询 筛选product_name, requirement_summary
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(product_name LIKE '%%%%%s%%%%' OR requirement_summary LIKE '%%%%%s%%%%') AND " % (ns.get('keyword'), ns.get('keyword')) + find_sql.split('WHERE')[1]
|
||||
|
||||
# 如果是overview sql不筛选requirement_summary
|
||||
if ns.get('display_page') == 'overview':
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(product_name LIKE '%%%%%s%%%%') AND " % (ns.get('keyword')) + find_sql.split('WHERE')[1]
|
||||
|
||||
# 计算筛选后 返回总数量 count(*)
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE publish_type = '%s' AND domain_name = '%s' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND (product_name LIKE '%%%%%s%%%%' OR requirement_summary LIKE '%%%%%s%%%%');"""
|
||||
count_sql = count_sql % (ns.get('publish_type'), domain_name, ns.get('keyword'), ns.get('keyword'))
|
||||
count_result = await sor.sqlExe(count_sql, {})
|
||||
total_count = count_result[0]['total_count']
|
||||
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
for res in result:
|
||||
if res.get('img') and res['img'] != 'null':
|
||||
res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img']
|
||||
else:
|
||||
res['img'] = None
|
||||
|
||||
# 根据display_page区分返回字段
|
||||
if ns.get('display_page') == 'overview':
|
||||
# result 产品名称去重后的 产品名称列表 根据名称去重
|
||||
product_names = list(set([item['product_name'] for item in result]))
|
||||
# 产品名称添加 uuid形成的八位id 形成列表嵌套字典的格式
|
||||
result = [{ 'id': str(uuid())[:8], 'product_name': product_name} for product_name in product_names]
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search success',
|
||||
'data': {
|
||||
'current_page': current_page,
|
||||
'page_size': page_size,
|
||||
'total_count': total_count,
|
||||
'result': result
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to search publish product, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await global_search(params_kw)
|
||||
return ret
|
||||
50
b/product/home_page_content_add.dspy
Normal file
50
b/product/home_page_content_add.dspy
Normal file
@ -0,0 +1,50 @@
|
||||
async def home_page_content_add(ns={}):
|
||||
"""
|
||||
添加首页内容项
|
||||
:param ns: 包含content_type, title, description等字段的字典
|
||||
:return: 创建结果
|
||||
"""
|
||||
ns_dic = {
|
||||
'id': uuid(), # 固定写法
|
||||
'menu_product_id': ns.get('menu_product_id'),
|
||||
'parent_id': ns.get('parent_id'),
|
||||
'level': ns.get('level', 1),
|
||||
'content_type': ns.get('content_type'), # advantage, feature, application, product
|
||||
'sort_order': ns.get('sort_order', 0),
|
||||
'title': ns.get('title'),
|
||||
'description': ns.get('description'),
|
||||
'img': ns.get('img'),
|
||||
'name': ns.get('name'),
|
||||
'price': ns.get('price'),
|
||||
'pre_price': ns.get('pre_price'),
|
||||
'price_unit': ns.get('price_unit'),
|
||||
'discount': ns.get('discount'),
|
||||
'bg_img_url': ns.get('bg_img_url'),
|
||||
'icon': ns.get('icon')
|
||||
}
|
||||
|
||||
# 必填字段验证
|
||||
if not ns_dic.get('content_type'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'content_type is required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.C('home_page_content_items', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'create home page content success',
|
||||
'data': {'id': ns_dic['id']}
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'create home page content failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_content_add(params_kw)
|
||||
return ret
|
||||
33
b/product/home_page_content_delete.dspy
Normal file
33
b/product/home_page_content_delete.dspy
Normal file
@ -0,0 +1,33 @@
|
||||
async def home_page_content_delete(ns={}):
|
||||
"""
|
||||
软删除内容项,id值必传并且把del_flg值修改为1
|
||||
:param ns: 包含id的字典
|
||||
:return: 删除结果
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'id is required'
|
||||
}
|
||||
|
||||
ns_dic = {
|
||||
'id': ns.get('id'),
|
||||
'del_flg': '1'
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_content_items', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'delete home page content success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delete home page content failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_content_delete(params_kw)
|
||||
return ret
|
||||
118
b/product/home_page_content_get_tree.dspy
Normal file
118
b/product/home_page_content_get_tree.dspy
Normal file
@ -0,0 +1,118 @@
|
||||
async def home_page_content_get_tree(ns={}):
|
||||
"""
|
||||
获取首页内容的树形结构,按content_type分组
|
||||
:param ns: 包含menu_product_id的字典
|
||||
:return: 树形结构数据
|
||||
"""
|
||||
menu_product_id = ns.get('menu_product_id')
|
||||
|
||||
if not menu_product_id:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'menu_product_id is required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 查询所有有效的内容项
|
||||
sql = """
|
||||
SELECT * FROM home_page_content_items
|
||||
WHERE menu_product_id = '%s' AND del_flg = '0'
|
||||
ORDER BY sort_order ASC, create_at ASC
|
||||
""" % menu_product_id
|
||||
all_items = await sor.sqlExe(sql, {})
|
||||
|
||||
# 通过home_page_product_info表查找标题和描述
|
||||
find_sql = """
|
||||
SELECT * FROM home_page_product_info
|
||||
WHERE id = '%s' AND del_flg = '0'
|
||||
""" % menu_product_id
|
||||
product_info = await sor.sqlExe(find_sql, {})
|
||||
product_title = None
|
||||
product_description = None
|
||||
if product_info:
|
||||
product_info = product_info[0]
|
||||
product_title = product_info.get('name', '')
|
||||
product_description = product_info.get('description', '')
|
||||
|
||||
# 按content_type分组
|
||||
result = {
|
||||
'title': product_title, # 可以从其他表获取
|
||||
'description': product_description, # 可以从其他表获取
|
||||
'advantages': [],
|
||||
'features': [],
|
||||
'applications': [],
|
||||
'products': []
|
||||
}
|
||||
|
||||
for item in all_items:
|
||||
content_type = item.get('content_type')
|
||||
item_data = {
|
||||
'id': item['id'],
|
||||
'title': item['title'],
|
||||
'description': item['description'],
|
||||
'img': item['img'],
|
||||
'icon': item['icon']
|
||||
}
|
||||
|
||||
# 根据内容类型添加到对应的列表
|
||||
if content_type == 'advantage':
|
||||
result['advantages'].append(item_data)
|
||||
elif content_type == 'feature':
|
||||
result['features'].append(item_data)
|
||||
elif content_type == 'application':
|
||||
# 应用场景可能包含子项
|
||||
app_data = item_data.copy()
|
||||
if not item.get('parent_id'): # 顶级应用
|
||||
app_data['provide'] = [] # 子项将在后续处理
|
||||
result['applications'].append(app_data)
|
||||
elif content_type == 'product' and not item.get('parent_id'):
|
||||
# 产品可能包含配置项
|
||||
product_data = item_data.copy()
|
||||
product_data['price'] = item.get('price')
|
||||
product_data['pre_price'] = item.get('pre_price')
|
||||
product_data['price_unit'] = item.get('price_unit')
|
||||
product_data['discount'] = item.get('discount')
|
||||
product_data['bg_img_url'] = item.get('bg_img_url')
|
||||
product_data['list'] = [] # 子项将在后续处理
|
||||
result['products'].append(product_data)
|
||||
|
||||
# 处理子级项目
|
||||
for item in all_items:
|
||||
if item.get('parent_id') != '0':
|
||||
parent_id = item.get('parent_id')
|
||||
content_type = item.get('content_type')
|
||||
|
||||
# 查找父级并添加子项
|
||||
if content_type == 'application':
|
||||
for app in result['applications']:
|
||||
if app['id'] == parent_id:
|
||||
app['provide'].append({
|
||||
'id': item['id'],
|
||||
'title': item['title'],
|
||||
'description': item['description']
|
||||
})
|
||||
elif content_type == 'product':
|
||||
for product in result['products']:
|
||||
if product['id'] == parent_id:
|
||||
product['list'].append({
|
||||
'id': item['id'],
|
||||
'name': item['name'],
|
||||
'description': item['description'],
|
||||
'icon': item['icon']
|
||||
})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get home page content tree success',
|
||||
'data': result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'get home page content tree failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_content_get_tree(params_kw)
|
||||
return ret
|
||||
36
b/product/home_page_content_search.dspy
Normal file
36
b/product/home_page_content_search.dspy
Normal file
@ -0,0 +1,36 @@
|
||||
async def home_page_content_search(ns={}):
|
||||
"""
|
||||
查找内容项,支持按内容类型、父级ID等条件查询
|
||||
:param ns: 查询条件字典
|
||||
:return: 查询结果
|
||||
"""
|
||||
# 构建查询条件
|
||||
conditions = {"del_flg": "0"}
|
||||
|
||||
if ns.get('content_type'):
|
||||
conditions['content_type'] = ns.get('content_type')
|
||||
if ns.get('parent_id'):
|
||||
conditions['parent_id'] = ns.get('parent_id')
|
||||
if ns.get('menu_product_id'):
|
||||
conditions['menu_product_id'] = ns.get('menu_product_id')
|
||||
if ns.get('id'):
|
||||
conditions['id'] = ns.get('id')
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
result = await sor.R('home_page_content_items', conditions)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search home page content success',
|
||||
'data': result
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'search home page content failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_content_search(params_kw)
|
||||
return ret
|
||||
39
b/product/home_page_content_update.dspy
Normal file
39
b/product/home_page_content_update.dspy
Normal file
@ -0,0 +1,39 @@
|
||||
async def home_page_content_update(ns={}):
|
||||
"""
|
||||
更新内容项
|
||||
:param ns: 包含id和需要更新的字段的字典
|
||||
:return: 更新结果
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'id is required'
|
||||
}
|
||||
|
||||
# 构建更新字段,排除空值
|
||||
ns_dic = {'id': ns.get('id')}
|
||||
update_fields = ['title', 'description', 'img', 'name', 'price',
|
||||
'pre_price', 'price_unit', 'discount', 'bg_img_url',
|
||||
'icon', 'sort_order', 'parent_id', 'level']
|
||||
|
||||
for field in update_fields:
|
||||
if ns.get(field):
|
||||
ns_dic[field] = ns.get(field)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_content_items', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'update home page content success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'update home page content failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_content_update(params_kw)
|
||||
return ret
|
||||
45
b/product/home_page_product_add.dspy
Normal file
45
b/product/home_page_product_add.dspy
Normal file
@ -0,0 +1,45 @@
|
||||
async def home_page_product_add(ns={}):
|
||||
"""
|
||||
添加产品信息
|
||||
:param ns: 包含产品信息的字典
|
||||
"""
|
||||
ns_dic = {
|
||||
'id': uuid(), # 固定写法
|
||||
'menu_id': ns.get('menu_id'),
|
||||
'name': ns.get('name'),
|
||||
'description': ns.get('description'),
|
||||
'label': ns.get('label'),
|
||||
'product_group': ns.get('product_group'),
|
||||
'url': ns.get('url'),
|
||||
'list_url': ns.get('list_url'),
|
||||
'icon_url': ns.get('icon_url'),
|
||||
'source': ns.get('source'),
|
||||
'sort_order': ns.get('sort_order', 0),
|
||||
'del_flg': '0'
|
||||
}
|
||||
|
||||
# 验证必填字段
|
||||
if not ns_dic.get('menu_id') or not ns_dic.get('name'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'menu_id and name are required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.C('home_page_product_info', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'create product success',
|
||||
'data': {'id': ns_dic['id']}
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'create product failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_add(params_kw)
|
||||
return ret
|
||||
33
b/product/home_page_product_delete.dspy
Normal file
33
b/product/home_page_product_delete.dspy
Normal file
@ -0,0 +1,33 @@
|
||||
async def home_page_product_delete(ns={}):
|
||||
"""
|
||||
软删除产品信息 id值必传 并且把del_flg值修改为1
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'product id is required'
|
||||
}
|
||||
|
||||
ns_dic = {
|
||||
'id': ns.get('id'),
|
||||
'del_flg': '1'
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_product_info', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'delete product success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delete product failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_delete(params_kw)
|
||||
return ret
|
||||
45
b/product/home_page_product_menu_add.dspy
Normal file
45
b/product/home_page_product_menu_add.dspy
Normal file
@ -0,0 +1,45 @@
|
||||
async def home_page_product_menu_add(ns={}):
|
||||
"""
|
||||
添加首页产品菜单
|
||||
:param ns: 包含菜单信息的字典
|
||||
"""
|
||||
ns_dic = {
|
||||
'id': uuid(), # 固定写法
|
||||
'parent_id': ns.get('parent_id'), # NULL表示一级菜单
|
||||
'menu_level': ns.get('menu_level'), # 1-一级, 2-二级, 3-三级
|
||||
'title': ns.get('title'),
|
||||
'sort_order': ns.get('sort_order', 0)
|
||||
}
|
||||
|
||||
|
||||
# 验证必填字段
|
||||
# if not ns_dic.get('menu_level') or not ns_dic.get('title'):
|
||||
# return {
|
||||
# 'status': False,
|
||||
# 'msg': 'menu_level and title are required'
|
||||
# }
|
||||
|
||||
if int(ns.get('menu_level')) > 1 and not ns.get('parent_id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'parent_id is required for menu_level > 1'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.C('home_page_product_menu', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'create menu success',
|
||||
'data': {'id': ns_dic['id']}
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'create menu failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_menu_add(params_kw)
|
||||
return ret
|
||||
33
b/product/home_page_product_menu_delete.dspy
Normal file
33
b/product/home_page_product_menu_delete.dspy
Normal file
@ -0,0 +1,33 @@
|
||||
async def home_page_product_menu_delete(ns={}):
|
||||
"""
|
||||
软删除菜单 id值必传 并且把del_flg值修改为1
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'menu id is required'
|
||||
}
|
||||
|
||||
ns_dic = {
|
||||
'id': ns.get('id'),
|
||||
'del_flg': '1'
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_product_menu', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'delete menu success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delete menu failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_menu_delete(params_kw)
|
||||
return ret
|
||||
229
b/product/home_page_product_menu_search.dspy
Normal file
229
b/product/home_page_product_menu_search.dspy
Normal file
@ -0,0 +1,229 @@
|
||||
async def home_page_product_menu_search(ns={}):
|
||||
"""
|
||||
查找菜单,支持按层级和父级ID筛选
|
||||
规则:
|
||||
1. 无参数时,返回所有数据并有嵌套层级
|
||||
2. 有参数时,menu_level和title必传,返回当前层级以及向下的嵌套层级数据
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 无参数时,返回所有数据
|
||||
if not ns:
|
||||
conditions = {"del_flg": "0"}
|
||||
result = await sor.R('home_page_product_menu', conditions)
|
||||
menu_tree = await build_menu_tree(result)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search all menu success',
|
||||
'data': menu_tree
|
||||
}
|
||||
|
||||
# 有参数时,验证必填参数
|
||||
# if not ns.get('menu_level') or not ns.get('title'):
|
||||
# return {
|
||||
# 'status': False,
|
||||
# 'msg': 'menu_level and title are required when parameters are provided'
|
||||
# }
|
||||
|
||||
# 获取指定层级及向下层级的数据
|
||||
menu_level = int(ns.get('menu_level'))
|
||||
title = ns.get('title')
|
||||
|
||||
# 构建查询条件,获取当前层级及向下层级的数据
|
||||
conditions = {"del_flg": "0"}
|
||||
|
||||
# 根据层级获取相应的数据
|
||||
if menu_level == 1:
|
||||
# 获取所有层级的数据,用于构建完整的树形结构
|
||||
all_conditions = {"del_flg": "0"}
|
||||
if title:
|
||||
# 如果指定了标题,获取所有层级中标题匹配的数据
|
||||
all_result = await sor.R('home_page_product_menu', all_conditions)
|
||||
filtered_result = [item for item in all_result if title in item.get('title', '')]
|
||||
|
||||
# 获取匹配项的所有子级数据
|
||||
result = []
|
||||
parent_ids = set()
|
||||
|
||||
# 收集一级菜单的ID
|
||||
for item in filtered_result:
|
||||
if item['menu_level'] == 1:
|
||||
parent_ids.add(item['id'])
|
||||
result.append(item)
|
||||
|
||||
# 获取所有子级数据
|
||||
if parent_ids:
|
||||
all_data = await sor.R('home_page_product_menu', {"del_flg": "0"})
|
||||
for item in all_data:
|
||||
if item['parent_id'] in parent_ids:
|
||||
result.append(item)
|
||||
|
||||
menu_tree = await build_menu_tree(result)
|
||||
else:
|
||||
# 获取所有数据
|
||||
result = await sor.R('home_page_product_menu', all_conditions)
|
||||
menu_tree = await build_menu_tree(result)
|
||||
|
||||
elif menu_level == 2:
|
||||
# 获取二级菜单及其子级(三级)
|
||||
all_conditions = {"del_flg": "0"}
|
||||
all_result = await sor.R('home_page_product_menu', all_conditions)
|
||||
|
||||
# 筛选匹配的二级菜单
|
||||
level2_items = [item for item in all_result if item['menu_level'] == 2 and title in item.get('title', '')]
|
||||
|
||||
if level2_items:
|
||||
parent_ids = set(item['id'] for item in level2_items)
|
||||
|
||||
# 获取对应的一级菜单
|
||||
result = []
|
||||
for item in all_result:
|
||||
if item['menu_level'] == 1 and any(level2['parent_id'] == item['id'] for level2 in level2_items):
|
||||
result.append(item)
|
||||
|
||||
# 添加匹配的二级菜单
|
||||
result.extend(level2_items)
|
||||
|
||||
# 获取三级子菜单
|
||||
for item in all_result:
|
||||
if item['menu_level'] == 3 and item['parent_id'] in parent_ids:
|
||||
result.append(item)
|
||||
|
||||
menu_tree = await build_menu_tree(result)
|
||||
else:
|
||||
menu_tree = []
|
||||
|
||||
elif menu_level == 3:
|
||||
# 获取三级菜单
|
||||
all_conditions = {"del_flg": "0"}
|
||||
all_result = await sor.R('home_page_product_menu', all_conditions)
|
||||
|
||||
# 筛选匹配的三级菜单
|
||||
level3_items = [item for item in all_result if item['menu_level'] == 3 and title in item.get('title', '')]
|
||||
|
||||
if level3_items:
|
||||
result = []
|
||||
|
||||
# 获取对应的二级和一级菜单
|
||||
level2_ids = set()
|
||||
level1_ids = set()
|
||||
|
||||
for item in level3_items:
|
||||
level2_ids.add(item['parent_id'])
|
||||
|
||||
for item in all_result:
|
||||
if item['menu_level'] == 2 and item['id'] in level2_ids:
|
||||
result.append(item)
|
||||
level1_ids.add(item['parent_id'])
|
||||
|
||||
for item in all_result:
|
||||
if item['menu_level'] == 1 and item['id'] in level1_ids:
|
||||
result.append(item)
|
||||
|
||||
# 添加匹配的三级菜单
|
||||
result.extend(level3_items)
|
||||
|
||||
menu_tree = await build_menu_tree(result)
|
||||
else:
|
||||
menu_tree = []
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Invalid menu_level, must be 1, 2, or 3'
|
||||
}
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search menu success',
|
||||
'data': menu_tree
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'search menu failed, %s' % str(e)
|
||||
}
|
||||
|
||||
async def get_home_page_product(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
find_sql = """select * from home_page_product_info where menu_id = '%s' and del_flg = '0' order by sort_order asc;""" % ns.get("menu_id")
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
return result
|
||||
|
||||
# 构建菜单树形结构
|
||||
async def build_menu_tree(menu_list, target_level=None, target_title=None):
|
||||
"""
|
||||
将扁平的菜单列表转换为树形结构
|
||||
:param menu_list: 菜单列表
|
||||
:param target_level: 目标层级(可选)
|
||||
:param target_title: 目标标题(可选)
|
||||
:return: 树形结构的菜单
|
||||
"""
|
||||
|
||||
# 通过sort_order对菜单进行排序
|
||||
menu_list.sort(key=lambda x: int(x['sort_order']), reverse=False)
|
||||
|
||||
menu_dict = {}
|
||||
result = []
|
||||
|
||||
# 先创建所有菜单的字典
|
||||
for menu in menu_list:
|
||||
# 创建菜单节点的基本结构
|
||||
menu_node = {
|
||||
'id': menu['id'],
|
||||
'title': menu['title'],
|
||||
'menu_level': menu['menu_level'],
|
||||
'parent_id': menu['parent_id'],
|
||||
'children': [] # 动态子菜单数组
|
||||
}
|
||||
menu_dict[menu['id']] = menu_node
|
||||
|
||||
# 构建父子关系
|
||||
for menu in menu_list:
|
||||
menu_node = menu_dict[menu['id']]
|
||||
parent_id = menu['parent_id']
|
||||
|
||||
# 如果有父级且父级存在
|
||||
if parent_id and parent_id in menu_dict:
|
||||
parent_node = menu_dict[parent_id]
|
||||
parent_node['children'].append(menu_node)
|
||||
else:
|
||||
# 没有父级的菜单(根节点)
|
||||
result.append(menu_node)
|
||||
|
||||
# 递归构建层级结构
|
||||
async def build_hierarchy(node, level=1):
|
||||
"""递归构建层级结构"""
|
||||
if level == 1:
|
||||
return {
|
||||
'id': node['id'],
|
||||
'firTitle': node['title'],
|
||||
'secMenu': [await build_hierarchy(child, 2) for child in node['children']]
|
||||
}
|
||||
elif level == 2:
|
||||
return {
|
||||
'id': node['id'],
|
||||
'secTitle': node['title'],
|
||||
'thrMenu': [await build_hierarchy(child, 3) for child in node['children']]
|
||||
}
|
||||
else:
|
||||
# 三级及以上
|
||||
return {
|
||||
'id': node['id'],
|
||||
'thrTitle': node['title'],
|
||||
'value': await get_home_page_product({'menu_id': node['id']}) # 三级菜单没有子菜单,value为空列表
|
||||
}
|
||||
|
||||
# 构建最终的树形结构
|
||||
final_result = []
|
||||
for root_node in result:
|
||||
final_result.append(await build_hierarchy(root_node))
|
||||
|
||||
return final_result
|
||||
|
||||
ret = await home_page_product_menu_search(params_kw)
|
||||
return ret
|
||||
40
b/product/home_page_product_menu_update.dspy
Normal file
40
b/product/home_page_product_menu_update.dspy
Normal file
@ -0,0 +1,40 @@
|
||||
async def home_page_product_menu_update(ns={}):
|
||||
"""
|
||||
更新菜单信息
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'menu id is required'
|
||||
}
|
||||
|
||||
# 构建更新字段,只更新传入的字段
|
||||
ns_dic = {'id': ns.get('id')}
|
||||
if ns.get('title'):
|
||||
ns_dic['title'] = ns.get('title')
|
||||
if ns.get('parent_id'):
|
||||
ns_dic['parent_id'] = ns.get('parent_id')
|
||||
if ns.get('menu_level'):
|
||||
ns_dic['menu_level'] = ns.get('menu_level')
|
||||
if ns.get('sort_order'):
|
||||
ns_dic['sort_order'] = int(ns.get('sort_order'))
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_product_menu', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'update menu success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'update menu failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_menu_update(params_kw)
|
||||
return ret
|
||||
86
b/product/home_page_product_search.dspy
Normal file
86
b/product/home_page_product_search.dspy
Normal file
@ -0,0 +1,86 @@
|
||||
async def home_page_product_search(ns={}):
|
||||
"""
|
||||
查找产品信息,支持按菜单ID、产品名称等筛选
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# 分页参数
|
||||
current_page = int(ns.get('current_page', 1))
|
||||
page_size = int(ns.get('page_size', 10))
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
# 构建查询条件
|
||||
conditions = ["hp.del_flg = '0'"]
|
||||
|
||||
if ns.get('menu_id'):
|
||||
conditions.append(f"hp.menu_id = '{ns.get('menu_id')}'")
|
||||
if ns.get('name'):
|
||||
conditions.append(f"hp.name LIKE '%{ns.get('name')}%'")
|
||||
if ns.get('product_group'):
|
||||
conditions.append(f"hp.product_group = '{ns.get('product_group')}'")
|
||||
if ns.get('source'):
|
||||
conditions.append(f"hp.source = '{ns.get('source')}'")
|
||||
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 查询总数
|
||||
count_sql = f"""
|
||||
SELECT COUNT(*) AS total_count
|
||||
FROM home_page_product_info hp
|
||||
WHERE {where_clause}
|
||||
"""
|
||||
total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
|
||||
# 查询产品列表
|
||||
find_sql = f"""
|
||||
SELECT hp.*, hm.title as menu_title, hm.menu_level
|
||||
FROM home_page_product_info hp
|
||||
LEFT JOIN home_page_product_menu hm ON hp.menu_id = hm.id
|
||||
WHERE {where_clause}
|
||||
ORDER BY hp.sort_order ASC, hp.create_at DESC
|
||||
LIMIT {page_size} OFFSET {offset}
|
||||
"""
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
|
||||
# 格式化返回数据,匹配home_page_menu.json的数据格式
|
||||
product_list = []
|
||||
for product in result:
|
||||
product_data = {
|
||||
'id': product['id'],
|
||||
'name': product['name'],
|
||||
'description': product['description'],
|
||||
'label': product['label'],
|
||||
'product_group': product['product_group'], # 注意字段名映射
|
||||
'url': product['url'],
|
||||
'list_url': product['list_url'], # 注意字段名映射
|
||||
'iconUrl': product['icon_url'], # 注意字段名映射
|
||||
'icon_url': product['source'],
|
||||
'menu_id': product['menu_id'],
|
||||
'menu_title': product['menu_title'],
|
||||
'menu_level': product['menu_level']
|
||||
}
|
||||
product_list.append(product_data)
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search product success',
|
||||
'data': {
|
||||
'product_list': product_list
|
||||
},
|
||||
'pagination': {
|
||||
'total': total_count,
|
||||
'page_size': page_size,
|
||||
'current_page': current_page,
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'search product failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_search(params_kw)
|
||||
return ret
|
||||
52
b/product/home_page_product_update.dspy
Normal file
52
b/product/home_page_product_update.dspy
Normal file
@ -0,0 +1,52 @@
|
||||
async def home_page_product_update(ns={}):
|
||||
"""
|
||||
更新产品信息
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'product id is required'
|
||||
}
|
||||
|
||||
# 构建更新字段,只更新传入的字段
|
||||
ns_dic = {'id': ns.get('id')}
|
||||
if ns.get('name'):
|
||||
ns_dic['name'] = ns.get('name')
|
||||
if ns.get('description'):
|
||||
ns_dic['description'] = ns.get('description')
|
||||
if ns.get('label'):
|
||||
ns_dic['label'] = ns.get('label')
|
||||
if ns.get('product_group'):
|
||||
ns_dic['product_group'] = ns.get('product_group')
|
||||
if ns.get('url'):
|
||||
ns_dic['url'] = ns.get('url')
|
||||
if ns.get('list_url'):
|
||||
ns_dic['list_url'] = ns.get('list_url')
|
||||
if ns.get('icon_url'):
|
||||
ns_dic['icon_url'] = ns.get('icon_url')
|
||||
if ns.get('source'):
|
||||
ns_dic['source'] = ns.get('source')
|
||||
if ns.get('sort_order'):
|
||||
ns_dic['sort_order'] = ns.get('sort_order')
|
||||
if ns.get('menu_id'):
|
||||
ns_dic['menu_id'] = ns.get('menu_id')
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('home_page_product_info', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'update product success'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'update product failed, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await home_page_product_update(params_kw)
|
||||
return ret
|
||||
49
b/product/homepage_category_tree_add.dspy
Normal file
49
b/product/homepage_category_tree_add.dspy
Normal file
@ -0,0 +1,49 @@
|
||||
async def homepage_category_tree_add(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递路由链接'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'domain_name': domain_name,
|
||||
'orgid': orgid,
|
||||
'parentid': ns.get('parentid', None),
|
||||
'priority': ns.get('priority', 99),
|
||||
'name': ns.get('name', ''),
|
||||
'icon': ns.get('icon', None),
|
||||
'source': ns.get('source', None),
|
||||
'listurl': ns.get('listurl', None),
|
||||
}
|
||||
try:
|
||||
await sor.C('homepage_category_tree', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await homepage_category_tree_add(params_kw)
|
||||
return ret
|
||||
16
b/product/homepage_category_tree_delete.dspy
Normal file
16
b/product/homepage_category_tree_delete.dspy
Normal file
@ -0,0 +1,16 @@
|
||||
async def homepage_category_tree_delete(ns={}):
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递分类ID'
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('homepage_category_tree', {'id': ns.get('id'), 'del_flg': '1'})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category deleted successfully'
|
||||
}
|
||||
|
||||
ret = await homepage_category_tree_delete(params_kw)
|
||||
return ret
|
||||
35
b/product/homepage_category_tree_search.dspy
Normal file
35
b/product/homepage_category_tree_search.dspy
Normal file
@ -0,0 +1,35 @@
|
||||
async def homepage_category_tree_search(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递路由链接'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
ns_dic = {
|
||||
'domain_name': domain_name,
|
||||
'del_flg': '0'
|
||||
}
|
||||
try:
|
||||
category_list = await sor.R('homepage_category_tree', ns_dic)
|
||||
# 对icon字段增加前缀
|
||||
for category in category_list:
|
||||
if category.get('iconurl') and ('http' not in category['iconurl']):
|
||||
category['iconurl'] = 'https://' + domain_name + category['iconurl']
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category created successfully',
|
||||
'data': category_list
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await homepage_category_tree_search(params_kw)
|
||||
return ret
|
||||
43
b/product/homepage_category_tree_update.dspy
Normal file
43
b/product/homepage_category_tree_update.dspy
Normal file
@ -0,0 +1,43 @@
|
||||
async def homepage_category_tree_update(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递路由链接'
|
||||
}
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递分类ID'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
ns.pop('userid', None)
|
||||
try:
|
||||
await sor.U('homepage_category_tree', ns)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category updated successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to update product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await homepage_category_tree_update(params_kw)
|
||||
return ret
|
||||
36
b/product/homepage_product_category.dspy
Normal file
36
b/product/homepage_product_category.dspy
Normal file
@ -0,0 +1,36 @@
|
||||
async def homepage_product_category(ns={}):
|
||||
if not ns.get('publish_type'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递产品类型'
|
||||
}
|
||||
publish_type = ns.get('publish_type')
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 读取user_publish_product产品
|
||||
user_publish_product_sql = """SELECT DISTINCT(product_category) FROM user_publish_product WHERE domain_name = '%s' AND first_page = '1' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % (domain_name, publish_type)
|
||||
user_publish_product_result = await sor.sqlExe(user_publish_product_sql, {})
|
||||
if not user_publish_product_result:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的产品'
|
||||
}
|
||||
user_publish_product_ids = [item['product_category'].split(",")[0] for item in user_publish_product_result]
|
||||
|
||||
# 读取user_publish_product_category产品类别
|
||||
user_publish_product_category_sql = """SELECT * FROM user_publish_product_category WHERE domain_name = '%s' AND del_flg = '0' ORDER BY priority ASC;""" % domain_name
|
||||
user_publish_product_category_result = await sor.sqlExe(user_publish_product_category_sql, {})
|
||||
result = [item for item in user_publish_product_category_result if str(item['id']) in user_publish_product_ids]
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'success',
|
||||
'data': result
|
||||
}
|
||||
|
||||
ret = await homepage_product_category(params_kw)
|
||||
return ret
|
||||
48
b/product/product_category_add.dspy
Normal file
48
b/product/product_category_add.dspy
Normal file
@ -0,0 +1,48 @@
|
||||
async def product_category_add(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递路由链接'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'domain_name': domain_name,
|
||||
'product_category': ns.get('product_category'),
|
||||
'parentid': ns.get('parentid') if ns.get('parentid') else None,
|
||||
'priority': ns['priority'] if ns.get('priority') else 99,
|
||||
'permission': ns.get('permission') if ns.get('permission') else '1',
|
||||
'cart_flag': ns.get('cart_flag') if ns.get('cart_flag') else None
|
||||
}
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
ns_dic['orgid'] = orgid
|
||||
try:
|
||||
await sor.C('user_publish_product_category', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await product_category_add(params_kw)
|
||||
return ret
|
||||
18
b/product/product_category_delete.dspy
Normal file
18
b/product/product_category_delete.dspy
Normal file
@ -0,0 +1,18 @@
|
||||
async def product_category_delete(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """update user_publish_product_category set del_flg = '1' where id = '%s';""" % ns.get('id')
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category deleted successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to delete product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await product_category_delete(params_kw)
|
||||
return ret
|
||||
88
b/product/product_category_search.dspy
Normal file
88
b/product/product_category_search.dspy
Normal file
@ -0,0 +1,88 @@
|
||||
async def build_tree(parent_id=None, all_cats=None):
|
||||
return [{
|
||||
"id": cat['id'],
|
||||
"name": cat['product_category'],
|
||||
"cart_flag": cat['cart_flag'],
|
||||
"children": await build_tree(cat['id'], all_cats)
|
||||
} for cat in all_cats if cat['parentid'] == parent_id]
|
||||
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
return role
|
||||
|
||||
async def product_category_search(ns={}):
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
to_page = ns.get('to_page')
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 首页不登录 通过域名筛选
|
||||
if to_page == 'show':
|
||||
if ns.get('first_level_id'):
|
||||
find_sql = """SELECT * FROM user_publish_product_category WHERE domain_name = '%s' AND del_flg = '0' AND parentid = '%s' ORDER BY priority;""" % (domain_name, ns.get('first_level_id'))
|
||||
else:
|
||||
find_sql = """SELECT * FROM user_publish_product_category WHERE domain_name = '%s' AND del_flg = '0' AND parentid is NULL ORDER BY priority;""" % domain_name
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product categories retrieved successfully',
|
||||
'data': result
|
||||
}
|
||||
|
||||
# 发布弹窗中的产品种类通过用户筛选 普通用户/管理人员
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
try:
|
||||
if user_role == '客户' or user_role == '管理员':
|
||||
find_sql = """SELECT * FROM user_publish_product_category WHERE domain_name = '%s' AND permission = '1' AND del_flg = '0' ORDER BY priority;""" % domain_name
|
||||
else:
|
||||
find_sql = """SELECT * FROM user_publish_product_category WHERE domain_name = '%s' AND del_flg = '0' ORDER BY priority;""" % domain_name
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
# res = await build_tree(parent_id=None, all_cats=result)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product categories retrieved successfully',
|
||||
'data': result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve product categories, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await product_category_search(params_kw)
|
||||
return ret
|
||||
18
b/product/product_category_update.dspy
Normal file
18
b/product/product_category_update.dspy
Normal file
@ -0,0 +1,18 @@
|
||||
async def product_category_update(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """update user_publish_product_category set product_category = '%s' where id = '%s';""" % (ns.get('product_category'), ns.get('id'))
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'product category updated successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to update product category, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await product_category_update(params_kw)
|
||||
return ret
|
||||
@ -8,7 +8,7 @@ async def product_quick_navigation(ns={}):
|
||||
"productgroup": "计算",
|
||||
"url": "https://console.vcp.baidu.com/bcc/#/bcc/instance/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bcc/#/bcc/instance/list",
|
||||
"iconUrl": "https://www.kaiyuancloud.cn/idfile?path=/svg_data/baidu_GPU.svg"
|
||||
"iconUrl": "https://www.opencomputing.cn/idfile?path=/svg_data/baidu_GPU.svg"
|
||||
},
|
||||
{
|
||||
"id": "LwhOnnk9BWaaDZ7QP0t6Y",
|
||||
@ -18,7 +18,7 @@ async def product_quick_navigation(ns={}):
|
||||
"productgroup": "计算",
|
||||
"url": "https://console.vcp.baidu.com/bcc/#/bcc/instance/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bcc/#/bcc/instance/list",
|
||||
"iconUrl": "https://www.kaiyuancloud.cn/idfile?path=/svg_data/baidu_BCC.svg"
|
||||
"iconUrl": "https://www.opencomputing.cn/idfile?path=/svg_data/baidu_BCC.svg"
|
||||
},
|
||||
{
|
||||
"id": "tGgs5SlaBH9t_TZVI60ZP",
|
||||
@ -28,7 +28,7 @@ async def product_quick_navigation(ns={}):
|
||||
"productgroup": "计算",
|
||||
"url": "https://console.vcp.baidu.com/bcc/#/dcc/host/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/bcc/#/dcc/host/list",
|
||||
"iconUrl": "https://www.kaiyuancloud.cn/idfile?path=/svg_data/baidu_DCC.svg"
|
||||
"iconUrl": "https://www.opencomputing.cn/idfile?path=/svg_data/baidu_DCC.svg"
|
||||
},
|
||||
{
|
||||
"id": "xLT6VfQwdBWzpfMXC8qFM",
|
||||
@ -38,7 +38,7 @@ async def product_quick_navigation(ns={}):
|
||||
"productgroup": "计算",
|
||||
"url": "https://console.vcp.baidu.com/ls/#/ls/instance/create",
|
||||
"listUrl": "https://console.vcp.baidu.com/ls/#/ls/instance/list",
|
||||
"iconUrl": "https://www.kaiyuancloud.cn/idfile?path=/svg_data/baidu_LS.svg"
|
||||
"iconUrl": "https://www.opencomputing.cn/idfile?path=/svg_data/baidu_LS.svg"
|
||||
}
|
||||
]
|
||||
return {
|
||||
|
||||
110
b/product/publish_product_add.dspy
Normal file
110
b/product/publish_product_add.dspy
Normal file
@ -0,0 +1,110 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
return role
|
||||
|
||||
async def publish_product_add(ns={}):
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
product_category = ns.get('product_category')
|
||||
company_type = ns.get('company_type')
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"publish_type": ns.get("publish_type"),
|
||||
"cart_flag": ns.get("cart_flag"),
|
||||
"orgid": orgid,
|
||||
"img": ns.get('img') if ns.get('img') else None,
|
||||
"domain_name": domain_name,
|
||||
"product_name": ns.get("product_name"),
|
||||
"product_category": product_category,
|
||||
"company_name": ns.get("company_name"),
|
||||
"company_type": json.dumps(company_type) if isinstance(company_type, list) else company_type,
|
||||
"contact_person": ns.get("contact_person"),
|
||||
"job_title": ns.get("job_title"),
|
||||
"phone_number": ns.get("phone_number"),
|
||||
"email": ns.get("email"),
|
||||
"cpu": ns.get("cpu"),
|
||||
"memory": ns.get("memory"),
|
||||
"gpu": ns.get("gpu"),
|
||||
"sys_disk": ns.get("sys_disk"),
|
||||
"data_disk": ns.get("data_disk"),
|
||||
"net_card": ns.get("net_card"),
|
||||
"price": ns.get("price"),
|
||||
"unit": ns.get("unit"),
|
||||
"discount": ns.get("discount"),
|
||||
"service_charge": ns.get("service_charge"),
|
||||
"short_term": ns.get("short_term"),
|
||||
"priority": ns.get("priority") if ns.get("priority") else 1,
|
||||
"status": ns.get("status") if ns.get("status") else '0',
|
||||
"title": ns.get("title"),
|
||||
"label": ns.get("label"),
|
||||
"first_page": ns.get("first_page") if ns.get("first_page") else '0',
|
||||
"requirement_summary": ns.get("requirement_summary"),
|
||||
"related_parameters": ns.get("related_parameters"),
|
||||
"application_scenario": ns.get("application_scenario"),
|
||||
"audit_status": ns.get('audit_status', 'pending'),
|
||||
}
|
||||
if ns.get('discount') == '0':
|
||||
ns['discount'] = None
|
||||
ns_dic['discount'] = None
|
||||
|
||||
if ns.get('price') and ns.get('discount'):
|
||||
ns_dic['discount_price'] = float(ns.get('price')) * float(ns['discount']) / 10
|
||||
else:
|
||||
ns_dic['discount_price'] = ns['price']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
# 非客户角色不需要审批
|
||||
if user_role != '客户' and user_role != '管理员':
|
||||
ns['status'] = '1'
|
||||
ns_dic['audit_status'] = 'approved'
|
||||
ns_dic['listing_status'] = 'listing'
|
||||
ns_dic['first_page'] = '1'
|
||||
try:
|
||||
await sor.C('user_publish_product', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'publish product created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to publish product, %s' % str(e)
|
||||
}
|
||||
|
||||
|
||||
ret = await publish_product_add(params_kw)
|
||||
return ret
|
||||
309
b/product/publish_product_search.dspy
Normal file
309
b/product/publish_product_search.dspy
Normal file
@ -0,0 +1,309 @@
|
||||
async def publish_product_to_excel(ns={}):
|
||||
if not ns.get('ids') and (not ns.get('result_from_search')):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递产品ID'
|
||||
}
|
||||
result = []
|
||||
if ns.get('ids'):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
ids = json.loads(ns.get('ids')) if isinstance(ns.get('ids'), str) else ns.get('ids')
|
||||
# 根据ids查询user_publish_product表
|
||||
find_sql = """SELECT * FROM user_publish_product WHERE id IN (%s) AND del_flg = '0';""" % ','.join(["'%s'" % id for id in ids])
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
if not result:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的产品'
|
||||
}
|
||||
if ns.get('result_from_search'):
|
||||
result = ns.get('result_from_search')
|
||||
|
||||
# 结果转换成 中文名称:值 的字典列表
|
||||
field_mapping = {
|
||||
# 'id': 'id',
|
||||
# 'publish_type': '类型',
|
||||
'img': '图片链接',
|
||||
# 'cart_flag': '是否支持显卡',
|
||||
# 'domain_name': '所属域名',
|
||||
# 'orgid': '所属机构',
|
||||
'product_name': '商品名称',
|
||||
# 'product_category': '所属类别',
|
||||
'company_name': '企业名称',
|
||||
# 'company_type': '公司类别',
|
||||
'contact_person': '联系人',
|
||||
'job_title': '职务',
|
||||
'phone_number': '手机号码',
|
||||
'email': '邮箱',
|
||||
'cpu': 'cpu',
|
||||
'memory': '内存',
|
||||
'gpu': 'gpu',
|
||||
'sys_disk': '系统盘',
|
||||
'data_disk': '数据盘',
|
||||
'net_card': '网卡',
|
||||
'price': '价格',
|
||||
'unit': '价格单位',
|
||||
'discount': '价格折扣',
|
||||
'discount_price': '折扣后价格',
|
||||
'service_charge': '服务费',
|
||||
'short_term': '是否短租',
|
||||
# 'priority': '排序优先级',
|
||||
'status': '上架状态',
|
||||
# 'title': '主题',
|
||||
# 'label': '标签',
|
||||
# 'first_page': '是否推送到首页',
|
||||
# 'admin_push': '是否是运营人员提交',
|
||||
'requirement_summary': '需求概述',
|
||||
'related_parameters': '相关参数',
|
||||
'application_scenario': '应用场景',
|
||||
'audit_status': '审核状态',
|
||||
'listing_status': '上架状态',
|
||||
'reject_reason': '驳回原因',
|
||||
'update_time': '更新时间',
|
||||
'create_at': '创建时间',
|
||||
# 'publish_time': '发布日期',
|
||||
# 'del_flg': '删除标志'
|
||||
}
|
||||
# 转换字典键为中文
|
||||
for data_dic in result:
|
||||
# 如果有图片路径 则转换为完整的图片链接
|
||||
if data_dic.get('img') and data_dic['img'] != 'null':
|
||||
data_dic['img'] = 'https://' + data_dic['domain_name'] + '/idfile?path=' + data_dic['img']
|
||||
else:
|
||||
data_dic['img'] = None
|
||||
# 转换字典键为中文 对应的值要有映射
|
||||
# 拆分后:显式循环结构(便于后续处理)
|
||||
new_data_dic = {}
|
||||
for key, value in data_dic.items():
|
||||
if key == 'publish_type':
|
||||
# 显示类型映射
|
||||
if value == '1':
|
||||
value = '产品'
|
||||
elif value == '2':
|
||||
value = '需求'
|
||||
if key == 'audit_status':
|
||||
# 显示审核状态映射
|
||||
if value == 'pending':
|
||||
value = '待审'
|
||||
elif value == 'approved':
|
||||
value = '通过'
|
||||
elif value == 'rejected':
|
||||
value = '拒绝'
|
||||
if key == 'listing_status':
|
||||
# 显示上架状态映射
|
||||
if value == 'listing':
|
||||
value = '上架'
|
||||
elif value == 'delisting':
|
||||
value = '下架'
|
||||
if key == 'short_term':
|
||||
# 显示短租状态映射
|
||||
if value == '1':
|
||||
value = '是'
|
||||
elif value == '0':
|
||||
value = '否'
|
||||
# 获取中文映射键
|
||||
chinese_key = field_mapping.get(key)
|
||||
# 仅保留有映射关系的字段
|
||||
if chinese_key is not None:
|
||||
new_data_dic[chinese_key] = value
|
||||
data_dic.clear()
|
||||
data_dic.update(new_data_dic)
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'export to excel success',
|
||||
'data': result
|
||||
}
|
||||
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
|
||||
return role
|
||||
|
||||
async def publish_product_search(ns={}):
|
||||
"""
|
||||
普通客户查看
|
||||
运营查看自己提交内容
|
||||
运营查看所有用户内容
|
||||
|
||||
运营: 待审 已审 上架
|
||||
客户: 已审 上架 驳回
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
offset = ns.get('offset')
|
||||
manager_self = ns.get('manager_self')
|
||||
to_excel = ns.get('to_excel')
|
||||
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'url_link is required'
|
||||
}
|
||||
if not ns.get('publish_type'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'publish_type is required'
|
||||
}
|
||||
|
||||
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
publish_type = ns.get('publish_type')
|
||||
page_size = int(ns['page_size']) if ns.get('page_size') else 8
|
||||
current_page_param = int(ns['current_page']) if ns.get('current_page') else 1
|
||||
current_page = (current_page_param - 1) * page_size
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
org_parentid_li = await sor.R('organization', {'id': orgid})
|
||||
org_parentid = org_parentid_li[0]['parentid']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
try:
|
||||
# 非客户角色
|
||||
if user_role != '客户' and user_role != '管理员':
|
||||
ns['del_flg'] = '0'
|
||||
|
||||
# 业主机构角色并且是只查看业主机构自己 manager_self==single
|
||||
if orgid == 'mIWUHBeeDM8mwAFPIQ8pS' and manager_self == 'single':
|
||||
count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid IS NULL AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % publish_type
|
||||
|
||||
find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid IS NULL AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (publish_type, page_size, current_page)
|
||||
# 业主机构角色并且是查看所有(不包括业主机构自己) manager_self!=single (WHERE (org.id = '%s' or org.parentid = '%s')
|
||||
elif orgid == 'mIWUHBeeDM8mwAFPIQ8pS':
|
||||
count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type)
|
||||
|
||||
find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page)
|
||||
# 其他机构非用户角色 只查看自己
|
||||
elif manager_self == 'single':
|
||||
count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.id = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type)
|
||||
|
||||
find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.id = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page)
|
||||
# 其他机构非用户角色查看所有客户 (WHERE (org.id = '%s' or org.parentid = '%s') AND upr.del_flg = '0')
|
||||
else:
|
||||
count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type)
|
||||
|
||||
find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE (org.parentid = '%s' OR org.id = '%s') AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, orgid, publish_type, page_size, current_page)
|
||||
# 客户角色
|
||||
else:
|
||||
ns['del_flg'] = '0'
|
||||
ns['orgid'] = user_list[0]['id']
|
||||
count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr WHERE upr.orgid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page)
|
||||
find_sql = """SELECT upr.* FROM user_publish_product AS upr WHERE upr.orgid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page)
|
||||
|
||||
# 截取count_sql和find_sql中的 WHERE, 向WHERE后追加新的筛选条件
|
||||
# 如果审核状态是pending,approved, 查询待审和已审的数据
|
||||
if ns.get('audit_status') == 'pending,approved':
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'pending' OR upr.audit_status = 'approved') AND " + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'pending' OR upr.audit_status = 'approved') AND " + find_sql.split('WHERE')[1]
|
||||
elif ns.get('audit_status') == 'approved,rejected':
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'rejected' OR upr.audit_status = 'approved') AND " + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'rejected' OR upr.audit_status = 'approved') AND " + find_sql.split('WHERE')[1]
|
||||
|
||||
elif ns.get('audit_status'):
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.audit_status = '%s' AND " % ns.get('audit_status') + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.audit_status = '%s' AND " % ns.get('audit_status') + find_sql.split('WHERE')[1]
|
||||
|
||||
if ns.get('listing_status'):
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.listing_status = '%s' AND " % ns.get('listing_status') + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.listing_status = '%s' AND " % ns.get('listing_status') + find_sql.split('WHERE')[1]
|
||||
|
||||
# 添加start_date和end_date筛选
|
||||
if ns.get('start_date') and ns.get('end_date'):
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "(upr.create_at BETWEEN '%s' AND '%s') AND " % (ns.get('start_date'), ns.get('end_date')) + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(upr.create_at BETWEEN '%s' AND '%s') AND " % (ns.get('start_date'), ns.get('end_date')) + find_sql.split('WHERE')[1]
|
||||
|
||||
# 添加keyword模糊查询 只筛选产品名称
|
||||
if ns.get('keyword'):
|
||||
count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.product_name LIKE '%%%%%s%%%%' AND " % ns.get('keyword') + count_sql.split('WHERE')[1]
|
||||
find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.product_name LIKE '%%%%%s%%%%' AND " % ns.get('keyword') + find_sql.split('WHERE')[1]
|
||||
print(count_sql)
|
||||
total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
|
||||
# 处理图片
|
||||
for res in result:
|
||||
if res.get('img') and res['img'] != 'null':
|
||||
res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img']
|
||||
else:
|
||||
res['img'] = None
|
||||
|
||||
# 读取产品类别表 轮询匹配result中的所有类别
|
||||
product_category_list = await sor.R('user_publish_product_category', {'del_flg': '0'})
|
||||
for res in result:
|
||||
for product_category in product_category_list:
|
||||
if product_category['id'] == res['product_category'].split(",")[0]:
|
||||
res['category_name'] = product_category['product_category']
|
||||
break
|
||||
|
||||
if to_excel == '1':
|
||||
res = await publish_product_to_excel({'result_from_search': result})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search to excel success',
|
||||
'data': res['data']
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirements retrieved successfully',
|
||||
'data': {
|
||||
"id": uuid(),
|
||||
"total_count": total_count,
|
||||
"page_size": page_size,
|
||||
"current_page": current_page_param,
|
||||
"product_list": result
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve requirements, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await publish_product_search(params_kw)
|
||||
return ret
|
||||
140
b/product/publish_product_search_detail.dspy
Normal file
140
b/product/publish_product_search_detail.dspy
Normal file
@ -0,0 +1,140 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
|
||||
return role
|
||||
|
||||
async def user_browse_history_add(ns={}):
|
||||
# 必要参数校验
|
||||
if not ns.get('userid') or not ns.get('productid'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'userid and productid are required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 根据timestamp时间字段:browse_time去重 查找10个小时内是否存在
|
||||
# browse_time = datetime.datetime.now() - datetime.timedelta(hours=10)
|
||||
|
||||
# 检查产品的publish_type
|
||||
product_sql = """
|
||||
SELECT publish_type FROM user_publish_product
|
||||
WHERE id = '%s' AND del_flg = '0';
|
||||
""" % ns.get('productid')
|
||||
product_result = await sor.sqlExe(product_sql, {})
|
||||
if product_result:
|
||||
publish_type = product_result[0]['publish_type']
|
||||
else:
|
||||
publish_type = 99
|
||||
|
||||
check_sql = """
|
||||
SELECT * FROM user_browse_history
|
||||
WHERE userid = '%s' AND productid = '%s' AND del_flg = '0';
|
||||
""" % (ns.get('userid'), ns.get('productid'))
|
||||
check_result = await sor.sqlExe(check_sql, {})
|
||||
if check_result:
|
||||
# 数据库更新browse_time字段
|
||||
update_sql = """
|
||||
UPDATE user_browse_history
|
||||
SET browse_time = '%s'
|
||||
WHERE id = '%s';
|
||||
""" % (datetime.datetime.now(), check_result[0]['id'])
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history recorded successfully',
|
||||
'data': {'record_id': check_result[0]['id']}
|
||||
}
|
||||
|
||||
# 生成记录ID
|
||||
record_id = uuid()
|
||||
insert_sql = """
|
||||
INSERT INTO user_browse_history (
|
||||
id, userid, productid, ip_address, user_agent, del_flg, tag, publish_type
|
||||
) VALUES ('%s', '%s', '%s', '%s', '%s', '0', '%s', '%s');
|
||||
""" % (record_id, ns.get('userid'), ns.get('productid'),
|
||||
ns.get('ip_address', ''), ns.get('user_agent', ''), ns.get('tag', ''), publish_type)
|
||||
await sor.sqlExe(insert_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history recorded successfully',
|
||||
'data': {'record_id': record_id}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to record browse history, %s' % str(e)
|
||||
}
|
||||
|
||||
async def publish_product_search_detail(ns={}):
|
||||
"""
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
user_role = None
|
||||
orgid = None
|
||||
# 区分运营和普通客户
|
||||
if userid:
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
orgid = user_list[0]['orgid']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
|
||||
# 如果用户角色是运营并且from='b' product_list中的phone_number和email做加星号处理
|
||||
product_list = await sor.R('user_publish_product', {'id': ns.get('id'), 'del_flg': '0'})
|
||||
product_category = await sor.R('user_publish_product_category', {'id': product_list[0]['product_category'].split(',')[0]})
|
||||
product_list[0]['product_category'] = product_category[0]['product_category']
|
||||
if user_role == '运营' and ns.get('from') == 'b':
|
||||
pass
|
||||
elif orgid == product_list[0]['orgid']:
|
||||
pass
|
||||
else:
|
||||
for product in product_list:
|
||||
if product.get('phone_number'):
|
||||
product['phone_number'] = product['phone_number'][:3] + '****' + product['phone_number'][7:]
|
||||
else:
|
||||
product['phone_number'] = '198****8601'
|
||||
if product.get('email'):
|
||||
product['email'] = product['email'][:2] + '****' + product['email'][6:]
|
||||
else:
|
||||
product['email'] = None
|
||||
|
||||
# 保存浏览记录
|
||||
if userid:
|
||||
res = await user_browse_history_add({'userid': userid, 'productid': ns.get('id'), 'tag': 'upp', 'publish_type': product_list[0]['publish_type']})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Product retrieved successfully',
|
||||
'data': product_list[0]
|
||||
}
|
||||
|
||||
ret = await publish_product_search_detail(params_kw)
|
||||
return ret
|
||||
143
b/product/publish_product_search_first_page.dspy
Normal file
143
b/product/publish_product_search_first_page.dspy
Normal file
@ -0,0 +1,143 @@
|
||||
async def favorite_check(ns={}):
|
||||
"""
|
||||
检查用户是否已收藏某个商品/需求
|
||||
:param ns: 包含userid, productid, favorite_type参数
|
||||
:return: 检查结果
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if not ns.get('userid') or not ns.get('productid'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '缺少必要参数'
|
||||
}
|
||||
|
||||
check_sql = """
|
||||
SELECT id FROM user_favorite
|
||||
WHERE userid = '%s' AND productid = '%s' AND del_flg = '0'
|
||||
""" % (ns.get('userid'), ns.get('productid'))
|
||||
|
||||
check_result = await sor.sqlExe(check_sql, {})
|
||||
if check_result:
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '查询成功',
|
||||
'data': {
|
||||
'is_favorite': True,
|
||||
'id': check_result[0]['id']
|
||||
}
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'status': False
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '查询失败, %s' % str(e)
|
||||
}
|
||||
|
||||
async def publish_product_search_first_page(ns={}):
|
||||
"""
|
||||
普通客户查看
|
||||
运营查看自己提交内容
|
||||
运营查看所有用户内容
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
ns['userid'] = userid
|
||||
publish_type = ns.get('publish_type')
|
||||
page_size = int(ns['page_size']) if ns.get('page_size') else 8
|
||||
current_page_param = int(ns['current_page']) if ns.get('current_page') else 1
|
||||
current_page = (current_page_param - 1) * page_size
|
||||
to_page = ns.get('to_page') if ns.get('to_page') else 'first_page'
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
company_type = ns.get('company_type')
|
||||
product_category = ns.get('product_category')
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
ns['del_flg'] = '0'
|
||||
# 如果是首页并且有产品分类
|
||||
if to_page == 'first_page' and product_category:
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE domain_name = '%s' AND first_page = '1' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND publish_type = '%s' AND product_category LIKE '%%%%%s%%%%';""" % (domain_name, publish_type, product_category)
|
||||
find_sql = """SELECT upp.* FROM user_publish_product AS upp WHERE upp.domain_name = '%s' AND upp.first_page = '1' AND upp.audit_status = 'approved' AND listing_status = 'listing' AND upp.product_category LIKE '%%%%%s%%%%' AND upp.del_flg = '0' AND upp.publish_type = '%s' ORDER BY upp.priority ASC, upp.create_at DESC LIMIT %s OFFSET %s;""" % (domain_name, product_category, publish_type, page_size, current_page)
|
||||
elif to_page == 'first_page':
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE domain_name = '%s' AND first_page = '1' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % (domain_name, publish_type)
|
||||
find_sql = """SELECT upp.* FROM user_publish_product AS upp INNER JOIN user_publish_product_category AS uppc ON upp.product_category LIKE uppc.id WHERE upp.domain_name = '%s' AND upp.first_page = '1' AND upp.audit_status = 'approved' AND upp.del_flg = '0' AND upp.publish_type = '%s' ORDER BY uppc.priority ASC, upp.create_at DESC LIMIT %s OFFSET %s;""" % (domain_name, publish_type, page_size, current_page)
|
||||
elif to_page == 'square' and product_category:
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE domain_name = '%s' AND product_category LIKE """ % domain_name + """'%%""" + product_category + """%%'""" + """ AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % publish_type
|
||||
find_sql = """SELECT * FROM user_publish_product WHERE domain_name = '%s' AND product_category LIKE """ % domain_name + """'%%""" + product_category + """%%'""" + """ AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC LIMIT %s OFFSET %s;""" % (publish_type, page_size, current_page)
|
||||
elif to_page == 'square':
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE domain_name = '%s' AND audit_status = 'approved' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % (domain_name, publish_type)
|
||||
find_sql = """SELECT * FROM user_publish_product WHERE domain_name = '%s' AND audit_status = 'approved' AND del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC LIMIT %s OFFSET %s;""" % (domain_name, publish_type, page_size, current_page)
|
||||
else:
|
||||
count_sql = ''
|
||||
find_sql = ''
|
||||
|
||||
total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
category_all = await sor.R('user_publish_product_category', {})
|
||||
product_dic = {}
|
||||
for res in result:
|
||||
# 公司类别筛选
|
||||
if company_type:
|
||||
list1 = [item.strip() for item in company_type.split(',')]
|
||||
list2 = [item.strip() for item in res['company_type'].split(',')]
|
||||
if not bool(set(list1) & set(list2)):
|
||||
continue
|
||||
if res.get('img') and res['img'] != 'null':
|
||||
res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img']
|
||||
else:
|
||||
res['img'] = None
|
||||
|
||||
# 是否收藏关注
|
||||
check_status_li = await favorite_check({'userid': ns.get('userid'), 'productid': res.get('id')})
|
||||
if check_status_li['status']:
|
||||
res['favorite'] = '1'
|
||||
else:
|
||||
res['favorite'] = '0'
|
||||
|
||||
# 电话和邮箱模糊化处理
|
||||
if res.get('phone_number'):
|
||||
res['phone_number'] = res['phone_number'][:3] + '****' + res['phone_number'][7:]
|
||||
else:
|
||||
res['phone_number'] = '198****8601'
|
||||
|
||||
if res.get('email'):
|
||||
res['email'] = res['email'][:2] + '****' + res['email'][6:]
|
||||
else:
|
||||
res['email'] = 'kawa@****.com'
|
||||
|
||||
category_id = res['product_category'].split(',')[0]
|
||||
category_name_li = [item['product_category'] for item in category_all if item['id'] == category_id]
|
||||
category_name = category_name_li[0] if category_name_li else '其他'
|
||||
if product_dic.get(category_name):
|
||||
product_dic[category_name].append(res)
|
||||
else:
|
||||
product_dic[category_name] = [res]
|
||||
product_list = []
|
||||
for key, value in product_dic.items():
|
||||
product_list.append({'id': uuid(), 'name': key, 'total_count': total_count, 'page_size': page_size, 'current_page': current_page_param, 'product_list': value})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirements retrieved successfully',
|
||||
'data': product_list
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve requirements, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await publish_product_search_first_page(params_kw)
|
||||
return ret
|
||||
120
b/product/publish_product_to_excel.dspy
Normal file
120
b/product/publish_product_to_excel.dspy
Normal file
@ -0,0 +1,120 @@
|
||||
async def publish_product_to_excel(ns={}):
|
||||
if not ns.get('ids') and (not ns.get('result')):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递产品ID'
|
||||
}
|
||||
result = []
|
||||
if ns.get('ids'):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
ids = json.loads(ns.get('ids')) if isinstance(ns.get('ids'), str) else ns.get('ids')
|
||||
# 根据ids查询user_publish_product表
|
||||
find_sql = """SELECT * FROM user_publish_product WHERE id IN (%s) AND del_flg = '0';""" % ','.join(["'%s'" % id for id in ids])
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
if not result:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的产品'
|
||||
}
|
||||
if ns.get('result_from_search'):
|
||||
result = ns.get('result_from_search')
|
||||
|
||||
# 结果转换成 中文名称:值 的字典列表
|
||||
field_mapping = {
|
||||
# 'id': 'id',
|
||||
# 'publish_type': '类型',
|
||||
'img': '图片链接',
|
||||
# 'cart_flag': '是否支持显卡',
|
||||
# 'domain_name': '所属域名',
|
||||
# 'orgid': '所属机构',
|
||||
'product_name': '商品名称',
|
||||
# 'product_category': '所属类别',
|
||||
'company_name': '企业名称',
|
||||
# 'company_type': '公司类别',
|
||||
'contact_person': '联系人',
|
||||
'job_title': '职务',
|
||||
'phone_number': '手机号码',
|
||||
'email': '邮箱',
|
||||
'cpu': 'cpu',
|
||||
'memory': '内存',
|
||||
'gpu': 'gpu',
|
||||
'sys_disk': '系统盘',
|
||||
'data_disk': '数据盘',
|
||||
'net_card': '网卡',
|
||||
'price': '价格',
|
||||
'unit': '价格单位',
|
||||
'discount': '价格折扣',
|
||||
'discount_price': '折扣后价格',
|
||||
'service_charge': '服务费',
|
||||
'short_term': '是否短租',
|
||||
# 'priority': '排序优先级',
|
||||
'status': '上架状态',
|
||||
# 'title': '主题',
|
||||
# 'label': '标签',
|
||||
# 'first_page': '是否推送到首页',
|
||||
# 'admin_push': '是否是运营人员提交',
|
||||
'requirement_summary': '需求概述',
|
||||
'related_parameters': '相关参数',
|
||||
'application_scenario': '应用场景',
|
||||
'audit_status': '审核状态',
|
||||
'listing_status': '上架状态',
|
||||
'reject_reason': '驳回原因',
|
||||
'update_time': '更新时间',
|
||||
'create_at': '创建时间',
|
||||
# 'publish_time': '发布日期',
|
||||
# 'del_flg': '删除标志'
|
||||
}
|
||||
# 转换字典键为中文
|
||||
for data_dic in result:
|
||||
# 如果有图片路径 则转换为完整的图片链接
|
||||
if data_dic.get('img') and data_dic['img'] != 'null':
|
||||
data_dic['img'] = 'https://' + data_dic['domain_name'] + '/idfile?path=' + data_dic['img']
|
||||
else:
|
||||
data_dic['img'] = None
|
||||
# 转换字典键为中文 对应的值要有映射
|
||||
# 拆分后:显式循环结构(便于后续处理)
|
||||
new_data_dic = {}
|
||||
for key, value in data_dic.items():
|
||||
if key == 'publish_type':
|
||||
# 显示类型映射
|
||||
if value == '1':
|
||||
value = '产品'
|
||||
elif value == '2':
|
||||
value = '需求'
|
||||
if key == 'audit_status':
|
||||
# 显示审核状态映射
|
||||
if value == 'pending':
|
||||
value = '待审'
|
||||
elif value == 'approved':
|
||||
value = '通过'
|
||||
elif value == 'rejected':
|
||||
value = '拒绝'
|
||||
if key == 'listing_status':
|
||||
# 显示上架状态映射
|
||||
if value == '1':
|
||||
value = '上架'
|
||||
elif value == '0':
|
||||
value = '下架'
|
||||
if key == 'short_term':
|
||||
# 显示短租状态映射
|
||||
if value == '1':
|
||||
value = '是'
|
||||
elif value == '0':
|
||||
value = '否'
|
||||
# 获取中文映射键
|
||||
chinese_key = field_mapping.get(key)
|
||||
# 仅保留有映射关系的字段
|
||||
if chinese_key is not None:
|
||||
new_data_dic[chinese_key] = value
|
||||
data_dic.clear()
|
||||
data_dic.update(new_data_dic)
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'export to excel success',
|
||||
'data': result
|
||||
}
|
||||
|
||||
ret = await publish_product_to_excel(params_kw)
|
||||
return ret
|
||||
143
b/product/publish_product_update.dspy
Normal file
143
b/product/publish_product_update.dspy
Normal file
@ -0,0 +1,143 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
|
||||
return role
|
||||
|
||||
async def publish_product_update(ns={}):
|
||||
"""
|
||||
运营审批
|
||||
运营编辑
|
||||
客户编辑
|
||||
运营发布
|
||||
"""
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
|
||||
# 处理图片 如果包含http就跳过
|
||||
if ns.get('img') and ns['img'].startswith('http'):
|
||||
ns.pop('img', None)
|
||||
|
||||
orgid = user_list[0]['orgid']
|
||||
ns.pop('userid', None)
|
||||
|
||||
ns_dic = ns
|
||||
if ns.get('discount') == '0':
|
||||
ns['discount'] = None
|
||||
ns_dic['discount'] = None
|
||||
|
||||
if ns.get('price') and ns.get('discount'):
|
||||
ns_dic['discount_price'] = float(ns.get('price')) * float(ns['discount']) / 10
|
||||
elif ns.get('price'):
|
||||
ns_dic['discount_price'] = ns['price']
|
||||
else:
|
||||
pass
|
||||
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
# 编辑状态
|
||||
# 非客户角色编辑客户的产品
|
||||
if user_role != '客户' and user_role != '管理员' and ns.get('orgid') != orgid:
|
||||
# 非客户角色审核客户的产品
|
||||
# 如果是待审状态 更新审核状态为通过 上架状态为上架 清空驳回原因
|
||||
if ns.get('audit_status') == 'approved':
|
||||
ns_dic['audit_status'] = 'approved'
|
||||
ns_dic['listing_status'] = 'listing'
|
||||
ns_dic['reject_reason'] = None
|
||||
# 如果是上架商品 更新publish_time为当前时间
|
||||
if ns.get('listing_status') == 'listing':
|
||||
ns_dic['publish_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
# 如果是下架商品 更新publish_time为None
|
||||
elif ns.get('listing_status') == 'delisting':
|
||||
ns_dic['publish_time'] = None
|
||||
# 如果是删除商品 更新publish_time为None
|
||||
elif ns.get('del_flg') == '1':
|
||||
ns_dic['publish_time'] = None
|
||||
else:
|
||||
ns_dic['publish_time'] = None
|
||||
|
||||
# 非客户角色编辑自己的产品 默认审批通过和发布成功
|
||||
elif user_role != '客户' and user_role != '管理员':
|
||||
# 运营删除自己的产品
|
||||
if ns.get('del_flg') == '1':
|
||||
pass
|
||||
else:
|
||||
ns['status'] = '1'
|
||||
ns_dic['audit_status'] = 'approved'
|
||||
# 运营下架自己的产品
|
||||
if not ns.get('listing_status') == 'delisting':
|
||||
ns_dic['listing_status'] = 'listing'
|
||||
ns_dic['first_page'] = '1'
|
||||
# 客户编辑以后 审核状态是: 待审 上架状态是:空
|
||||
else:
|
||||
# 客户要下架自己的产品
|
||||
if ns.get('listing_status') == 'delisting' or ns.get('listing_status') == 'listing':
|
||||
# 如果状态是审批中和未上架
|
||||
exists_status = await sor.R('user_publish_product', {'id': ns.get('id')})
|
||||
if exists_status[0]['audit_status'] == 'pending' and (not exists_status[0]['listing_status']):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '审批中的产品操作'
|
||||
}
|
||||
if ns.get('listing_status') == 'delisting':
|
||||
ns_dic['listing_status'] = 'delisting'
|
||||
ns_dic['publish_time'] = None
|
||||
|
||||
if ns.get('listing_status') == 'listing':
|
||||
if exists_status[0]['audit_status'] == 'approved':
|
||||
ns_dic['listing_status'] = 'listing'
|
||||
ns_dic['publish_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '审批未通过,不能上架'
|
||||
}
|
||||
|
||||
# 客户仅编辑不是下架产品
|
||||
else:
|
||||
ns_dic['audit_status'] = 'pending'
|
||||
ns_dic['listing_status'] = None
|
||||
ns_dic['publish_time'] = None
|
||||
try:
|
||||
await sor.U('user_publish_product', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'publish product created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to publish product, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await publish_product_update(params_kw)
|
||||
return ret
|
||||
72
b/product/requirement_add.dspy
Normal file
72
b/product/requirement_add.dspy
Normal file
@ -0,0 +1,72 @@
|
||||
async def requirement_add(ns={}):
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
product_category = ns.get('product_category')
|
||||
company_type = ns.get('company_type')
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"orgid": orgid,
|
||||
"domain_name": domain_name,
|
||||
"requirement_name": ns.get("requirement_name"),
|
||||
"product_category": product_category,
|
||||
"company_name": ns.get("company_name"),
|
||||
"company_type": json.dumps(company_type) if isinstance(company_type, list) else company_type,
|
||||
"contact_person": ns.get("contact_person"),
|
||||
"job_title": ns.get("job_title"),
|
||||
"phone_number": ns.get("phone_number"),
|
||||
"email": ns.get("email"),
|
||||
"cpu": ns.get("cpu"),
|
||||
"memory": ns.get("memory"),
|
||||
"gpu": ns.get("gpu"),
|
||||
"sys_disk": ns.get("sys_disk"),
|
||||
"data_disk": ns.get("data_disk"),
|
||||
"net_card": ns.get("net_card"),
|
||||
"price": ns.get("price"),
|
||||
"priority": ns.get("priority") if ns.get("priority") else 1,
|
||||
"status": ns.get("status") if ns.get("status") else '0',
|
||||
"title": ns.get("title"),
|
||||
"label": ns.get("label"),
|
||||
"first_page": ns.get("first_page") if ns.get("first_page") else '0',
|
||||
"requirement_summary": ns.get("requirement_summary"),
|
||||
"related_parameters": ns.get("related_parameters"),
|
||||
"application_scenario": ns.get("application_scenario"),
|
||||
"audit_status": ns.get('audit_status', 'pending'),
|
||||
}
|
||||
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
# 非客户角色不需要审批
|
||||
if user_role != '客户':
|
||||
ns['status'] = '1'
|
||||
ns_dic['audit_status'] = 'approved'
|
||||
ns_dic['first_page'] = '1'
|
||||
|
||||
try:
|
||||
await sor.C('user_publish_requirement', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirement created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create requirement, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await requirement_add(params_kw)
|
||||
return ret
|
||||
21
b/product/requirement_delete.dspy
Normal file
21
b/product/requirement_delete.dspy
Normal file
@ -0,0 +1,21 @@
|
||||
async def requirement_delete(ns={}):
|
||||
ns_dic = {
|
||||
'id': ns.get('id'),
|
||||
'del_flg': '1'
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('user_publish_requirement', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirement delete successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to delete requirement, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await requirement_delete(params_kw)
|
||||
return ret
|
||||
93
b/product/requirement_search.dspy
Normal file
93
b/product/requirement_search.dspy
Normal file
@ -0,0 +1,93 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
return role
|
||||
|
||||
async def requirement_search(ns={}):
|
||||
"""
|
||||
普通客户查看
|
||||
运营查看自己提交内容
|
||||
运营查看所有用户内容
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
offset = ns['offset']
|
||||
flag = ns.get('flag')
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 区分运营和普通客户
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到匹配的用户'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
org_parentid_li = await sor.R('organization', {'id': orgid})
|
||||
org_parentid = org_parentid_li[0]['parentid']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
try:
|
||||
# 非客户角色
|
||||
if user_role != '客户':
|
||||
ns['del_flg'] = '0'
|
||||
|
||||
# 业主机构角色并且是只查看业主机构自己 flag==single
|
||||
if orgid == 'mIWUHBeeDM8mwAFPIQ8pS' and flag == 'single':
|
||||
find_sql = """SELECT upr.* FROM user_publish_requirement AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.parentid IS NULL AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % offset
|
||||
# 业主机构角色并且是查看所有(包括业主机构自己) flag!=single
|
||||
elif orgid == 'mIWUHBeeDM8mwAFPIQ8pS':
|
||||
find_sql = """SELECT upr.* FROM user_publish_requirement AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.id = '%s' or org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, orgid, offset)
|
||||
# 其他机构非用户角色 只查看自己
|
||||
elif flag == 'single':
|
||||
find_sql = """SELECT upr.* FROM user_publish_requirement AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE org.id = '%s' AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, offset)
|
||||
# 其他机构非用户角色查看所有
|
||||
else:
|
||||
find_sql = """SELECT upr.* FROM user_publish_requirement AS upr LEFT JOIN organization AS org ON upr.orgid = org.id
|
||||
WHERE (org.id = '%s' or org.parentid = '%s') AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, orgid, offset)
|
||||
# 客户角色
|
||||
else:
|
||||
ns['del_flg'] = '0'
|
||||
ns['orgid'] = user_list[0]['id']
|
||||
find_sql = """SELECT * FROM user_publish_requirement WHERE orgid = '%s' AND del_flg = '0' ORDER BY create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, offset)
|
||||
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirements retrieved successfully',
|
||||
'data': result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve requirements, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await requirement_search(params_kw)
|
||||
return ret
|
||||
23
b/product/requirement_update.dspy
Normal file
23
b/product/requirement_update.dspy
Normal file
@ -0,0 +1,23 @@
|
||||
async def requirement_update(ns={}):
|
||||
product_category = ns.get('product_category')
|
||||
company_type = ns.get('company_type')
|
||||
if product_category:
|
||||
ns['product_category'] = json.dumps(product_category) if isinstance(product_category, list) else product_category
|
||||
if company_type:
|
||||
ns['company_type'] = json.dumps(company_type) if isinstance(company_type, list) else company_type
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('user_publish_requirement', ns)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Requirement updated successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to update requirement, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await requirement_update(params_kw)
|
||||
return ret
|
||||
@ -1,8 +1,53 @@
|
||||
async def search_user_inquiry(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递url_link'
|
||||
}
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
search_sql = """select * from product_inquiry order by create_at desc;"""
|
||||
search_sql = """select * from product_inquiry where domain_name = '%s' and del_flg = '0' order by update_time desc;""" % domain_name
|
||||
result = await sor.sqlExe(search_sql, {})
|
||||
if ns.get('to_excel') == '1':
|
||||
# 创建映射字段 导出execl
|
||||
# 结果转换成 中文名称:值 的字典列表
|
||||
field_mapping = {
|
||||
'name': '联系人姓名',
|
||||
'custom_type': '客户类型',
|
||||
'phone': '联系人电话',
|
||||
'email': '邮箱',
|
||||
'company': '公司名称',
|
||||
'content': '咨询内容',
|
||||
'feedback': '反馈状态',
|
||||
}
|
||||
# 新增值映射字典,集中管理各字段的数值转换规则
|
||||
value_mapping = {
|
||||
'custom_type': {'0': '个人', '1': '企业'},
|
||||
'feedback': {'0': '未反馈', '1': '已反馈'} # 根据表结构补充反馈状态映射
|
||||
}
|
||||
# 转换字典键为中文
|
||||
for data_dic in result:
|
||||
# 拆分后:显式循环结构(便于后续处理)
|
||||
new_data_dic = {}
|
||||
# 按field_mapping定义的顺序处理字段,确保输出顺序一致
|
||||
for key in field_mapping.keys():
|
||||
# 跳过数据中不存在的字段
|
||||
if key not in data_dic:
|
||||
continue
|
||||
value = data_dic[key]
|
||||
chinese_key = field_mapping[key]
|
||||
if key in value_mapping:
|
||||
mapped_value = value_mapping[key].get(str(value), value) # 若未找到对应映射,保留原始值
|
||||
new_data_dic[chinese_key] = mapped_value
|
||||
else:
|
||||
new_data_dic[chinese_key] = value
|
||||
data_dic.clear()
|
||||
data_dic.update(new_data_dic)
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search success',
|
||||
|
||||
@ -2,32 +2,33 @@ async def getpromoting(ns):
|
||||
"""促销展示"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
# if ns:
|
||||
# 生成邀请码展示促销活动
|
||||
users_id = await get_user()
|
||||
if ns.get('type'):
|
||||
ns['sort'] = 'create_at desc'
|
||||
users_id = await get_user()
|
||||
if ns.get('type'):
|
||||
ns['sort'] = 'create_at desc'
|
||||
|
||||
orgid = await sor.R('users', {'id': users_id})
|
||||
ns['orgid'] = orgid[0]['orgid']
|
||||
# reacs = await sor.R('promoting', ns)
|
||||
dates = datetime.datetime.now()
|
||||
promoting = """select * from promoting where del_flg = 0 and orgid = ${orgid}$ and end_date > ${dates}$ order by create_at desc"""
|
||||
reacs = await sor.sqlExe(promoting, {'orgid': ns['orgid'],'dates':dates})
|
||||
date = await get_business_date(sor=None)
|
||||
listdata = []
|
||||
for i in reacs:
|
||||
if i['end_date'] > date:
|
||||
listdata.append(i)
|
||||
return {'status': True, 'data': listdata}
|
||||
else:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
orgid = await sor.R('users', {'id': users_id})
|
||||
ns['orgid'] = orgid[0]['orgid']
|
||||
reacs = await sor.R('promoting', ns)
|
||||
return {'status': True, 'data': reacs}
|
||||
return {'status': False, 'msg': '参数不正确'}
|
||||
orgid = await sor.R('users', {'id': users_id})
|
||||
ns['orgid'] = orgid[0]['orgid']
|
||||
# reacs = await sor.R('promoting', ns)
|
||||
dates = datetime.datetime.now()
|
||||
promoting = """select * from promoting where del_flg = 0 and orgid = ${orgid}$ and end_date > ${dates}$ order by create_at desc"""
|
||||
reacs = await sor.sqlExe(promoting, {'orgid': ns['orgid'],'dates':dates})
|
||||
date = await get_business_date(sor=None)
|
||||
listdata = []
|
||||
for i in reacs:
|
||||
if i['end_date'] > date:
|
||||
listdata.append(i)
|
||||
return {'status': True, 'data': listdata}
|
||||
else:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
orgid = await sor.R('users', {'id': users_id})
|
||||
ns['orgid'] = orgid[0]['orgid']
|
||||
reacs = await sor.R('promoting', ns)
|
||||
return {'status': True, 'data': reacs}
|
||||
|
||||
# return {'status': False, 'msg': '参数不正确'}
|
||||
|
||||
ret = await getpromoting(params_kw)
|
||||
return ret
|
||||
@ -69,10 +69,10 @@ async def cpcc_kehu_kan_chanpin(ns={}):
|
||||
cpcc_li = await sor.sqlExe(cpcc_find_sql, {})
|
||||
|
||||
domain_url = ns.get('domain_url')
|
||||
if ('https://www.kaiyuancloud.cn/dev' in domain_url) or ('localhost' in domain_url):
|
||||
base_url = 'https://www.kaiyuancloud.cn/dev'
|
||||
elif 'https://www.kaiyuancloud.cn' in domain_url:
|
||||
base_url = 'https://www.kaiyuancloud.cn'
|
||||
if ('https://www.opencomputing.cn/dev' in domain_url) or ('localhost' in domain_url):
|
||||
base_url = 'https://www.opencomputing.cn/dev'
|
||||
elif 'https://www.opencomputing.cn' in domain_url:
|
||||
base_url = 'https://www.opencomputing.cn'
|
||||
else:
|
||||
base_url = domain_url.split('://')[0] + '://' + domain_url.split('://')[1].split('/')[0]
|
||||
|
||||
|
||||
@ -217,10 +217,10 @@ async def create_cpcc_instance(ns={}):
|
||||
customer_goods_id = affirmbz_order_res['customer_goods_id']
|
||||
try:
|
||||
domain_url = ns.get('domain_url')
|
||||
if ('https://www.kaiyuancloud.cn/dev' in domain_url) or ('localhost' in domain_url):
|
||||
base_url = 'https://www.kaiyuancloud.cn/dev'
|
||||
elif 'https://www.kaiyuancloud.cn' in domain_url:
|
||||
base_url = 'https://www.kaiyuancloud.cn'
|
||||
if ('https://www.opencomputing.cn/dev' in domain_url) or ('localhost' in domain_url):
|
||||
base_url = 'https://www.opencomputing.cn/dev'
|
||||
elif 'https://www.opencomputing.cn' in domain_url:
|
||||
base_url = 'https://www.opencomputing.cn'
|
||||
else:
|
||||
base_url = domain_url.split('://')[0] + '://' + domain_url.split('://')[1].split('/')[0]
|
||||
|
||||
|
||||
@ -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', 'test.kaiyuancloud.cn', 'localhost:9527']) and '/domain/' not in url_link:
|
||||
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:
|
||||
yezhu_info = (await sor.R('organization', {'org_type': '0'}))[0]
|
||||
domain_res = (await sor.R('params', {'pname': '业主机构域名'}))[0]['pvalue']
|
||||
# yezhu = {
|
||||
@ -61,18 +61,27 @@ async def get_ipc_logo(ns={}):
|
||||
yezhu = json.loads(domain_res.replace("'", '"')) if not isinstance(domain_res, dict) else domain_res
|
||||
yezhu['domain_name'] = domain_url
|
||||
if 'ncmatch' in domain_url or '9527' in domain_url:
|
||||
yezhu['logo'] = "https://www.kaiyuancloud.cn/idfile?path=logo_ncmatch.png"
|
||||
yezhu['logo'] = "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png"
|
||||
yezhu['additional_msg'] = {
|
||||
"home": {
|
||||
"logoImg": "https://www.kaiyuancloud.cn/idfile?path=logo_ncmatch.png",
|
||||
"logoImg": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
|
||||
"bannerTitle": "开元数智",
|
||||
"adress": "北京市石景山区和平西路60号院1号楼11层1101-30",
|
||||
"footerTitle": "开元数智(北京)科技有限公司",
|
||||
'qrCode': 'https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ncmatch_inquiry.jpg'
|
||||
'qrCode': 'https://www.opencomputing.cn/idfile?path=firstpagehot/ncmatch_inquiry.jpg',
|
||||
'footer_info': '京ICP备2022001945号-4 开元数智(北京)科技有限公司',
|
||||
"copyright": "",
|
||||
"domain_name": "ncmatch.cn",
|
||||
"email": "Open-computing@kaiyuancloud.cn",
|
||||
"license": "2022001945号-4",
|
||||
"logo": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
|
||||
"mobile": "400-6150805 010-65917875",
|
||||
"publicsecurity": "11010502054007",
|
||||
"businesslicense": "京B2-20232313"
|
||||
},
|
||||
"about": {
|
||||
"title": "开元数智",
|
||||
"logo": "https://www.kaiyuancloud.cn/idfile?path=logo_ncmatch.png",
|
||||
"logo": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
|
||||
"content": [
|
||||
"开元数智(北京)科技有限公司(以下简称“开元数智”)创立于2022年,总部位于北京中关村科技园区,现已形成以上海、南京、深圳、济南为区域枢纽的全国性服务网络。作为新型数字基础设施建设领域的创新企业,公司主营业务涵盖智能算力中心规划建设与运营、算力网络体系构建、企业级AI算力服务及大模型应用整体解决方案。",
|
||||
"公司自主研发的NCMatch智能算力公共服务平台,作为行业领先的一站式人工智能算力服务解决方案,已构建云网算数智“五位一体”的服务体系。该平台深度整合算力资源调度系统、智能算法模型库及行业应用矩阵,为高等院校、科研院所、政企机构及人工智能开发企业提供专业级算力云服务,全面覆盖基础算力供给、大模型训练调优及产业智能化升级等多维度需求。",
|
||||
@ -82,18 +91,27 @@ async def get_ipc_logo(ns={}):
|
||||
]
|
||||
}
|
||||
}
|
||||
elif 'kaiyuancloud' in domain_url:
|
||||
elif 'kaiyuancloud' in domain_url or 'opencomputing' in domain_url or 'localhost' in domain_url:
|
||||
yezhu['additional_msg'] = {
|
||||
"home": {
|
||||
"logoImg": "https://www.kaiyuancloud.cn/idfile?path=logo.png",
|
||||
"logoImg": "https://www.opencomputing.cn/idfile?path=logo.png",
|
||||
"bannerTitle": "开元云",
|
||||
"adress": "北京市朝阳区东三环中路65号富力中心",
|
||||
"footerTitle": "开元云(北京)科技有限公司",
|
||||
'qrCode': 'https://www.kaiyuancloud.cn/idfile?path=firstpagehot/kaiyuancloud_inquiry.png'
|
||||
'qrCode': 'https://www.opencomputing.cn/idfile?path=firstpagehot/kaiyuancloud_inquiry.png',
|
||||
'footer_info': '京公网安备11010502054007号 开元云(北京)科技有限公司',
|
||||
"copyright": "",
|
||||
"domain_name": "ncmatch.cn",
|
||||
"email": "Open-computing@kaiyuancloud.cn",
|
||||
"license": "2022001945号-2",
|
||||
"logo": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
|
||||
"mobile": "400-6150805 010-65917875",
|
||||
"publicsecurity": "11010502054007",
|
||||
"businesslicense": "京B2-20232313"
|
||||
},
|
||||
"about": {
|
||||
"title": "开元云",
|
||||
"logo": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/kaiyuan_about.jpg",
|
||||
"logo": "https://www.opencomputing.cn/idfile?path=firstpagebg/kaiyuan_about.jpg",
|
||||
"content": [
|
||||
'开元云科技(Open Computing.ai)以"让AI无处不在,让智能如此简单"为使命,通过融合技术赋能千行百业,致力于成为全球领先的人工智能服务运营商。公司聚焦教育科研、金融风控、轨道交通、生物医药、医疗诊断等战略应用场景,构建全栈AI解决方案,推动产业智能化升级。',
|
||||
'作为国家级高新技术企业、创新型中小企业和ISO9001/27001双认证单位,以"卓越、开放、创新"为核心价值观,与北京大学科创园、中关村NCMatch 、浪潮云洲、百度智能云、阿里云等顶尖机构建立深度合作。依托自主研发的OCAI 公共服务平台,实现AI模型服务与商业价值的双重突破。',
|
||||
|
||||
54
b/user/enterprise_audit_info_add.dspy
Normal file
54
b/user/enterprise_audit_info_add.dspy
Normal file
@ -0,0 +1,54 @@
|
||||
async def enterprise_audit_info_add(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 检查orgid是否存在
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'user not found'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
|
||||
# 检查orgid在数据库是否存在
|
||||
orgid_exist = await sor.R('enterprise_audit_info', {'orgid': orgid, 'del_flg': '0'})
|
||||
if orgid_exist:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'orgid info already exists'
|
||||
}
|
||||
|
||||
ns_dic = {
|
||||
'id': uuid(),
|
||||
'orgid': orgid,
|
||||
'account_type': ns.get('account_type'),
|
||||
'company_name': ns.get('company_name'),
|
||||
'license_number': ns.get('license_number'),
|
||||
'license_original_img': ns.get('license_original_img'),
|
||||
'license_copy_img': ns.get('license_copy_img'),
|
||||
'office_address': ns.get('office_address'),
|
||||
'registered_address': ns.get('registered_address'),
|
||||
'contact_name': ns.get('contact_name'),
|
||||
'telephone': ns.get('telephone'),
|
||||
'mobile_phone': ns.get('mobile_phone'),
|
||||
'email': ns.get('email'),
|
||||
'audit_status': 'pending', # 默认待审
|
||||
}
|
||||
try:
|
||||
await sor.C('enterprise_audit_info', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'enterprise audit info created successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to create enterprise audit info, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await enterprise_audit_info_add(params_kw)
|
||||
return ret
|
||||
117
b/user/enterprise_audit_info_search.dspy
Normal file
117
b/user/enterprise_audit_info_search.dspy
Normal file
@ -0,0 +1,117 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
|
||||
return role
|
||||
|
||||
async def enterprise_audit_info_search(ns={}):
|
||||
if not ns.get('url_link'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '请传递url_link'
|
||||
}
|
||||
|
||||
# 分页
|
||||
current_page = int(ns['current_page']) if ns.get('current_page') else 1
|
||||
page_size = int(ns['page_size']) if ns.get('page_size') else 10
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
audit_status = ns.get('audit_status')
|
||||
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
if 'localhost' in domain_name:
|
||||
domain_name = 'dev.opencomputing.cn'
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 检查orgid是否存在
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'user not found'
|
||||
}
|
||||
orgid = user_list[0]['orgid']
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
try:
|
||||
if user_role == '客户' or user_role == '管理员': # 客户查询
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM enterprise_audit_info WHERE orgid = '%s' AND del_flg = '0';""" % orgid
|
||||
find_sql = """SELECT * FROM enterprise_audit_info WHERE orgid = '%s' AND del_flg = '0';""" % orgid
|
||||
else: # 运营查询 enterprise_audit_info和organization表关联查询 enterprise_audit_info中的orgid和organization表中的id关联查询
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM enterprise_audit_info AS eai LEFT JOIN organization as org ON eai.orgid = org.id WHERE org.parentid = '%s' AND eai.del_flg = '0';""" % orgid
|
||||
find_sql = """SELECT eai.* FROM enterprise_audit_info AS eai LEFT JOIN organization as org ON eai.orgid = org.id WHERE org.parentid = '%s' AND eai.del_flg = '0' ORDER BY eai.update_time DESC LIMIT %s OFFSET %s;""" % (orgid, page_size, offset)
|
||||
# 拆分find_sql 增加audit_status条件筛选
|
||||
if audit_status:
|
||||
# Split the audit_status string into individual statuses
|
||||
statuses = [status.strip() for status in audit_status.split(',') if status.strip()]
|
||||
if statuses:
|
||||
# Create a properly escaped list of statuses for SQL
|
||||
escaped_statuses = []
|
||||
for status in statuses:
|
||||
# Escape single quotes by doubling them (SQL standard)
|
||||
escaped_status = status.replace("'", "''")
|
||||
escaped_statuses.append(f"'{escaped_status}'")
|
||||
|
||||
# Join the escaped statuses for the IN clause
|
||||
statuses_str = ','.join(escaped_statuses)
|
||||
|
||||
if statuses_str:
|
||||
count_sql = count_sql.split("WHERE")[0] + f"WHERE eai.audit_status IN ({statuses_str}) AND " + count_sql.split("WHERE")[1]
|
||||
find_sql = find_sql.split("WHERE")[0] + f"WHERE eai.audit_status IN ({statuses_str}) AND " + find_sql.split("WHERE")[1]
|
||||
# 非pending
|
||||
else:
|
||||
count_sql = count_sql.split("WHERE")[0] + "WHERE eai.audit_status != 'pending' AND " + count_sql.split("WHERE")[1]
|
||||
find_sql = find_sql.split("WHERE")[0] + "WHERE eai.audit_status != 'pending' AND " + find_sql.split("WHERE")[1]
|
||||
|
||||
# 执行查询
|
||||
total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
res = await sor.sqlExe(find_sql, {})
|
||||
|
||||
# 处理结果中的图片路径 增加前缀
|
||||
for item in res:
|
||||
if item.get('license_original_img'):
|
||||
item['license_original_img'] = 'https://' + domain_name + '/idfile?path=' + item['license_original_img']
|
||||
if item.get('license_copy_img'):
|
||||
item['license_copy_img'] = 'https://' + domain_name + '/idfile?path=' + item['license_copy_img']
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'enterprise audit info search successfully',
|
||||
'data': {
|
||||
'total_count': total_count,
|
||||
'current_page': current_page,
|
||||
'page_size': page_size,
|
||||
'data': res
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to search enterprise audit info, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await enterprise_audit_info_search(params_kw)
|
||||
return ret
|
||||
70
b/user/enterprise_audit_info_update.dspy
Normal file
70
b/user/enterprise_audit_info_update.dspy
Normal file
@ -0,0 +1,70 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
# get role
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "userrole table, user id can not find..."
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
# get role name
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "role table, can not get role name"
|
||||
}
|
||||
|
||||
return role
|
||||
|
||||
async def enterprise_audit_info_update(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 检查orgid是否存在
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
user_list = await sor.R('users', {'id': userid})
|
||||
if not user_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'user not found'
|
||||
}
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
ns.pop('userid', None)
|
||||
# ns['orgid'] = orgid
|
||||
try:
|
||||
if user_role == '客户': # 客户更新
|
||||
ns['audit_status'] = 'pending' # 客户更新时默认审核状态为待审
|
||||
else: # 运营更新 如果是approved reject_reason为空
|
||||
if ns.get('audit_status') == 'approved':
|
||||
ns['reject_reason'] = None
|
||||
|
||||
# 生成更新的sql语句
|
||||
update_sql = """UPDATE enterprise_audit_info SET """
|
||||
for key, value in ns.items():
|
||||
if value is None:
|
||||
update_sql += f"{key} = NULL, "
|
||||
continue
|
||||
update_sql += f"{key} = '{value}', "
|
||||
update_sql = update_sql[:-2] + f" WHERE id = '{ns.get('id')}';"""
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '更新成功'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to update enterprise audit info, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await enterprise_audit_info_update(params_kw)
|
||||
return ret
|
||||
59
b/user/favorite_add.dspy
Normal file
59
b/user/favorite_add.dspy
Normal file
@ -0,0 +1,59 @@
|
||||
async def favorite_add(ns={}):
|
||||
"""
|
||||
添加用户收藏
|
||||
:param ns: 包含userid, productid, favorite_type等参数
|
||||
:return: 操作结果
|
||||
"""
|
||||
ns_dic = {
|
||||
'id': uuid(), # 生成32位ID
|
||||
'userid': ns.get('userid'),
|
||||
'productid': ns.get('productid'),
|
||||
'favorite_type': ns.get('favorite_type', '1'), # 默认为商品收藏
|
||||
'tag': ns.get('tag') # 标签
|
||||
}
|
||||
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
ns_dic['userid'] = ns.get('userid')
|
||||
else:
|
||||
ns_dic['userid'] = await get_user()
|
||||
|
||||
if not ns_dic.get('userid'):
|
||||
server_error(401)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 检查是否已收藏 处理tag是NULL的情况
|
||||
conditions = [
|
||||
"userid = '%s'" % ns_dic['userid'],
|
||||
"productid = '%s'" % ns_dic['productid'],
|
||||
"favorite_type = '%s'" % ns_dic['favorite_type'] if ns_dic['favorite_type'] is not None else "favorite_type IS NULL",
|
||||
"del_flg = '0'",
|
||||
"tag = '%s'" % ns_dic['tag'] if ns_dic['tag'] is not None else "tag IS NULL"
|
||||
]
|
||||
check_sql = "SELECT id FROM user_favorite WHERE " + " AND ".join(conditions)
|
||||
|
||||
check_result = await sor.sqlExe(check_sql, {})
|
||||
|
||||
if check_result:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '已收藏关注'
|
||||
}
|
||||
|
||||
# 执行收藏操作
|
||||
await sor.C('user_favorite', ns_dic)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '关注收藏成功'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '关注收藏失败, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await favorite_add(params_kw)
|
||||
return ret
|
||||
43
b/user/favorite_delete.dspy
Normal file
43
b/user/favorite_delete.dspy
Normal file
@ -0,0 +1,43 @@
|
||||
async def favorite_delete(ns={}):
|
||||
"""
|
||||
删除用户收藏(软删除)
|
||||
:param ns: 包含id或userid+productid+favorite_type参数
|
||||
:return: 操作结果
|
||||
"""
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
ns['userid'] = ns.get('userid')
|
||||
else:
|
||||
ns['userid'] = await get_user()
|
||||
if not ns.get('userid'):
|
||||
server_error(401)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if ns.get('id'):
|
||||
# 根据收藏ID删除
|
||||
update_sql = """
|
||||
UPDATE user_favorite
|
||||
SET del_flg = '1'
|
||||
WHERE userid = '%s' AND productid = '%s'
|
||||
""" % (ns.get('userid'), ns.get('id'))
|
||||
await sor.sqlExe(update_sql, {})
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '缺少必要参数'
|
||||
}
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '取消关注收藏成功'
|
||||
}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '取消关注收藏失败, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await favorite_delete(params_kw)
|
||||
return ret
|
||||
108
b/user/favorite_search.dspy
Normal file
108
b/user/favorite_search.dspy
Normal file
@ -0,0 +1,108 @@
|
||||
async def favorite_search(ns={}):
|
||||
"""
|
||||
查询用户收藏列表
|
||||
:param ns: 包含userid, favorite_type等查询参数
|
||||
:return: 查询结果
|
||||
"""
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
ns['userid'] = ns.get('userid')
|
||||
else:
|
||||
ns['userid'] = await get_user()
|
||||
if not ns.get('userid'):
|
||||
server_error(401)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 分页参数
|
||||
current_page = int(ns.get('current_page', 1))
|
||||
page_size = int(ns.get('page_size', 1000))
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
# 构建查询条件
|
||||
where_conditions = ["f.del_flg = '0'"]
|
||||
if ns.get('userid'):
|
||||
where_conditions.append("f.userid = '%s'" % ns.get('userid'))
|
||||
if ns.get('publish_type'):
|
||||
where_conditions.append("f.favorite_type = '%s'" % ns.get('publish_type'))
|
||||
|
||||
where_clause = " AND ".join(where_conditions)
|
||||
|
||||
# 查询总数
|
||||
count_sql = """
|
||||
SELECT COUNT(*) AS total_count
|
||||
FROM user_favorite f
|
||||
WHERE %s
|
||||
""" % where_clause
|
||||
|
||||
count_result = await sor.sqlExe(count_sql, {})
|
||||
total_count = count_result[0]['total_count'] if count_result else 0
|
||||
|
||||
# 查询数据
|
||||
query_sql = """
|
||||
SELECT *
|
||||
FROM user_favorite f
|
||||
WHERE %s
|
||||
ORDER BY f.create_at DESC
|
||||
LIMIT %s OFFSET %s
|
||||
""" % (where_clause, page_size, offset)
|
||||
result = await sor.sqlExe(query_sql, {})
|
||||
|
||||
# 通过查询数据中的productid, 查询product表, 增加product_info
|
||||
for product in result:
|
||||
product_sql = f"""
|
||||
SELECT * FROM user_publish_product
|
||||
WHERE id = '{product['productid']}' AND del_flg = '0' AND listing_status = 'listing';
|
||||
"""
|
||||
product_info_li = await sor.sqlExe(product_sql, {})
|
||||
if product_info_li:
|
||||
product['product_info'] = product_info_li[0]
|
||||
# 增加收藏状态
|
||||
product['product_info']['favorite'] = '1'
|
||||
# 手机号加*
|
||||
if product['product_info'].get('phone_number'):
|
||||
product['product_info']['phone_number'] = '**************'
|
||||
if product['product_info'].get('img'):
|
||||
product['product_info']['img'] = 'https://' + product['product_info']['domain_name'] + '/idfile?path=' + product['product_info']['img']
|
||||
|
||||
else:
|
||||
product['product_info'] = None
|
||||
|
||||
date_groups = {}
|
||||
for item in result:
|
||||
# 提取日期部分(如"2025-08-22 15:58:52" → "2025-08-22")
|
||||
browse_date = datetime.datetime.strptime(item["create_at"], "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%d")
|
||||
if browse_date not in date_groups:
|
||||
date_groups[browse_date] = []
|
||||
|
||||
date_groups[browse_date].append(item)
|
||||
|
||||
# 按日期升序排序并添加序号
|
||||
sorted_dates = sorted(date_groups.keys(), reverse=True) # 按日期升序排列
|
||||
result = []
|
||||
for idx, date in enumerate(sorted_dates, start=1):
|
||||
result.append({
|
||||
"id": str(idx), # 序号从1开始
|
||||
"browse_date": date,
|
||||
"products": date_groups[date] # 该日期下的所有浏览记录
|
||||
})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '查询成功',
|
||||
'data': {
|
||||
'total_count': total_count,
|
||||
'current_page': current_page,
|
||||
'page_size': page_size,
|
||||
'favorites': result
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '查询失败, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await favorite_search(params_kw)
|
||||
return ret
|
||||
@ -1,26 +1,67 @@
|
||||
async def mobilecode(ns):
|
||||
"""登录发送短信验证码"""
|
||||
"""发送短信验证码,支持注册和登录筛选"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
type = 0
|
||||
ns['del_flg'] = '0'
|
||||
userreacs = await sor.R('users', ns)
|
||||
if len(userreacs) >= 1:
|
||||
type += 1
|
||||
else:
|
||||
userreacs = await sor.R('users', {'mobile': ns['username'], 'del_flg': '0'})
|
||||
if len(userreacs) >= 1:
|
||||
type += 1
|
||||
if type >= 1:
|
||||
code = await generate_vcode()
|
||||
nss = await send_vcode(userreacs[0]['mobile'], '用户注册登录验证', {'SMSvCode': code.get('vcode')})
|
||||
# return {'1':nss}
|
||||
if nss:
|
||||
return {'status': True, 'msg': '发送成功', 'codeid': code.get('id')}
|
||||
# 获取操作类型:register 或 login
|
||||
action_type = ns.get('action_type') # register 或 login
|
||||
|
||||
if not action_type:
|
||||
return {'status': False, 'msg': '操作类型action_type不能为空'}
|
||||
|
||||
# 通过手机号查找用户
|
||||
mobile = ns.get('mobile')
|
||||
if not mobile:
|
||||
return {'status': False, 'msg': '手机号不能为空'}
|
||||
|
||||
userreacs = await sor.R('users', {'mobile': mobile, 'del_flg': '0'})
|
||||
|
||||
# 注册逻辑:检查手机号是否已存在
|
||||
if action_type == 'register':
|
||||
if len(userreacs) >= 1:
|
||||
return {'status': False, 'msg': '手机号已注册,请直接登录'}
|
||||
else:
|
||||
return {'status': False, 'msg': '发送失败'}
|
||||
# 注册时手机号不存在,可以发送验证码
|
||||
code = await generate_vcode()
|
||||
nss = await send_vcode(mobile, '用户注册登录验证', {'SMSvCode': code.get('vcode')})
|
||||
if nss['status']:
|
||||
return {'status': True, 'msg': '注册验证码发送成功', 'codeid': code.get('id')}
|
||||
else:
|
||||
return {'status': False, 'msg': '发送失败'}
|
||||
|
||||
# 登录逻辑:检查手机号是否存在
|
||||
elif action_type == 'login':
|
||||
if len(userreacs) >= 1:
|
||||
# 登录时手机号存在,可以发送验证码
|
||||
code = await generate_vcode()
|
||||
nss = await send_vcode(userreacs[0]['mobile'], '用户注册登录验证', {'SMSvCode': code.get('vcode')})
|
||||
if nss['status']:
|
||||
return {'status': True, 'msg': '登录验证码发送成功', 'codeid': code.get('id')}
|
||||
else:
|
||||
return {'status': False, 'msg': '发送失败'}
|
||||
else:
|
||||
return {'status': False, 'action': 'redirect', 'msg': '用户未注册, 请到注册页面注册'}
|
||||
|
||||
# 原有逻辑:如果没有指定action_type,保持原有逻辑
|
||||
else:
|
||||
return {'status': False, 'action': 'redirect', 'msg': '用户未注册, 请到注册页面注册'}
|
||||
type = 0
|
||||
ns['del_flg'] = '0'
|
||||
userreacs = await sor.R('users', ns)
|
||||
if len(userreacs) >= 1:
|
||||
type += 1
|
||||
else:
|
||||
userreacs = await sor.R('users', {'mobile': ns['username'], 'del_flg': '0'})
|
||||
if len(userreacs) >= 1:
|
||||
type += 1
|
||||
if type >= 1:
|
||||
code = await generate_vcode()
|
||||
nss = await send_vcode(userreacs[0]['mobile'], '用户注册登录验证', {'SMSvCode': code.get('vcode')})
|
||||
# return {'1':nss}
|
||||
if nss:
|
||||
return {'status': True, 'msg': '发送成功', 'codeid': code.get('id')}
|
||||
else:
|
||||
return {'status': False, 'msg': '发送失败'}
|
||||
else:
|
||||
return {'status': False, 'action': 'redirect', 'msg': '用户未注册, 请到注册页面注册'}
|
||||
|
||||
|
||||
ret = await mobilecode(params_kw)
|
||||
|
||||
54
b/user/user_browse_history_add.dspy
Normal file
54
b/user/user_browse_history_add.dspy
Normal file
@ -0,0 +1,54 @@
|
||||
async def user_browse_history_add(ns={}):
|
||||
# 必要参数校验
|
||||
if not ns.get('userid') or not ns.get('productid'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'userid and productid are required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 根据timestamp时间字段:browse_time去重 查找10个小时内是否存在
|
||||
# browse_time = datetime.datetime.now() - datetime.timedelta(hours=10)
|
||||
check_sql = """
|
||||
SELECT * FROM user_browse_history
|
||||
WHERE userid = '%s' AND productid = '%s' AND del_flg = '0';
|
||||
""" % (ns.get('userid'), ns.get('productid'))
|
||||
check_result = await sor.sqlExe(check_sql, {})
|
||||
if check_result:
|
||||
# 数据库更新browse_time字段
|
||||
update_sql = """
|
||||
UPDATE user_browse_history
|
||||
SET browse_time = '%s'
|
||||
WHERE id = '%s';
|
||||
""" % (datetime.datetime.now(), check_result[0]['id'])
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history recorded successfully',
|
||||
'data': {'record_id': check_result[0]['id']}
|
||||
}
|
||||
|
||||
# 生成记录ID
|
||||
record_id = uuid()
|
||||
insert_sql = """
|
||||
INSERT INTO user_browse_history (
|
||||
id, userid, productid, ip_address, user_agent, del_flg, tag
|
||||
) VALUES ('%s', '%s', '%s', '%s', '%s', '0', '%s');
|
||||
""" % (record_id, ns.get('userid'), ns.get('productid'),
|
||||
ns.get('ip_address', ''), ns.get('user_agent', ''), ns.get('tag', ''))
|
||||
await sor.sqlExe(insert_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history recorded successfully',
|
||||
'data': {'record_id': record_id}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to record browse history, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await user_browse_history_add(params_kw)
|
||||
return ret
|
||||
29
b/user/user_browse_history_delete.dspy
Normal file
29
b/user/user_browse_history_delete.dspy
Normal file
@ -0,0 +1,29 @@
|
||||
async def user_browse_history_delete(ns={}):
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'record id is required'
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 逻辑删除(更新删除标志)
|
||||
update_sql = """
|
||||
UPDATE user_browse_history
|
||||
SET del_flg = '1'
|
||||
WHERE id = '%s';
|
||||
""" % ns.get('id')
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history deleted successfully'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to delete browse history, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await user_browse_history_delete(params_kw)
|
||||
return ret
|
||||
124
b/user/user_browse_history_search.dspy
Normal file
124
b/user/user_browse_history_search.dspy
Normal file
@ -0,0 +1,124 @@
|
||||
async def user_browse_history_search(ns={}):
|
||||
# 处理url_link转换成domain_name
|
||||
if ns.get('url_link'):
|
||||
domain_name = ns.get('url_link').split("//")[1].split("/")[0]
|
||||
else:
|
||||
domain_name = None
|
||||
|
||||
# 处理userid
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
if not userid:
|
||||
server_error(401)
|
||||
|
||||
# 参数处理
|
||||
productid = ns.get('productid')
|
||||
publish_type = ns.get('publish_type')
|
||||
start_time = ns.get('start_time')
|
||||
end_time = ns.get('end_time')
|
||||
page_size = int(ns.get('page_size', 10000))
|
||||
current_page = int(ns.get('current_page', 1))
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
# 基础查询条件
|
||||
base_conditions = ["del_flg = '0'"]
|
||||
if userid:
|
||||
base_conditions.append(f"userid = '{userid}'")
|
||||
if productid:
|
||||
base_conditions.append(f"productid = '{productid}'")
|
||||
if publish_type:
|
||||
base_conditions.append(f"publish_type = '{publish_type}'")
|
||||
if start_time and end_time:
|
||||
end_time += ' 23:59:59'
|
||||
base_conditions.append(f"browse_time BETWEEN '{start_time}' AND '{end_time}'")
|
||||
|
||||
# 构建查询SQL
|
||||
where_clause = " AND ".join(base_conditions)
|
||||
|
||||
find_sql = f"""
|
||||
SELECT * FROM user_browse_history
|
||||
WHERE {where_clause}
|
||||
ORDER BY browse_time DESC
|
||||
LIMIT {page_size} OFFSET {offset};
|
||||
"""
|
||||
# 总数查询SQL
|
||||
count_sql = f"""
|
||||
SELECT COUNT(*) AS total_count FROM user_browse_history
|
||||
WHERE {where_clause};
|
||||
"""
|
||||
|
||||
# 执行查询
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
|
||||
# 根据result中productid查询product_info
|
||||
for product in result:
|
||||
# 查询product_info
|
||||
product_sql = f"""
|
||||
SELECT * FROM user_publish_product
|
||||
WHERE id = '{product['productid']}' AND del_flg = '0' AND listing_status = 'listing';
|
||||
"""
|
||||
favorite_sql = f"""
|
||||
SELECT * FROM user_favorite
|
||||
WHERE productid = '{product['productid']}' AND userid = '{userid}' AND del_flg = '0';
|
||||
"""
|
||||
favorite_status = await sor.sqlExe(favorite_sql, {})
|
||||
product_info_li = await sor.sqlExe(product_sql, {})
|
||||
if product_info_li:
|
||||
product['product_info'] = product_info_li[0]
|
||||
|
||||
if favorite_status:
|
||||
product['product_info']['favorite'] = '1'
|
||||
else:
|
||||
product['product_info']['favorite'] = '0'
|
||||
|
||||
if product['product_info'].get('phone_number'):
|
||||
product['product_info']['phone_number'] = '***************'
|
||||
if product['product_info'].get('img'):
|
||||
product['product_info']['img'] = 'https://' + product['product_info']['domain_name'] + '/idfile?path=' + product['product_info']['img']
|
||||
else:
|
||||
product['product_info'] = None
|
||||
|
||||
date_groups = {}
|
||||
for item in result:
|
||||
# 提取日期部分(如"2025-08-22 15:58:52" → "2025-08-22")
|
||||
browse_date = datetime.datetime.strptime(item["browse_time"], "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%d")
|
||||
if browse_date not in date_groups:
|
||||
date_groups[browse_date] = []
|
||||
|
||||
date_groups[browse_date].append(item)
|
||||
|
||||
# 按日期升序排序并添加序号
|
||||
sorted_dates = sorted(date_groups.keys(), reverse=True) # 按日期升序排列
|
||||
result = []
|
||||
for idx, date in enumerate(sorted_dates, start=1):
|
||||
result.append({
|
||||
"id": str(idx), # 序号从1开始
|
||||
"browse_date": date,
|
||||
"products": date_groups[date] # 该日期下的所有浏览记录
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Browse history retrieved successfully',
|
||||
'data': {
|
||||
'total_count': total_count,
|
||||
'page_size': page_size,
|
||||
'current_page': current_page,
|
||||
'history_list': result
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'Failed to retrieve browse history, %s' % str(e)
|
||||
}
|
||||
|
||||
ret = await user_browse_history_search(params_kw)
|
||||
return ret
|
||||
@ -85,8 +85,8 @@
|
||||
"session_redis_delete":{
|
||||
"url":"redis://127.0.0.1:6379"
|
||||
},
|
||||
"session_max_time":3000,
|
||||
"session_issue_time":2500
|
||||
"session_max_time":30000,
|
||||
"session_issue_time":25000
|
||||
},
|
||||
"langMapping":{
|
||||
"zh-Hans-CN":"zh-cn",
|
||||
|
||||
@ -78,8 +78,8 @@
|
||||
"privatekey":"$[workdir]$/conf/rsa_private_key.pem",
|
||||
"publickey":"$[workdir]$/conf/rsa_public_key.pem"
|
||||
},
|
||||
"session_max_time":3000,
|
||||
"session_issue_time":2500
|
||||
"session_max_time":30000,
|
||||
"session_issue_time":25000
|
||||
},
|
||||
"langMapping":{
|
||||
"zh-Hans-CN":"zh-cn",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
*/20 * * * * curl https://dev.kaiyuancloud.cn/zj/zj_get_order.dspy
|
||||
49 9-10 * * * curl https://dev.kaiyuancloud.cn/zj/zj_get_bill.dspy
|
||||
|
||||
*/20 * * * * curl https://www.kaiyuancloud.cn/dev/hpc/GetUserBill.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
#*/20 * * * * curl https://www.kaiyuancloud.cn/dev/hpc/GetUserBill.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
0 0 * * * curl https://www.kaiyuancloud.cn/dev/lease/update_stock.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
# 30 9 * * * curl https://www.kaiyuancloud.cn/dev/provider_settle/auto_provider_settle_cron_job.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
# 0 1 * * * curl https://www.kaiyuancloud.cn/dev/handover/params_time.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
@ -13,13 +13,25 @@
|
||||
* * * * * curl https://www.kaiyuancloud.cn/dev/baiduc/baidu_new_update_resouce.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
#* * * * * curl https://www.kaiyuancloud.cn/dev/baiduc/baidu_sms_kafka_consumer.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
|
||||
*/20 * * * * curl https://www.kaiyuancloud.cn/hpc/GetUserBill.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
0 0 * * * curl https://www.kaiyuancloud.cn/lease/update_stock.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
# 30 9 * * * curl https://www.kaiyuancloud.cn/provider_settle/auto_provider_settle_cron_job.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
# 0 1 * * * curl https://www.kaiyuancloud.cn/handover/params_time.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
0 2 * * * curl https://www.kaiyuancloud.cn/daylog/updateCurrentTime.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/60 * * * * curl https://www.kaiyuancloud.cn/baiduc/baidu_users_get_post_pay.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/1 * * * * curl https://www.kaiyuancloud.cn/account/email_info.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/1 * * * * curl https://www.kaiyuancloud.cn/jdcloud/get_partner_order_list.dspy?page=1 > /d/zhc/crontab_prod.log 2>&1
|
||||
* * * * * curl https://www.kaiyuancloud.cn/baiduc/baidu_new_update_resouce.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
# * * * * * curl https://www.kaiyuancloud.cn/baiduc/baidu_sms_kafka_consumer.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
#*/20 * * * * curl https://dev.opencomputing.cn/hpc/GetUserBill.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
0 0 * * * curl https://dev.opencomputing.cn/lease/update_stock.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
# 30 9 * * * curl https://dev.opencomputing.cn/provider_settle/auto_provider_settle_cron_job.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
# 0 1 * * * curl https://dev.opencomputing.cn/handover/params_time.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
0 2 * * * curl https://dev.opencomputing.cn/daylog/updateCurrentTime.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
*/60 * * * * curl https://dev.opencomputing.cn/baiduc/baidu_users_get_post_pay.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
*/1 * * * * curl https://dev.opencomputing.cn/account/email_info.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
*/1 * * * * curl https://dev.opencomputing.cn/jdcloud/get_partner_order_list.dspy?page=1 > /d/zhc/crontab_dev.log 2>&1
|
||||
* * * * * curl https://dev.opencomputing.cn/baiduc/baidu_new_update_resouce.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
#* * * * * curl https://dev.opencomputing.cn/baiduc/baidu_sms_kafka_consumer.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
|
||||
#*/20 * * * * curl https://www.opencomputing.cn/hpc/GetUserBill.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
0 0 * * * curl https://www.opencomputing.cn/lease/update_stock.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
# 30 9 * * * curl https://www.opencomputing.cn/provider_settle/auto_provider_settle_cron_job.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
# 0 1 * * * curl https://www.opencomputing.cn/handover/params_time.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
0 2 * * * curl https://www.opencomputing.cn/daylog/updateCurrentTime.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/60 * * * * curl https://www.opencomputing.cn/baiduc/baidu_users_get_post_pay.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/1 * * * * curl https://www.opencomputing.cn/account/email_info.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
*/1 * * * * curl https://www.opencomputing.cn/jdcloud/get_partner_order_list.dspy?page=1 > /d/zhc/crontab_prod.log 2>&1
|
||||
* * * * * curl https://www.opencomputing.cn/baiduc/baidu_new_update_resouce.dspy > /d/zhc/crontab_prod.log 2>&1
|
||||
#* * * * * curl https://www.opencomputing.cn/baiduc/baidu_sms_kafka_consumer.dspy > /d/zhc/crontab_dev.log 2>&1
|
||||
#*/5 * * * * /usr/bin/python3 /d/zhc/kboss_prod/kgadget/src/more_task_scheduler.py
|
||||
|
||||
14775
docs/API模块文档.md
Normal file
14775
docs/API模块文档.md
Normal file
File diff suppressed because one or more lines are too long
2
f/web-kboss/.gitignore
vendored
2
f/web-kboss/.gitignore
vendored
@ -1,10 +1,8 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
# src/
|
||||
>>>>>>> a3d0bd5845e8b37373bf85c7c40401a7c67884b9
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
0
f/web-kboss/BINARY_IMAGE_UPLOAD_FIX.md
Normal file
0
f/web-kboss/BINARY_IMAGE_UPLOAD_FIX.md
Normal file
0
f/web-kboss/CHANGES_AFTER_PREVIEW_REMOVAL.md
Normal file
0
f/web-kboss/CHANGES_AFTER_PREVIEW_REMOVAL.md
Normal file
0
f/web-kboss/README_IMAGE_OPTIMIZATION.md
Normal file
0
f/web-kboss/README_IMAGE_OPTIMIZATION.md
Normal file
@ -51,6 +51,7 @@
|
||||
"uuid": "^9.0.0",
|
||||
"vue": "2.6.10",
|
||||
"vue-count-to": "^1.0.13",
|
||||
"vue-cropper": "^0.6.5",
|
||||
"vue-device-detector": "^1.1.6",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue-router": "^3.0.2",
|
||||
|
||||
@ -13,12 +13,45 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
#dify-chatbot-bubble-button {
|
||||
background-color: #1C64F2 !important;
|
||||
}
|
||||
#dify-chatbot-bubble-window {
|
||||
width: 24rem !important;
|
||||
height: 40rem !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script>
|
||||
window.difyChatbotConfig = {
|
||||
token: 'HKghmPZLD4JczCXc',
|
||||
baseUrl: 'http://aigc.smartcrec.com',
|
||||
inputs: {
|
||||
// You can define the inputs from the Start node here
|
||||
// key is the variable name
|
||||
// e.g.
|
||||
// name: "NAME"
|
||||
},
|
||||
systemVariables: {
|
||||
// user_id: 'YOU CAN DEFINE USER ID HERE',
|
||||
// conversation_id: 'YOU CAN DEFINE CONVERSATION ID HERE, IT MUST BE A VALID UUID',
|
||||
},
|
||||
userVariables: {
|
||||
// avatar_url: 'YOU CAN DEFINE USER AVATAR URL HERE',
|
||||
// name: 'YOU CAN DEFINE USER NAME HERE',
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="http://aigc.smartcrec.com/embed.min.js"
|
||||
id="HKghmPZLD4JczCXc"
|
||||
defer>
|
||||
</script>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
@ -112,6 +112,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.audioElement = new Audio('https://www.kaiyuancloud.cn/dev/idfile?path=/batch_upload/phone-ring.mp3');
|
||||
|
||||
// 设置音频循环播放
|
||||
this.audioElement.loop = true;
|
||||
if (sessionStorage.getItem('juese') === '销售' && !window.location.href.includes('login')) {
|
||||
@ -270,11 +271,6 @@ export default {
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
.el-message--success {
|
||||
/* border:1px dashed blue;
|
||||
height: 45px; */
|
||||
}
|
||||
|
||||
.el-table {
|
||||
z-index: 0 !important;
|
||||
}
|
||||
|
||||
16
f/web-kboss/src/api/BaiDuTokenapi/index.js
Normal file
16
f/web-kboss/src/api/BaiDuTokenapi/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
import request from '@/utils/request'
|
||||
// 获取token
|
||||
export function baiducloudAPI() {
|
||||
return request({
|
||||
url: `/baiduc/get_tokenid.dspy`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
// 退订回调
|
||||
export function cancelCallbackAPI(params) {
|
||||
return request({
|
||||
url: `/baiducloud/get_baidu_orderlist.dspy`,
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@ -28,7 +28,7 @@ export function getReachargelogAPI(params) {
|
||||
//客户充值冲账
|
||||
export function editReachargelogAPI(params) {
|
||||
return request({
|
||||
url: `examine/upledger_examine${suffix}`,
|
||||
url: `customer/mybalance.dspy`,
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
|
||||
@ -42,11 +42,11 @@ export function logoutAPI(params) {
|
||||
})
|
||||
}
|
||||
|
||||
//获取验证码 1
|
||||
//获取验证码
|
||||
export function getCodeAPI(params) {
|
||||
return request({
|
||||
url: `/user/mobilecode${suffix}`,
|
||||
method: 'get',
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@ -263,3 +263,23 @@ export function reqGetCodeAPI(data) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 注册/登录获取验证码
|
||||
export function sendCode(data) {
|
||||
return request({
|
||||
url: `/user/mobilecode.dspy`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
// 注册
|
||||
export function register(data) {
|
||||
console.log(data);
|
||||
|
||||
return request({
|
||||
url: `/customer/registerUser${suffix}`,
|
||||
method: 'post',
|
||||
data,
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
278
f/web-kboss/src/api/ncmatch/index.js
Normal file
278
f/web-kboss/src/api/ncmatch/index.js
Normal file
@ -0,0 +1,278 @@
|
||||
import request from "@/utils/request";
|
||||
//获取商品分类
|
||||
export function reqGetProductCategorySearch(data) {
|
||||
return request({
|
||||
url: '/product/product_category_search.dspy',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data
|
||||
})
|
||||
}
|
||||
//添加产品 publish_product_add
|
||||
export function reqPublishProductAdd(data) {
|
||||
return request({
|
||||
url: '/product/publish_product_add.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//获公司类型 /product/company_category_search.dspy
|
||||
export function reqCompanyCategorySearch(data) {
|
||||
return request({
|
||||
url: '/product/company_category_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取全部产品/product/publish_product_search_first_page.dspy
|
||||
export function reqPublishProductSearchFirstPage(data) {
|
||||
return request({
|
||||
url: '/product/publish_product_search_first_page.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//算力供需广场 获取列表
|
||||
export function reqGetSupplyAndDemandSquareList(data) {
|
||||
return request({
|
||||
url: '/product/publish_product_search_first_page.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取商品详情
|
||||
export function reqGetProductDetail(data) {
|
||||
return request({
|
||||
url: '/product/publish_product_search_detail.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//提交审批 ///user/enterprise_audit_info_add.dspy
|
||||
export function reqApproveUser(data){
|
||||
return request({
|
||||
url: '/user/enterprise_audit_info_add.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取菜单ncmatch菜单 menu
|
||||
|
||||
export function reqNcMatchMenu(data){
|
||||
return request({
|
||||
url: '/product/homepage_category_tree_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
|
||||
})
|
||||
}
|
||||
//运营查找商品|需求
|
||||
export function reqSearchByMangement(data){
|
||||
return request({
|
||||
url: '/product/publish_product_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
|
||||
})
|
||||
}
|
||||
//编辑商品
|
||||
export function reqEditProduct(data){
|
||||
return request({
|
||||
url: '/product/publish_product_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//编辑非图片字段
|
||||
export function reqEditProductNoImg(data){
|
||||
return request({
|
||||
url: '/product/publish_product_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//搜索
|
||||
export function reqSearch(data){
|
||||
return request({
|
||||
url: '/product/global_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//导出 //reqExportProduct
|
||||
export function reqExportProduct(data){
|
||||
return request({
|
||||
url: '/product/publish_product_to_excel.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//产品添加子级和兄弟节点
|
||||
export function reqAddProductMenu(data){
|
||||
return request({
|
||||
url: '/product/homepage_category_tree_add.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//资质查询
|
||||
export function reqEnterpriseAuditInfoSearch(data){
|
||||
return request({
|
||||
url: '/user/enterprise_audit_info_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//咨询表单 /product/search_user_inquiry.dspy
|
||||
export function reqSearchUserInquiry(data){
|
||||
return request({
|
||||
url: '/product/search_user_inquiry.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//审核状态查询 /user/enterprise_audit_info_search.dspy
|
||||
export function reqApproveUserSearch(data){
|
||||
return request({
|
||||
url: '/user/enterprise_audit_info_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//政企审核 更新 /user/enterprise_audit_info_update.dspy
|
||||
|
||||
export function reqEnterpriseUpdate(data){
|
||||
return request({
|
||||
url: '/user/enterprise_audit_info_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//首页类别查询 /product/homepage_product_category.dspy
|
||||
export function reqHomepageProductCategory(data){
|
||||
return request({
|
||||
url: '/product/homepage_product_category.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//产品树更新 /product/homepage_category_tree_update.dspy
|
||||
export function reqHomepageCategoryTreeUpdate(data){
|
||||
return request({
|
||||
url: '/product/homepage_category_tree_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//产品树删除 /product/homepage_category_tree_delete.dspy
|
||||
export function reqHomepageCategoryTreeDelete(data){
|
||||
return request({
|
||||
url: '/product/homepage_category_tree_delete.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//供需一级分类
|
||||
export function reqSupplyAndDemandFirstCategory(data){
|
||||
return request({
|
||||
url: '/product/product_category_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//供需二级分类
|
||||
export function reqSupplyAndDemandSecondCategory(data){
|
||||
return request({
|
||||
url: '/product/supply_and_demand_first_category.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//收藏 /product/publish_product_collect.dspy
|
||||
export function reqPublishProductCollect(data){
|
||||
return request({
|
||||
url: '/user/favorite_add.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//取消收藏 /user/favorite_delete.dspy
|
||||
export function reqFavoriteDelete(data){
|
||||
return request({
|
||||
url: '/user/favorite_delete.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//浏览记录 /user/user_browse_history_search.dspy
|
||||
export function reqUserBrowseHistorySearch(data){
|
||||
return request({
|
||||
url: '/user/user_browse_history_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//删除浏览记录 /user/user_browse_history_delete.dspy
|
||||
export function reqUserBrowseHistoryDeleteById(data){
|
||||
return request({
|
||||
url: '/user/user_browse_history_delete.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//删除关注记录 /user/favorite_delete.dspy
|
||||
export function reqFavoriteDeleteById(data){
|
||||
return request({
|
||||
url: '/user/favorite_delete.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//全部收藏列表 /user/favorite_search.dspy
|
||||
export function reqFavoriteSearch(data){
|
||||
return request({
|
||||
url: '/user/favorite_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user