diff --git a/b/account/email_info.dspy b/b/account/email_info.dspy index af6b3eb..c4a6e4b 100644 --- a/b/account/email_info.dspy +++ b/b/account/email_info.dspy @@ -90,7 +90,7 @@ async def email_info(msg, indent=0): index = find_data.index("<") name = find_data[:index] if price and name: - mail_code_sql = """SELECT * FROM mail_code WHERE LOCATE(mailcode, name) > 0 and 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) diff --git a/b/baiduc/baidu_confirm_auto_renew_order.dspy b/b/baiduc/baidu_confirm_auto_renew_order.dspy index dfac1a8..518af55 100644 --- a/b/baiduc/baidu_confirm_auto_renew_order.dspy +++ b/b/baiduc/baidu_confirm_auto_renew_order.dspy @@ -720,11 +720,13 @@ async def baidu_confirm_auto_renew_order(ns={}): # 读取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: @@ -746,7 +748,6 @@ async def baidu_confirm_auto_renew_order(ns={}): 'renew_status_count': renew_status_count, 'update_msg': update_msg, } - } ret = await baidu_confirm_auto_renew_order(params_kw) diff --git a/b/product/get_firstpage_net_detail.dspy b/b/product/get_firstpage_net_detail.dspy index 77987ca..4e9f9fa 100644 --- a/b/product/get_firstpage_net_detail.dspy +++ b/b/product/get_firstpage_net_detail.dspy @@ -875,53 +875,6 @@ detailDataLJS = { } ], "products": [ - { - "title": "NVIDIA-4090", - "description": "配备GPU的云端服务器,可以为机器学习、高性能计算、图形图像渲染等计算密集型应用提供加速处理能力。根据需求场景的不同,既可提供弹性的GPU云服务器,也可提供高性能的GPU裸金属服务器,助力您的业务创新,提升竞争优势。", - "price": "6000", - "pre_price": "7143", - "price_unit": "台/月", - "discount": 8.4, - "bgImgUrl": "https://www.kaiyuancloud.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" - } - ] - }, { "title": "NVIDIA-4090", "description": "轻量应用服务器(Light server)是一种内置应用型镜像或系统型镜像的小规格云服务器, 绑定适配大小的磁盘和带宽,为中小型企业和个人用户提供官网搭建、web应用搭建、云上学习和测试等场景的服务。", diff --git a/b/product/homepage_category_tree_delete.dspy b/b/product/homepage_category_tree_delete.dspy new file mode 100644 index 0000000..8b16a94 --- /dev/null +++ b/b/product/homepage_category_tree_delete.dspy @@ -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 \ No newline at end of file diff --git a/b/product/homepage_product_category.dspy b/b/product/homepage_product_category.dspy new file mode 100644 index 0000000..8a01b8c --- /dev/null +++ b/b/product/homepage_product_category.dspy @@ -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 \ No newline at end of file diff --git a/b/product/publish_product_add.dspy b/b/product/publish_product_add.dspy index 4427aef..60a53d2 100644 --- a/b/product/publish_product_add.dspy +++ b/b/product/publish_product_add.dspy @@ -91,6 +91,7 @@ async def publish_product_add(ns={}): if 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) diff --git a/b/product/publish_product_search.dspy b/b/product/publish_product_search.dspy index 5da93e8..2deb96d 100644 --- a/b/product/publish_product_search.dspy +++ b/b/product/publish_product_search.dspy @@ -1,3 +1,121 @@ +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 @@ -36,6 +154,8 @@ async def publish_product_search(ns={}): """ offset = ns.get('offset') manager_self = ns.get('manager_self') + to_excel = ns.get('to_excel') + if ns.get('userid'): userid = ns.get('userid') @@ -46,6 +166,12 @@ async def publish_product_search(ns={}): '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: @@ -141,17 +267,34 @@ async def publish_product_search(ns={}): res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img'] else: res['img'] = None - 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 + + # 读取产品类别表 轮询匹配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, diff --git a/b/product/publish_product_search_detail.dspy b/b/product/publish_product_search_detail.dspy index c212b01..9db7072 100644 --- a/b/product/publish_product_search_detail.dspy +++ b/b/product/publish_product_search_detail.dspy @@ -23,6 +23,57 @@ async def get_user_role(ns={}): return role +async def user_browse_history_add(ns={}): + # ns = { + # 'userid': '9KVhsVCJsW_29q3hRhMAr', # 用户ID + # 'product_id': 'p2s2YPPU7uquza3gGw9k2', # 产品ID + # 'ip_address': '192.168.1.1', # IP地址 + # 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102' # 用户代理 + # } + # 必要参数校验 + if not ns.get('userid') or not ns.get('product_id'): + return { + 'status': False, + 'msg': 'userid and product_id 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 product_id = '%s' AND del_flg = '0' AND browse_time >= '%s'; + """ % (ns.get('userid'), ns.get('product_id'), browse_time) + check_result = await sor.sqlExe(check_sql, {}) + if check_result: + return { + 'status': False, + 'msg': 'The user has browsed this product within the last 10 hours' + } + + # 生成记录ID + record_id = uuid() + # 插入浏览记录 + insert_sql = """ + INSERT INTO user_browse_history ( + id, userid, product_id, ip_address, user_agent, del_flg + ) VALUES ('%s', '%s', '%s', '%s', '%s', '0'); + """ % (record_id, ns.get('userid'), ns.get('product_id'), + ns.get('ip_address', ''), ns.get('user_agent', '')) + 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: @@ -36,6 +87,7 @@ async def publish_product_search_detail(ns={}): db = DBPools() async with db.sqlorContext('kboss') as sor: user_role = None + orgid = None # 区分运营和普通客户 if userid: user_list = await sor.R('users', {'id': userid}) @@ -44,8 +96,12 @@ async def publish_product_search_detail(ns={}): # 如果用户角色是运营并且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'): @@ -57,6 +113,10 @@ async def publish_product_search_detail(ns={}): else: product['email'] = 'kawa@****.com' + # 保存浏览记录 + if userid: + await user_browse_history_add({'userid': userid, 'product_id': ns.get('id')}) + return { 'status': True, 'msg': 'Product retrieved successfully', diff --git a/b/product/publish_product_search_first_page.dspy b/b/product/publish_product_search_first_page.dspy index da7477b..cee413d 100644 --- a/b/product/publish_product_search_first_page.dspy +++ b/b/product/publish_product_search_first_page.dspy @@ -20,8 +20,12 @@ async def publish_product_search_first_page(ns={}): async with db.sqlorContext('kboss') as sor: try: ns['del_flg'] = '0' - if 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 del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % (domain_name, publish_type) + # 如果是首页并且有产品分类 + 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 del_flg = '0' AND publish_type = '%s' ORDER BY create_at DESC;""" % publish_type diff --git a/b/product/publish_product_update.dspy b/b/product/publish_product_update.dspy index 3c397b3..e824e5a 100644 --- a/b/product/publish_product_update.dspy +++ b/b/product/publish_product_update.dspy @@ -68,10 +68,11 @@ async def publish_product_update(ns={}): # 非客户角色编辑客户的产品 if 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') diff --git a/b/product/search_user_inquiry.dspy b/b/product/search_user_inquiry.dspy index 1dae62e..906e50e 100644 --- a/b/product/search_user_inquiry.dspy +++ b/b/product/search_user_inquiry.dspy @@ -12,6 +12,42 @@ async def search_user_inquiry(ns={}): async with db.sqlorContext('kboss') as sor: 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', diff --git a/b/user/enterprise_audit_info_search.dspy b/b/user/enterprise_audit_info_search.dspy index 3bc5eb1..6294bb7 100644 --- a/b/user/enterprise_audit_info_search.dspy +++ b/b/user/enterprise_audit_info_search.dspy @@ -29,6 +29,14 @@ async def enterprise_audit_info_search(ns={}): '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' @@ -50,10 +58,36 @@ async def enterprise_audit_info_search(ns={}): user_role = await get_user_role({'userid': userid, 'sor': sor}) try: if 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关联查询 - 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;""" % orgid - # 执行查询 + 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, {}) # 处理结果中的图片路径 增加前缀 @@ -66,7 +100,12 @@ async def enterprise_audit_info_search(ns={}): return { 'status': True, 'msg': 'enterprise audit info search successfully', - 'data': res + 'data': { + 'total_count': total_count, + 'current_page': current_page, + 'page_size': page_size, + 'data': res + } } except Exception as e: return { diff --git a/b/user/user_browse_history_add.dspy b/b/user/user_browse_history_add.dspy new file mode 100644 index 0000000..bbdd7b0 --- /dev/null +++ b/b/user/user_browse_history_add.dspy @@ -0,0 +1,53 @@ +async def user_browse_history_add(ns={}): + # ns = { + # 'userid': '9KVhsVCJsW_29q3hRhMAr', # 用户ID + # 'product_id': 'p2s2YPPU7uquza3gGw9k2', # 产品ID + # 'ip_address': '192.168.1.1', # IP地址 + # 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102' # 用户代理 + # } + # 必要参数校验 + if not ns.get('userid') or not ns.get('product_id'): + return { + 'status': False, + 'msg': 'userid and product_id 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 product_id = '%s' AND del_flg = '0' AND browse_time >= '%s'; + """ % (ns.get('userid'), ns.get('product_id'), browse_time) + check_result = await sor.sqlExe(check_sql, {}) + if check_result: + return { + 'status': False, + 'msg': 'The user has browsed this product within the last 10 hours' + } + + # 生成记录ID + record_id = uuid() + # 插入浏览记录 + insert_sql = """ + INSERT INTO user_browse_history ( + id, userid, product_id, ip_address, user_agent, del_flg + ) VALUES ('%s', '%s', '%s', '%s', '%s', '0'); + """ % (record_id, ns.get('userid'), ns.get('product_id'), + ns.get('ip_address', ''), ns.get('user_agent', '')) + 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 \ No newline at end of file diff --git a/b/user/user_browse_history_delete.dspy b/b/user/user_browse_history_delete.dspy new file mode 100644 index 0000000..7439659 --- /dev/null +++ b/b/user/user_browse_history_delete.dspy @@ -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 \ No newline at end of file diff --git a/b/user/user_browse_history_search.dspy b/b/user/user_browse_history_search.dspy new file mode 100644 index 0000000..9df8083 --- /dev/null +++ b/b/user/user_browse_history_search.dspy @@ -0,0 +1,72 @@ +async def user_browse_history_search(ns={}): + # 处理userid + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + if not userid: + return { + 'status': False, + 'msg': 'no match user' + } + + # 参数处理 + product_id = ns.get('product_id') + start_time = ns.get('start_time') + end_time = ns.get('end_time') + page_size = int(ns.get('page_size', 10)) + 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 product_id: + base_conditions.append(f"product_id = '{product_id}'") + 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) + + # 根据product_id查询product_info + + 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'] + + 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 \ No newline at end of file diff --git a/f/web-kboss/BINARY_IMAGE_UPLOAD_FIX.md b/f/web-kboss/BINARY_IMAGE_UPLOAD_FIX.md new file mode 100644 index 0000000..e69de29 diff --git a/f/web-kboss/CHANGES_AFTER_PREVIEW_REMOVAL.md b/f/web-kboss/CHANGES_AFTER_PREVIEW_REMOVAL.md new file mode 100644 index 0000000..e69de29 diff --git a/f/web-kboss/README_IMAGE_OPTIMIZATION.md b/f/web-kboss/README_IMAGE_OPTIMIZATION.md new file mode 100644 index 0000000..e69de29 diff --git a/f/web-kboss/src/api/ncmatch/index.js b/f/web-kboss/src/api/ncmatch/index.js index 19360c6..0143f65 100644 --- a/f/web-kboss/src/api/ncmatch/index.js +++ b/f/web-kboss/src/api/ncmatch/index.js @@ -125,3 +125,61 @@ export function reqExportProduct(data){ 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 + }) +} diff --git a/f/web-kboss/src/components/FloatingBox/FloatingBox.vue b/f/web-kboss/src/components/FloatingBox/FloatingBox.vue index 2d479f4..a5562d9 100644 --- a/f/web-kboss/src/components/FloatingBox/FloatingBox.vue +++ b/f/web-kboss/src/components/FloatingBox/FloatingBox.vue @@ -24,8 +24,9 @@
+