fix(entcms): 重写所有数据库操作使用 async with context manager
_get_db() 返回的是 async context manager,不是 sor 对象。
所有函数都错误地直接调用 sor.R/C/U/D,导致 AttributeError。
修正为正确模式:
db = DBPools()
async with db.sqlorContext(DBNAME) as sor:
await sor.R('table', ns)
影响函数:
- cms_content CRUD (4个)
- cms_categories CRUD (4个) + get_category_options
- cms_leads CRUD (4个) + submit_lead
- cms_sections CRUD (4个) + get_visible_sections
- cms_site_config CRUD (4个) + get_site_config
- get_published_content, get_latest_news, get_content_detail
- submit_content_for_approval
This commit is contained in:
parent
2a49ed80d1
commit
7abdc336b7
@ -5,6 +5,7 @@ entcms - 企业CMS系统模块
|
||||
import json
|
||||
from ahserver.serverenv import ServerEnv
|
||||
from appPublic.uniqueID import getID
|
||||
from sqlor.dbpools import DBPools
|
||||
|
||||
MODULE_NAME = "entcms"
|
||||
MODULE_VERSION = "1.0.0"
|
||||
@ -12,152 +13,165 @@ MODULE_VERSION = "1.0.0"
|
||||
DBNAME = "entcms"
|
||||
|
||||
|
||||
def _get_db():
|
||||
"""获取数据库上下文"""
|
||||
from sqlor.dbpools import DBPools
|
||||
return DBPools().sqlorContext(DBNAME)
|
||||
|
||||
|
||||
# ===== CMS Content CRUD =====
|
||||
async def cms_content_list(ns=None):
|
||||
"""查询内容列表"""
|
||||
sor = _get_db()
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc, created_at desc')
|
||||
rows = await sor.R('cms_content', ns)
|
||||
total = len(rows)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc, created_at desc')
|
||||
rows = await sor.R('cms_content', ns)
|
||||
total = len(rows)
|
||||
return {'rows': rows, 'total': total}
|
||||
|
||||
|
||||
async def cms_content_create(data):
|
||||
"""创建内容"""
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_content', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_content', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_content_update(data):
|
||||
"""更新内容"""
|
||||
sor = _get_db()
|
||||
await sor.U('cms_content', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.U('cms_content', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_content_delete(data):
|
||||
"""删除内容"""
|
||||
sor = _get_db()
|
||||
await sor.D('cms_content', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.D('cms_content', data)
|
||||
return data
|
||||
|
||||
|
||||
# ===== CMS Categories CRUD =====
|
||||
async def cms_categories_list(ns=None):
|
||||
"""查询分类列表"""
|
||||
sor = _get_db()
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc')
|
||||
rows = await sor.R('cms_categories', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc')
|
||||
rows = await sor.R('cms_categories', ns)
|
||||
return {'rows': rows, 'total': len(rows)}
|
||||
|
||||
|
||||
async def cms_categories_create(data):
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_categories', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_categories', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_categories_update(data):
|
||||
sor = _get_db()
|
||||
await sor.U('cms_categories', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.U('cms_categories', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_categories_delete(data):
|
||||
sor = _get_db()
|
||||
await sor.D('cms_categories', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.D('cms_categories', data)
|
||||
return data
|
||||
|
||||
|
||||
async def get_category_options(content_type=None):
|
||||
"""获取分类下拉选项"""
|
||||
sor = _get_db()
|
||||
ns = {'sort': 'sort_order asc'}
|
||||
if content_type:
|
||||
ns['content_type'] = content_type
|
||||
rows = await sor.R('cms_categories', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'sort': 'sort_order asc'}
|
||||
if content_type:
|
||||
ns['content_type'] = content_type
|
||||
rows = await sor.R('cms_categories', ns)
|
||||
options = [{'value': r['id'], 'text': r['name']} for r in rows]
|
||||
return options
|
||||
|
||||
|
||||
# ===== CMS Leads CRUD =====
|
||||
async def cms_leads_list(ns=None):
|
||||
sor = _get_db()
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'created_at desc')
|
||||
rows = await sor.R('cms_leads', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'created_at desc')
|
||||
rows = await sor.R('cms_leads', ns)
|
||||
return {'rows': rows, 'total': len(rows)}
|
||||
|
||||
|
||||
async def cms_leads_create(data):
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_leads', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_leads', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_leads_update(data):
|
||||
sor = _get_db()
|
||||
await sor.U('cms_leads', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.U('cms_leads', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_leads_delete(data):
|
||||
sor = _get_db()
|
||||
await sor.D('cms_leads', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.D('cms_leads', data)
|
||||
return data
|
||||
|
||||
|
||||
async def submit_lead(data):
|
||||
"""公开接口 - 网站访客提交线索"""
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
data.setdefault('status', 'new')
|
||||
data.setdefault('source', 'website')
|
||||
await sor.C('cms_leads', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
data.setdefault('status', 'new')
|
||||
data.setdefault('source', 'website')
|
||||
await sor.C('cms_leads', data)
|
||||
return {'status': 'ok', 'id': data['id']}
|
||||
|
||||
|
||||
# ===== CMS Sections CRUD =====
|
||||
async def cms_sections_list(ns=None):
|
||||
sor = _get_db()
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc')
|
||||
rows = await sor.R('cms_sections', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'sort_order asc')
|
||||
rows = await sor.R('cms_sections', ns)
|
||||
return {'rows': rows, 'total': len(rows)}
|
||||
|
||||
async def cms_sections_create(data):
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_sections', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_sections', data)
|
||||
return data
|
||||
|
||||
async def cms_sections_update(data):
|
||||
sor = _get_db()
|
||||
await sor.U('cms_sections', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.U('cms_sections', data)
|
||||
return data
|
||||
|
||||
async def cms_sections_delete(data):
|
||||
sor = _get_db()
|
||||
await sor.D('cms_sections', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.D('cms_sections', data)
|
||||
return data
|
||||
|
||||
async def get_visible_sections():
|
||||
"""获取所有可见栏目(公开接口)"""
|
||||
sor = _get_db()
|
||||
ns = {'is_visible': '1', 'sort': 'sort_order asc'}
|
||||
rows = await sor.R('cms_sections', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'is_visible': '1', 'sort': 'sort_order asc'}
|
||||
rows = await sor.R('cms_sections', ns)
|
||||
import json as _json
|
||||
for r in rows:
|
||||
for field in ['display_config', 'style_config', 'static_content']:
|
||||
@ -169,39 +183,44 @@ async def get_visible_sections():
|
||||
|
||||
# ===== CMS Site Config CRUD =====
|
||||
async def cms_site_config_list(ns=None):
|
||||
sor = _get_db()
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'config_group asc, sort_order asc')
|
||||
rows = await sor.R('cms_site_config', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = ns or {}
|
||||
ns.setdefault('sort', 'config_group asc, sort_order asc')
|
||||
rows = await sor.R('cms_site_config', ns)
|
||||
return {'rows': rows, 'total': len(rows)}
|
||||
|
||||
|
||||
async def cms_site_config_create(data):
|
||||
sor = _get_db()
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_site_config', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
data['id'] = getID()
|
||||
await sor.C('cms_site_config', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_site_config_update(data):
|
||||
sor = _get_db()
|
||||
await sor.U('cms_site_config', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.U('cms_site_config', data)
|
||||
return data
|
||||
|
||||
|
||||
async def cms_site_config_delete(data):
|
||||
sor = _get_db()
|
||||
await sor.D('cms_site_config', data)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
await sor.D('cms_site_config', data)
|
||||
return data
|
||||
|
||||
|
||||
async def get_site_config(group=None):
|
||||
"""获取站点配置(公开接口)"""
|
||||
sor = _get_db()
|
||||
ns = {'sort': 'sort_order asc'}
|
||||
if group:
|
||||
ns['config_group'] = group
|
||||
rows = await sor.R('cms_site_config', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'sort': 'sort_order asc'}
|
||||
if group:
|
||||
ns['config_group'] = group
|
||||
rows = await sor.R('cms_site_config', ns)
|
||||
result = {}
|
||||
for r in rows:
|
||||
g = r.get('config_group', '')
|
||||
@ -214,11 +233,12 @@ async def get_site_config(group=None):
|
||||
# ===== Public Content APIs =====
|
||||
async def get_published_content(content_type=None, limit=10):
|
||||
"""获取已发布内容(公开接口)"""
|
||||
sor = _get_db()
|
||||
ns = {'status': 'published', 'sort': 'sort_order asc, published_at desc'}
|
||||
if content_type:
|
||||
ns['content_type'] = content_type
|
||||
rows = await sor.R('cms_content', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'status': 'published', 'sort': 'sort_order asc, published_at desc'}
|
||||
if content_type:
|
||||
ns['content_type'] = content_type
|
||||
rows = await sor.R('cms_content', ns)
|
||||
if limit:
|
||||
rows = rows[:limit]
|
||||
return rows
|
||||
@ -226,36 +246,39 @@ async def get_published_content(content_type=None, limit=10):
|
||||
|
||||
async def get_latest_news(limit=2):
|
||||
"""获取最新新闻(公开接口)"""
|
||||
sor = _get_db()
|
||||
ns = {'status': 'published', 'content_type': 'news', 'sort': 'published_at desc'}
|
||||
rows = await sor.R('cms_content', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'status': 'published', 'content_type': 'news', 'sort': 'published_at desc'}
|
||||
rows = await sor.R('cms_content', ns)
|
||||
return rows[:limit]
|
||||
|
||||
|
||||
async def get_content_detail(content_id):
|
||||
"""获取内容详情(公开接口)"""
|
||||
sor = _get_db()
|
||||
ns = {'id': content_id, 'status': 'published'}
|
||||
rows = await sor.R('cms_content', ns)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
ns = {'id': content_id, 'status': 'published'}
|
||||
rows = await sor.R('cms_content', ns)
|
||||
return rows[0] if rows else None
|
||||
|
||||
|
||||
# ===== Submit for approval =====
|
||||
async def submit_content_for_approval(content_id, title, applicant_id):
|
||||
"""提交内容审批(调用dingdingflow)"""
|
||||
# 更新内容状态为pending
|
||||
sor = _get_db()
|
||||
await sor.U('cms_content', {'id': content_id, 'status': 'pending'})
|
||||
# 调用dingdingflow的submit_approval
|
||||
try:
|
||||
from dingdingflow.init import submit_approval
|
||||
result = await submit_approval('content_publish', content_id, title, applicant_id)
|
||||
# 保存审批ID
|
||||
if result and result.get('approval_id'):
|
||||
await sor.U('cms_content', {'id': content_id, 'approval_id': result['approval_id']})
|
||||
return result
|
||||
except ImportError:
|
||||
return {'status': 'error', 'message': 'dingdingflow模块未安装'}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
# 更新内容状态为pending
|
||||
await sor.U('cms_content', {'id': content_id, 'status': 'pending'})
|
||||
# 调用dingdingflow的submit_approval
|
||||
try:
|
||||
from dingdingflow.init import submit_approval
|
||||
result = await submit_approval('content_publish', content_id, title, applicant_id)
|
||||
# 保存审批ID
|
||||
if result and result.get('approval_id'):
|
||||
await sor.U('cms_content', {'id': content_id, 'approval_id': result['approval_id']})
|
||||
return result
|
||||
except ImportError:
|
||||
return {'status': 'error', 'message': 'dingdingflow模块未安装'}
|
||||
|
||||
|
||||
def load_entcms():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user