diff --git a/b/baiduc/baidu_confirm_auto_renew_order.dspy b/b/baiduc/baidu_confirm_auto_renew_order.dspy index e6509ab..0aafc0d 100644 --- a/b/baiduc/baidu_confirm_auto_renew_order.dspy +++ b/b/baiduc/baidu_confirm_auto_renew_order.dspy @@ -802,7 +802,15 @@ async def baidu_confirm_auto_renew_order(ns={}): renew_status = await get_baidu_orderlist({'order_id': order_id, 'userid': user_id}) if renew_status.get('status'): renew_status_count += 1 - + else: + ns_err_log = { + 'id': uuid(), + 'log_level': 'ERROR', + 'log_content': '续费订单 %s 失败 %s' % (order_id, str(renew_status)), + 'user_id': user_id, + 'request_url': '/baiduc/baidu_confirm_auto_renew_order.dspy' + } + await sor.C('warn_error_log', ns_err_log) # 并触发update函数 update_msg = await update_baidu_order_list({'orgid': orgid}) diff --git a/b/baiduc/baidu_confirm_refund_order.dspy b/b/baiduc/baidu_confirm_refund_order.dspy index ed3ad96..46245ca 100644 --- a/b/baiduc/baidu_confirm_refund_order.dspy +++ b/b/baiduc/baidu_confirm_refund_order.dspy @@ -745,11 +745,32 @@ async def update_baidu_order_list(ns={}): } } +async def baidu_orderdetail_by_uuid(ns={}): + order_id = ns.get('order_id') + baidu_id = ns.get('baidu_id') + method = 'POST' + nss = {'uuids': [order_id], 'queryAccountId': 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() + return { + 'status': True, + 'msg': 'get baidu order detail success', + 'data': data_ + } + 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')}) @@ -764,18 +785,21 @@ async def baidu_confirm_refund_order(ns={}): 'msg': '用户 %s 未绑定百度智能云账号' % ns.get('userid') } - orders = json.loads(ns.get('order_id')) if isinstance(ns.get('order_id'), str) else ns.get('order_id') + refund_orders_base_list = json.loads(ns.get('order_id')) if isinstance(ns.get('order_id'), str) else ns.get('order_id') - for order_id in orders: + for order_id in refund_orders_base_list: + with open('baidu_refund_order_id.txt', 'a+') as f: + f.write('%s 当前退订订单ID: %s ' % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), order_id)) + db = DBPools() async with db.sqlorContext('kboss') as sor: 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 + # 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 if not refundstatus: # data_ = {} @@ -787,6 +811,7 @@ async def baidu_confirm_refund_order(ns={}): header = { "Host": "billing.baidubce.com" } + await asyncio.sleep(0.5) header = await get_auth_header(method=method, url=url, header=header) async with aiohttp_client.request( method=method, @@ -807,64 +832,94 @@ async def baidu_confirm_refund_order(ns={}): 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')}) + with open('baidu_refund_order_id.txt', 'a+') as f: + f.write('远程退订成功: %s \n' % str(data_)) 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] - } + } + with open('baidu_refund_order_id.txt', 'a+') as f: + f.write('远程退订失败: %s ' % str(data_)) + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + await asyncio.sleep(3) + order_status_dict = await baidu_orderdetail_by_uuid({'order_id': order_id, 'baidu_id': ns.get('baidu_id')}) + if order_status_dict.get('data') and order_status_dict['data'].get('orders') and order_status_dict['data']['orders'][0]['status'] == 'NEED_CONFIRM': + await user_action_record(ns_record) + # 从列表中移除该订单ID + refund_orders_base_list.remove(order_id) + ns_err_log = { + 'id': uuid(), + 'log_level': 'ERROR', + 'log_content': '检测到 产品仍在使用中 暂时不退费, 订单详情 %s' % str(order_status_dict['data']), + 'user_id': ns.get('userid'), + 'request_url': '/baiduc//baidu_confirm_refund_order.dspy', + 'request_params': json.dumps({'order_id': order_id, 'baidu_id': ns.get('baidu_id')}), + } + await sor.C('warn_error_log', ns_err_log) + with open('baidu_refund_order_id.txt', 'a+') as f: + f.write('检测到 产品仍在使用中 暂时不退费 %s \n' % str(order_status_dict['data'])) + else: + ns_record['reason'] = '远程退款失败, 产品已释放, 订单状态 %s, 正常退费' % order_status_dict['data']['orders'][0]['status'] + await user_action_record(ns_record) + with open('baidu_refund_order_id.txt', 'a+') as f: + f.write('检测到 产品已释放,订单状态 %s, 继续进入退费程序 \n' % order_status_dict['data']['orders'][0]['status']) if refundstatus == '2': """ 退款状态为2, 说明退款成功, 无需继续处理 """ + refund_orders_base_list.remove(order_id) continue - + + # 分割 + # 增加延迟 + await asyncio.sleep(5) + + # 把 NEED_CONFIRM的本地库改为CREATED + await update_baidu_order_list({'userid': ns.get('userid')}) + + + for order_id in refund_orders_base_list: # 获取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: + refund_status_li = await sor.R('baidu_orders', {'orderid': order_id}) + refundstatus = refund_status_li[0]['refundstatus'] + refund_id = refund_status_li[0]['id'] 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': '远程退款成功, 本地客户退款成功'}) + 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 + await sor.U('user_action', {'id': ns_record_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': '百度云退款成功,本机构给客户退款出错!, %s' % str(local_refund_status) + ns_err_log = { + 'id': uuid(), + 'log_level': 'ERROR', + 'log_content': '远程退款成功,本地退款失败 %s' % str(local_refund_status), + 'user_id': ns.get('userid'), + 'request_url': '/baiduc//baidu_confirm_refund_order.dspy', + 'request_params': json.dumps({'order_id': order_id, 'baidu_id': ns.get('baidu_id')}), } + await sor.C('warn_error_log', ns_err_log) + + ns_record = { + 'orderid': order_id, + 'ordertype': 'REFUND', + 'userid': ns.get('userid'), + 'reason': '远程退款成功,本地退款失败, %s' % str(local_refund_status) + } + await user_action_record(ns_record) + continue return { 'status': True, diff --git a/b/baiduc/get_orderdetail_by_uuid.dspy b/b/baiduc/get_orderdetail_by_uuid.dspy new file mode 100644 index 0000000..4e8387b --- /dev/null +++ b/b/baiduc/get_orderdetail_by_uuid.dspy @@ -0,0 +1,97 @@ +AK = 'ALTAKPk92fX9cgGDax83yNL8mP' +SK = '9b16b8efd4dc463d8bbd5462db1db8a5' + +async def get_auth_header(method: str, url: str, header: dict, query={}, get_res=False): + import urllib + import hmac + # 解析uri + url_parse = urllib.parse.urlparse(url) + uri = url_parse.path + url_query = url_parse.query + + # 获取query + if url_query: + query = dict(urllib.parse.parse_qsl(url_query)) + + # 2.x-bce-date + x_bce_date = time.gmtime() + x_bce_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', x_bce_date) + + # 4.认证字符串前缀 + authStringPrefix = "bce-auth-v1" + "/" + AK + "/" + x_bce_date + "/" + "1800" + + # windows下为urllib.parse.quote,Linux下为urllib.quote + # 5.生成CanonicalRequest + # 5.1生成CanonicalURI + CanonicalURI = urllib.parse.quote(uri) + + # 如果您调用的接口的query比较复杂的话,需要做额外处理 + # 5.2生成CanonicalQueryString + # CanonicalQueryString = query + result = ['%s=%s' % (k, urllib.parse.quote(str(v))) for k, v in query.items() if k.lower != 'authorization'] + result.sort() + CanonicalQueryString = '&'.join(result) + + # 5.3生成CanonicalHeaders + result = [] + signedHeaders_list = [] + for key,value in header.items(): + tempStr = str(urllib.parse.quote(key.lower(),safe="")) + ":" + str(urllib.parse.quote(value,safe="")) + signedHeaders_list.append(str(urllib.parse.quote(key.lower(),safe=""))) + result.append(tempStr) + result.sort() + signedHeaders = ';'.join(sorted(signedHeaders_list)) + CanonicalHeaders = "\n".join(result) + + # 5.4拼接得到CanonicalRequest + CanonicalRequest = method + "\n" + CanonicalURI + "\n" + CanonicalQueryString +"\n" + CanonicalHeaders + + # 6.生成signingKey + signingKey = hmac.new(SK.encode('utf-8'), authStringPrefix.encode('utf-8'), hashlib.sha256) + + # 7.生成Signature + Signature = hmac.new((signingKey.hexdigest()).encode('utf-8'), CanonicalRequest.encode('utf-8'), hashlib.sha256) + + # 8.生成Authorization并放到header里 + header['Authorization'] = authStringPrefix + "/" + signedHeaders + "/" + Signature.hexdigest() + + if get_res: + # 异步请求链接 返回结果 + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + allow_redirects=True, + json=query) as res: + return res + else: + return header + + +async def get_orderdetail_by_uuid(ns={}): + order_id = ns.get('order_id') + baidu_id = ns.get('baidu_id') + method = 'POST' + nss = {'uuids': [order_id], 'queryAccountId': 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() + return { + 'status': True, + 'msg': 'get baidu order detail success', + 'data': data_ + } + +ret = await get_orderdetail_by_uuid(params_kw) +return ret \ No newline at end of file diff --git a/b/baiducloud/get_baidu_orderlist.dspy b/b/baiducloud/get_baidu_orderlist.dspy index b78e862..5f9e2d0 100644 --- a/b/baiducloud/get_baidu_orderlist.dspy +++ b/b/baiducloud/get_baidu_orderlist.dspy @@ -84,6 +84,10 @@ async def affirmbz_order(ns={}): # 处理购买逻辑 else: + if j.get('chargemode') == 'postpay' and j.get('orderkey') == 'snapshot': + # 快照后付费不创建客户产品记录 + continue + product = await sor.R('product', {'id': j['productid']}) nss = {} nss['id'] = uuid() diff --git a/b/product/get_firstpage_product_tree.dspy b/b/product/get_firstpage_product_tree.dspy index 88d0d49..53cdfeb 100644 --- a/b/product/get_firstpage_product_tree.dspy +++ b/b/product/get_firstpage_product_tree.dspy @@ -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': '一体机-昆仑芯'}, diff --git a/b/product/get_resource_expire_time.dspy b/b/product/get_resource_expire_time.dspy index 9ccf878..c758560 100644 --- a/b/product/get_resource_expire_time.dspy +++ b/b/product/get_resource_expire_time.dspy @@ -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['shortId'], - '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) diff --git a/b/product/home_page_content_add.dspy b/b/product/home_page_content_add.dspy new file mode 100644 index 0000000..c3e3e5a --- /dev/null +++ b/b/product/home_page_content_add.dspy @@ -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 \ No newline at end of file diff --git a/b/product/home_page_content_delete.dspy b/b/product/home_page_content_delete.dspy new file mode 100644 index 0000000..bcc16e8 --- /dev/null +++ b/b/product/home_page_content_delete.dspy @@ -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 \ No newline at end of file diff --git a/b/product/home_page_content_get_tree.dspy b/b/product/home_page_content_get_tree.dspy new file mode 100644 index 0000000..a45cf09 --- /dev/null +++ b/b/product/home_page_content_get_tree.dspy @@ -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 \ No newline at end of file diff --git a/b/product/home_page_content_search.dspy b/b/product/home_page_content_search.dspy new file mode 100644 index 0000000..40b87e5 --- /dev/null +++ b/b/product/home_page_content_search.dspy @@ -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 \ No newline at end of file diff --git a/b/product/home_page_content_update.dspy b/b/product/home_page_content_update.dspy new file mode 100644 index 0000000..ebd5f6a --- /dev/null +++ b/b/product/home_page_content_update.dspy @@ -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 \ No newline at end of file diff --git a/b/product/home_page_product_menu_add.dspy b/b/product/home_page_product_menu_add.dspy index 677eab5..8ba3e07 100644 --- a/b/product/home_page_product_menu_add.dspy +++ b/b/product/home_page_product_menu_add.dspy @@ -13,13 +13,13 @@ async def home_page_product_menu_add(ns={}): # 验证必填字段 - if not ns_dic.get('menu_level') or not ns_dic.get('title'): - return { - 'status': False, - 'msg': 'menu_level and title are required' - } + # if not ns_dic.get('menu_level') or not ns_dic.get('title'): + # return { + # 'status': False, + # 'msg': 'menu_level and title are required' + # } - if ns.get('menu_level') > 1 and not ns.get('parent_id'): + 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' diff --git a/b/product/home_page_product_menu_search.dspy b/b/product/home_page_product_menu_search.dspy index 7ed8f08..af946c7 100644 --- a/b/product/home_page_product_menu_search.dspy +++ b/b/product/home_page_product_menu_search.dspy @@ -165,7 +165,7 @@ async def build_menu_tree(menu_list, target_level=None, target_title=None): """ # 通过sort_order对菜单进行排序 - menu_list.sort(key=lambda x: x['sort_order'], reverse=True) + menu_list.sort(key=lambda x: int(x['sort_order']), reverse=False) menu_dict = {} result = [] diff --git a/b/product/home_page_product_menu_update.dspy b/b/product/home_page_product_menu_update.dspy index 893413d..0f853f5 100644 --- a/b/product/home_page_product_menu_update.dspy +++ b/b/product/home_page_product_menu_update.dspy @@ -14,12 +14,12 @@ async def home_page_product_menu_update(ns={}): ns_dic = {'id': ns.get('id')} if ns.get('title'): ns_dic['title'] = ns.get('title') - if ns.get('parent_id') is not None: + 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') is not None: - ns_dic['sort_order'] = ns.get('sort_order') + if ns.get('sort_order'): + ns_dic['sort_order'] = int(ns.get('sort_order')) db = DBPools() async with db.sqlorContext('kboss') as sor: diff --git a/b/product/home_page_product_update.dspy b/b/product/home_page_product_update.dspy index cda43a5..118016f 100644 --- a/b/product/home_page_product_update.dspy +++ b/b/product/home_page_product_update.dspy @@ -14,21 +14,21 @@ async def home_page_product_update(ns={}): ns_dic = {'id': ns.get('id')} if ns.get('name'): ns_dic['name'] = ns.get('name') - if ns.get('description') is not None: + if ns.get('description'): ns_dic['description'] = ns.get('description') - if ns.get('label') is not None: + if ns.get('label'): ns_dic['label'] = ns.get('label') - if ns.get('product_group') is not None: + if ns.get('product_group'): ns_dic['product_group'] = ns.get('product_group') - if ns.get('url') is not None: + if ns.get('url'): ns_dic['url'] = ns.get('url') - if ns.get('list_url') is not None: + if ns.get('list_url'): ns_dic['list_url'] = ns.get('list_url') - if ns.get('icon_url') is not None: + if ns.get('icon_url'): ns_dic['icon_url'] = ns.get('icon_url') - if ns.get('source') is not None: + if ns.get('source'): ns_dic['source'] = ns.get('source') - if ns.get('sort_order') is not None: + 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') diff --git a/f/web-kboss/src - 快捷方式.lnk b/f/web-kboss/src - 快捷方式.lnk deleted file mode 100644 index a0203e4..0000000 Binary files a/f/web-kboss/src - 快捷方式.lnk and /dev/null differ diff --git a/f/web-kboss/src/api/H5/index.js b/f/web-kboss/src/api/H5/index.js new file mode 100644 index 0000000..6704d81 --- /dev/null +++ b/f/web-kboss/src/api/H5/index.js @@ -0,0 +1,9 @@ +import request from "@/utils/request"; + +export const reqHotProduct = () => { + return request({ + url: '/product/get_firstpage_jizuonet.dspy', + method: 'post', + }) +} + diff --git a/f/web-kboss/src/api/productsServices/index.js b/f/web-kboss/src/api/productsServices/index.js new file mode 100644 index 0000000..074df41 --- /dev/null +++ b/f/web-kboss/src/api/productsServices/index.js @@ -0,0 +1,117 @@ +import request from "@/utils/request"; + +// 菜单添加 +export function addProductMenuAPI(params) { + return request({ + url: `/product/home_page_product_menu_add.dspy`, + method: 'post', + data: params, + }) +} + +// 菜单更新 +export function updateProductMenuAPI(params) { + return request({ + url: `/product/home_page_product_menu_update.dspy`, + method: 'post', + data: params, + }) +} + +// 菜单查找 +export function findProductMenuAPI(params) { + return request({ + url: `/product/home_page_product_menu_search.dspy`, + method: 'get', + data: params, + }) +} + +// 菜单删除 +export function deleteProductMenuAPI(params) { + return request({ + url: `/product/home_page_product_menu_delete.dspy`, + method: 'post', + data: params, + }) +} + +// 产品添加 +export function addProductThreeMenuAPI(params) { + return request({ + url: `/product/home_page_product_add.dspy`, + method: 'post', + data: params, + }) +} + +// 产品列表 +export function findProductThreeMenuAPI(params) { + return request({ + url: `/product/home_page_product_search.dspy`, + method: 'post', + data: params, + }) +} + +// 三级产品更新 +export function updateProductThreeMenuAPI(params) { + return request({ + url: `/product/home_page_product_update.dspy`, + method: 'post', + data: params, + }) +} + +// 三级产品删除 +export function deleteProductThreeMenuAPI(params) { + return request({ + url: `/product/home_page_product_delete.dspy`, + method: 'post', + data: params, + }) +} + +//产品介绍页数据添加 +export function addProductIntroAPI(params) { + return request({ + url: `/product/home_page_content_add.dspy`, + method: 'post', + data: params, + }) +} +// 产品介绍页数据删除 +export function deleteProductIntroAPI(params) { + return request({ + url: `/product/home_page_content_delete.dspy`, + method: 'get', + data: params, + }) +} + +// 产品介绍页数据更新 +export function updateProductIntroAPI(params) { + return request({ + url: `/product/home_page_content_update.dspy`, + method: 'post', + data: params, + }) +} + +// 产品介绍页数据树 +export function findProductIntroAPI(params) { + return request({ + url: `/product/home_page_content_get_tree.dspy`, + method: 'post', + data: params, + }) +} + +// 产品介绍页数据查找 +export function findProductIntroTreeAPI(params) { + return request({ + url: `/product/home_page_content_search.dspy`, + method: 'get', + data: params, + }) +} diff --git a/f/web-kboss/src/router/index.js b/f/web-kboss/src/router/index.js index 214d047..d155c42 100644 --- a/f/web-kboss/src/router/index.js +++ b/f/web-kboss/src/router/index.js @@ -21,7 +21,7 @@ import CreateEip from "@/views/product/productHome/capitalOnline/Net/Eip/createE import { getHomePath } from '@/views/setting/tools' Vue.use(Router); - + /** * Note: sub-menu only appear when route children.length >= 1 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html @@ -80,7 +80,16 @@ export const constantRoutes = [ title: '产品详情', component: () => import('@/views/homePage/wxDetailPage.vue'), hidden: true - }, { + }, + { + path: '/h5HomePage', + name: 'H5HomePage', + title: 'H5首页', + component: () => import('@/views/H5/indexPage/index.vue'), + hidden: true, + }, + + { hidden: true, path: '/screen', name: 'screen', title: '可视化大屏', meta: { title: "可视化大屏", fullPath: "/operation/analyze/screen", }, component: () => import('@/views/product/bigScreen/index.vue'), children: [{ @@ -1156,8 +1165,17 @@ export const asyncRoutes = [ path: "index", component: () => import("@/views/operation/menuMangement/index.vue"), name: "menuMangement", - meta: { title: "菜单管理", fullPath: "/menuMangement/index" }, + meta: { title: "ncmatch菜单管理", fullPath: "/menuMangement/index" }, }, + { + path: "productsServices", + component: () => import("@/views/operation/productsServices/index.vue"), + name: "productsServices", + meta: { + title: "产品与服务管理", + fullPath: "/operation/productsServices" + } + } ] }, diff --git a/f/web-kboss/src/store/modules/permission.js b/f/web-kboss/src/store/modules/permission.js index dbbe047..9b9188d 100644 --- a/f/web-kboss/src/store/modules/permission.js +++ b/f/web-kboss/src/store/modules/permission.js @@ -145,6 +145,22 @@ const mutations = { }; const actions = { + /** + * 生成动态路由 + * + * 根据用户类型、组织类型和权限列表生成对应的动态路由配置 + * 包含管理员和普通用户的不同路由生成逻辑 + * + * @param {Object} context - Vuex上下文对象 + * @param {Function} context.commit - 提交mutation的方法 + * @param {Object} context.rootState - 根模块的状态 + * @param {Object} params - 参数对象 + * @param {string} [params.userType] - 用户类型 + * @param {number} [params.orgType] - 组织类型 + * @param {Array} [params.auths] - 权限列表 + * @param {Object} [params.user] - 用户信息对象 + * @returns {Promise} 解析后的动态路由数组 + */ generateRoutes({ commit, rootState }, params) { console.log("ACTION generateRoutes - params:", params); return new Promise((resolve) => { diff --git a/f/web-kboss/src/views/H5/images/banner.png b/f/web-kboss/src/views/H5/images/banner.png new file mode 100644 index 0000000..71ab7f2 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/banner.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img.png b/f/web-kboss/src/views/H5/images/top/img.png new file mode 100644 index 0000000..e54e43a Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_1.png b/f/web-kboss/src/views/H5/images/top/img_1.png new file mode 100644 index 0000000..680851b Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_1.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_2.png b/f/web-kboss/src/views/H5/images/top/img_2.png new file mode 100644 index 0000000..be42375 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_2.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_3.png b/f/web-kboss/src/views/H5/images/top/img_3.png new file mode 100644 index 0000000..061d487 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_3.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_4.png b/f/web-kboss/src/views/H5/images/top/img_4.png new file mode 100644 index 0000000..97d65ca Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_4.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_5.png b/f/web-kboss/src/views/H5/images/top/img_5.png new file mode 100644 index 0000000..93760c9 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_5.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_6.png b/f/web-kboss/src/views/H5/images/top/img_6.png new file mode 100644 index 0000000..434ef87 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_6.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_7.png b/f/web-kboss/src/views/H5/images/top/img_7.png new file mode 100644 index 0000000..b4b3525 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_7.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_8.png b/f/web-kboss/src/views/H5/images/top/img_8.png new file mode 100644 index 0000000..76459a4 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_8.png differ diff --git a/f/web-kboss/src/views/H5/images/top/img_9.png b/f/web-kboss/src/views/H5/images/top/img_9.png new file mode 100644 index 0000000..974b5e0 Binary files /dev/null and b/f/web-kboss/src/views/H5/images/top/img_9.png differ diff --git a/f/web-kboss/src/views/H5/indexPage/index.vue b/f/web-kboss/src/views/H5/indexPage/index.vue new file mode 100644 index 0000000..d5cbe75 --- /dev/null +++ b/f/web-kboss/src/views/H5/indexPage/index.vue @@ -0,0 +1,392 @@ + + + + + diff --git a/f/web-kboss/src/views/customer/orderManagement/index.vue b/f/web-kboss/src/views/customer/orderManagement/index.vue index 3b3d37e..6ac8a14 100644 --- a/f/web-kboss/src/views/customer/orderManagement/index.vue +++ b/f/web-kboss/src/views/customer/orderManagement/index.vue @@ -189,7 +189,7 @@ diff --git a/f/web-kboss/src/views/homePage/mainPage/qqq.vue b/f/web-kboss/src/views/homePage/mainPage/qqq.vue new file mode 100644 index 0000000..e69de29 diff --git a/f/web-kboss/src/views/homePage/ncmatch/index.vue b/f/web-kboss/src/views/homePage/ncmatch/index.vue index ff3a69f..4511b31 100644 --- a/f/web-kboss/src/views/homePage/ncmatch/index.vue +++ b/f/web-kboss/src/views/homePage/ncmatch/index.vue @@ -353,7 +353,7 @@ export default Vue.extend({ color: #1b5bff; } } -/deep/.el-pagination{ +/deep/.el-pagination{ text-align: center !important; } diff --git a/f/web-kboss/src/views/homePage/ncmatch/mainPage/menuAside/index.vue b/f/web-kboss/src/views/homePage/ncmatch/mainPage/menuAside/index.vue index 961e204..2bb30b4 100644 --- a/f/web-kboss/src/views/homePage/ncmatch/mainPage/menuAside/index.vue +++ b/f/web-kboss/src/views/homePage/ncmatch/mainPage/menuAside/index.vue @@ -38,7 +38,7 @@ @mouseenter="selectSecondary(secondary)" @click="handleSecondaryClick(secondary)"> {{ secondary.second_level_name }} - + diff --git a/f/web-kboss/src/views/homePage/ncmatch/supplyAndDemandSquare/index.vue b/f/web-kboss/src/views/homePage/ncmatch/supplyAndDemandSquare/index.vue index f0c76d8..18ddf8f 100644 --- a/f/web-kboss/src/views/homePage/ncmatch/supplyAndDemandSquare/index.vue +++ b/f/web-kboss/src/views/homePage/ncmatch/supplyAndDemandSquare/index.vue @@ -341,10 +341,10 @@ export default { align-items: center; } .banner-box { - height: 700px!important; + height: 600px!important; background: url('./img/tt-banner.png') no-repeat ; width: 100%; - padding-bottom: 200px; + // padding-bottom: 10px; .conter { width: 700px; diff --git a/f/web-kboss/src/views/operation/productsServices/index.vue b/f/web-kboss/src/views/operation/productsServices/index.vue new file mode 100644 index 0000000..fb1f81e --- /dev/null +++ b/f/web-kboss/src/views/operation/productsServices/index.vue @@ -0,0 +1,1963 @@ + + + + diff --git a/f/web-kboss/src/views/operation/productsServices/less/index.css b/f/web-kboss/src/views/operation/productsServices/less/index.css new file mode 100644 index 0000000..4099553 --- /dev/null +++ b/f/web-kboss/src/views/operation/productsServices/less/index.css @@ -0,0 +1,687 @@ +.mianBox { + display: flex; + justify-content: space-between; + min-height: 100vh; + gap: 16px; + padding-bottom: 20px; + padding-bottom: 40px; +} +.left { + width: 30%; + min-width: 320px; + height: 100vh; +} +.left-card { + display: flex; + flex-direction: column; + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); +} +.left-card /deep/ .el-card__body { + padding: 20px; + flex: 1; + height: 100%; +} +.right { + flex: 1; + min-width: 0; +} +.toptit { + font-size: 16px; + font-weight: 600; + color: #303133; + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 1px solid #e4e7ed; +} +.search { + margin-bottom: 20px; +} +.search /deep/ .el-input-group__append { + background-color: #409eff; + border-color: #409eff; +} +.search /deep/ .el-input-group__append .el-button { + color: white; +} +.search /deep/ .el-input-group__append .el-button:hover { + background-color: #66b1ff; +} +.custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding: 6px 8px; + border-radius: 4px; + transition: background-color 0.2s; +} +.custom-tree-node:hover { + background-color: #f5f7fa; +} +.custom-tree-node .el-button { + padding: 4px; + margin-left: 4px; +} +.custom-tree-node .el-button i { + font-size: 12px; +} +.custom-tree-node .el-button:hover { + background-color: rgba(64, 158, 255, 0.1); + border-radius: 50%; +} +.tree-container { + overflow-y: auto; + border: 1px solid #e4e7ed; + border-radius: 6px; + padding: 12px; + background-color: #fafafa; +} +.tree-container /deep/ .el-tree .el-tree-node .el-tree-node__content { + height: 36px; +} +.tree-container /deep/ .el-tree .el-tree-node .el-tree-node__content:hover { + background-color: #f0f7ff; +} +.tree-container /deep/ .el-tree .el-tree-node.is-current > .el-tree-node__content { + background-color: #ecf5ff; + color: #409eff; + font-weight: 500; +} +.add-menu-box { + display: flex; + align-items: center; + justify-content: center; + border: 2px dashed #c0c4cc; + border-radius: 6px; + padding: 12px; + text-align: center; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + margin-top: 20px; + background-color: #fafafa; + color: #606266; +} +.add-menu-box:hover { + border-color: #409eff; + background-color: #f0f7ff; + color: #409eff; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(64, 158, 255, 0.1); +} +.add-menu-box .add-icon { + font-size: 20px; + font-weight: 600; + margin-right: 8px; + line-height: 1; +} +.add-menu-box div { + font-size: 14px; + font-weight: 500; +} +.product-card { + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); + margin-bottom: 20px; +} +.product-card /deep/ .el-card__body { + padding: 24px; +} +.rigtop { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 24px; + flex-wrap: wrap; + gap: 16px; +} +.rigtop-left { + flex: 1; + min-width: 0; +} +.breadcrumb { + margin-top: 8px; +} +.breadcrumb /deep/ .el-breadcrumb__inner { + color: #909399; + font-size: 13px; +} +.breadcrumb /deep/ .el-breadcrumb__inner:hover { + color: #409eff; +} +.breadcrumb /deep/ .el-breadcrumb__separator { + color: #c0c4cc; +} +.current-menu { + font-size: 20px; + font-weight: 600; + color: #303133; + line-height: 1.4; +} +.add-product-btn .el-button { + border-radius: 6px; + padding: 10px 20px; + font-weight: 500; +} +.add-product-btn .el-button i { + margin-right: 4px; +} +.product-table { + margin-bottom: 24px; +} +.product-table /deep/ .el-table { + border-radius: 6px; + overflow: hidden; + border: 1px solid #ebeef5; +} +.product-table /deep/ .el-table th { + background-color: #f5f7fa; + color: #303133; + font-weight: 600; + height: 48px; +} +.product-table /deep/ .el-table td { + padding: 16px 0; +} +.product-table /deep/ .el-table .el-table__row { + cursor: pointer; + transition: background-color 0.2s; +} +.product-table /deep/ .el-table .el-table__row:hover { + background-color: #f5f7fa; +} +.product-table /deep/ .el-table .el-table__row.current-row { + background-color: #ecf5ff; +} +.product-info .product-name { + font-size: 14px; + font-weight: 600; + color: #303133; + margin-bottom: 6px; + line-height: 1.4; +} +.product-info .product-desc { + font-size: 12px; + color: #909399; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} +.product-tags { + display: flex; + flex-wrap: wrap; + gap: 4px; +} +.product-tags .el-tag { + border-radius: 4px; + padding: 0 8px; + height: 24px; + line-height: 22px; + font-size: 12px; +} +.product-tags .el-tag--info { + background-color: #f4f4f5; + border-color: #e9e9eb; + color: #909399; +} +.action-buttons { + display: flex; + gap: 8px; +} +.action-buttons .el-button { + min-width: 60px; + padding: 7px 15px; + border-radius: 4px; + font-size: 12px; +} +.action-buttons .el-button--danger { + background-color: #fef0f0; + border-color: #fbc4c4; + color: #f56c6c; +} +.action-buttons .el-button--danger:hover { + background-color: #f56c6c; + color: white; +} +.pagination { + display: flex; + justify-content: flex-end; + margin-top: 24px; + padding-top: 24px; + border-top: 1px solid #ebeef5; +} +.pagination /deep/ .el-pagination .el-pagination__sizes, +.pagination /deep/ .el-pagination .el-pagination__jump { + margin-left: 16px; +} +.pagination /deep/ .el-pagination .btn-prev, +.pagination /deep/ .el-pagination .btn-next { + border-radius: 4px; + border: 1px solid #d8dce5; +} +.pagination /deep/ .el-pagination .el-pager li { + border-radius: 4px; + border: 1px solid #d8dce5; + margin: 0 4px; +} +.pagination /deep/ .el-pagination .el-pager li.active { + background-color: #409eff; + color: white; + border-color: #409eff; +} +.card-top { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 16px; + border-bottom: 1px solid #e4e7ed; + margin-bottom: 24px; +} +.card-top .top-tit span:first-child { + font-size: 18px; + font-weight: 600; + color: #303133; + display: block; + margin-bottom: 4px; +} +.card-top .top-tit span:last-child { + font-size: 13px; + color: #909399; +} +.card-top .top-btn .el-button { + border-radius: 6px; + padding: 10px 24px; + font-weight: 500; +} +.card-content { + width: 100%; +} +.card-content .content-tab { + width: 100%; +} +.card-content .content-tab .tab-top { + font-size: 15px; + font-weight: 600; + color: #303133; + margin-bottom: 16px; +} +.card-content .content-tab .tab-content { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 24px; +} +.card-content .content-tab .tab-content .tab-item { + padding: 10px 24px; + border-radius: 20px; + background-color: #f5f7fa; + color: #606266; + font-size: 14px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid transparent; +} +.card-content .content-tab .tab-content .tab-item:hover { + background-color: #e4e7ed; + transform: translateY(-1px); +} +.card-content .content-tab .tab-content .tab-item.active { + background-color: #409eff; + color: white; + font-weight: 500; + border-color: #409eff; + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3); +} +.product-detail-card { + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); +} +.product-detail-card /deep/ .el-card__body { + padding: 24px; +} +.product-detail-card .product-basic-info { + padding: 20px; + background-color: #fafafa; + border-radius: 6px; + border: 1px solid #ebeef5; +} +.product-detail-card .product-basic-info /deep/ .el-form-item { + margin-bottom: 20px; +} +.product-detail-card .product-basic-info /deep/ .el-form-item:last-child { + margin-bottom: 0; +} +.product-detail-card .product-basic-info /deep/ .el-form-item .el-form-item__label { + color: #606266; + font-weight: 500; +} +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input .el-input__inner, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-textarea .el-input__inner, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input .el-textarea__inner, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-textarea .el-textarea__inner { + border-radius: 4px; +} +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input .el-input__inner:focus, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-textarea .el-input__inner:focus, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input .el-textarea__inner:focus, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-textarea .el-textarea__inner:focus { + border-color: #409eff; +} +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input-number .el-input-number__decrease, +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input-number .el-input-number__increase { + border-radius: 4px 0 0 4px; +} +.product-detail-card .product-basic-info /deep/ .el-form-item .el-input-number .el-input__inner { + border-radius: 0 4px 4px 0; +} +.product-detail-card .product-detail-content { + margin-top: 16px; +} +.product-detail-card .product-detail-content .editor-container /deep/ .el-textarea .el-textarea__inner { + border-radius: 6px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 14px; + line-height: 1.6; + padding: 16px; + border: 1px solid #dcdfe6; +} +.product-detail-card .product-detail-content .editor-container /deep/ .el-textarea .el-textarea__inner:focus { + border-color: #409eff; + box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); +} +.product-detail-card .product-detail-content .editor-container /deep/ .el-textarea .el-textarea__inner::placeholder { + color: #c0c4cc; +} +.empty-detail { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80px 40px; + text-align: center; +} +.empty-detail .empty-icon { + font-size: 64px; + margin-bottom: 24px; + opacity: 0.3; + animation: float 3s ease-in-out infinite; +} +.empty-detail .empty-text { + color: #909399; + font-size: 16px; + line-height: 1.6; + max-width: 300px; +} + /deep/ .el-dialog { + border-radius: 8px; +} + /deep/ .el-dialog .el-dialog__header { + padding: 20px 24px 10px; + border-bottom: 1px solid #e4e7ed; +} + /deep/ .el-dialog .el-dialog__header .el-dialog__title { + font-size: 18px; + font-weight: 600; + color: #303133; +} + /deep/ .el-dialog .el-dialog__body { + padding: 20px 24px; +} + /deep/ .el-dialog .el-dialog__body .el-form-item { + margin-bottom: 20px; +} + /deep/ .el-dialog .el-dialog__body .el-form-item:last-child { + margin-bottom: 0; +} + /deep/ .el-dialog .el-dialog__footer { + padding: 10px 24px 20px; + border-top: 1px solid #e4e7ed; +} + /deep/ .el-dialog .el-dialog__footer .dialog-footer .el-button { + border-radius: 6px; + padding: 10px 20px; + min-width: 80px; +} + /deep/ .el-dialog .el-dialog__footer .dialog-footer .el-button--primary { + font-weight: 500; +} +@keyframes float { + 0%, + 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} +@media (max-width: 1200px) { + .mianBox { + flex-direction: column; + } + .left, + .right { + width: 100%; + } + .left { + margin-bottom: 16px; + } + .tree-container { + height: 300px; + } +} +.pagination-controls { + width: 100%; + display: flex; + justify-content: center; +} +@media (max-width: 768px) { + .rigtop { + flex-direction: column; + align-items: stretch; + } + .add-product-btn { + align-self: flex-start; + } + .tab-content { + flex-direction: column; + } + .tab-content .tab-item { + width: 100%; + text-align: center; + } + .action-buttons { + flex-direction: column; + gap: 4px; + } +} +.content-form { + padding: 20px; +} +.content-form .el-form-item { + margin-bottom: 20px; +} +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #ebeef5; +} +.section-header h3 { + margin: 0; + font-size: 18px; + color: #303133; +} +.form-list { + margin-top: 20px; +} +.form-item { + padding: 20px; + margin-bottom: 20px; + border: 1px solid #ebeef5; + border-radius: 4px; + background-color: #fafafa; +} +.form-item.main-form-item { + background-color: #f5f7fa; +} +.form-title { + font-size: 16px; + font-weight: bold; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px dashed #ebeef5; + color: #409eff; +} +.form-actions { + text-align: right; + margin-top: 10px; + padding-top: 10px; + border-top: 1px dashed #ebeef5; +} +.form-actions .el-button { + padding: 0 10px; +} +.saved-list { + margin-bottom: 30px; +} +.list-item { + padding: 15px; + margin-bottom: 15px; + border: 1px solid #e4e7ed; + border-radius: 4px; + background-color: #fff; +} +.list-item.main-item { + background-color: #f8f9fa; +} +.list-item .item-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #f0f0f0; +} +.list-item .item-header .item-title { + font-weight: bold; + color: #606266; +} +.list-item .item-content { + display: flex; + align-items: flex-start; +} +.list-item .item-content .item-image { + margin-right: 15px; + flex-shrink: 0; +} +.list-item .item-content .item-details { + flex: 1; +} +.list-item .item-content .item-details div { + margin-bottom: 5px; +} +.list-item .item-content .item-details div strong { + color: #606266; + margin-right: 5px; +} +.detail-section { + margin-top: 15px; + padding-top: 15px; + border-top: 1px dashed #e4e7ed; +} +.detail-list .detail-item { + padding: 10px; + margin-bottom: 10px; + background-color: #fff; + border: 1px solid #f0f0f0; + border-radius: 4px; +} +.detail-list .detail-item .detail-title { + font-weight: bold; + margin-bottom: 8px; + color: #67c23a; +} +.detail-list .detail-item .detail-content { + margin-bottom: 8px; +} +.detail-list .detail-item .detail-content div { + margin-bottom: 3px; +} +.detail-list .detail-item .detail-content div strong { + color: #909399; + margin-right: 5px; +} +.detail-list .detail-item .detail-actions { + text-align: right; +} +.detail-form-section { + margin-top: 15px; + padding: 15px; + background-color: #f9f9f9; + border-radius: 4px; + border: 1px dashed #dcdfe6; +} +.detail-form-item { + margin-bottom: 15px; + padding: 15px; + background-color: #fff; + border-radius: 4px; + border: 1px solid #ebeef5; +} +.add-detail-btn { + text-align: center; + margin-top: 10px; +} +.main-product-form { + padding: 20px; + margin-bottom: 30px; + border: 1px solid #ebeef5; + border-radius: 4px; + background-color: #fafafa; +} +.card-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid #ebeef5; +} +.card-top .top-tit { + display: flex; + flex-direction: column; +} +.card-top .top-tit span:first-child { + font-size: 18px; + font-weight: bold; + margin-bottom: 5px; +} +.card-top .top-tit span:last-child { + font-size: 14px; + color: #409eff; +} +.no-product-selected { + padding: 80px 20px; + text-align: center; +} +.no-product-selected .empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 200px; +} +.product-table /deep/ .el-table__row { + cursor: pointer; +} +.product-table /deep/ .el-table__row:hover { + background-color: #f5f7fa; +} +.product-table /deep/ .el-table__row.current-row { + background-color: #ecf5ff; +} diff --git a/f/web-kboss/src/views/operation/productsServices/less/index.less b/f/web-kboss/src/views/operation/productsServices/less/index.less new file mode 100644 index 0000000..8ba1c6d --- /dev/null +++ b/f/web-kboss/src/views/operation/productsServices/less/index.less @@ -0,0 +1,868 @@ +.mianBox { + display: flex; + justify-content: space-between; + min-height: 100vh; + // min-height: 600px; + gap: 16px; + padding-bottom: 20px; + padding-bottom: 40px; + // box-sizing: border-box +} + +.left { + width: 30%; + min-width: 320px; + height: 100vh; +} + +.left-card { + // height: 100%; + display: flex; + flex-direction: column; + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); + + /deep/ .el-card__body { + padding: 20px; + flex: 1; + height: 100%; + } +} + +.right { + flex: 1; + min-width: 0; // 防止flex溢出 +} + +.toptit { + font-size: 16px; + font-weight: 600; + color: #303133; + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 1px solid #e4e7ed; +} + +.search { + margin-bottom: 20px; + + /deep/ .el-input-group__append { + background-color: #409eff; + border-color: #409eff; + + .el-button { + color: white; + + &:hover { + background-color: #66b1ff; + } + } + } +} + +.custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding: 6px 8px; + border-radius: 4px; + transition: background-color 0.2s; + + &:hover { + background-color: #f5f7fa; + } + + .el-button { + padding: 4px; + margin-left: 4px; + + i { + font-size: 12px; + } + + &:hover { + background-color: rgba(64, 158, 255, 0.1); + border-radius: 50%; + } + } +} + +.tree-container { + // height: 400px; + overflow-y: auto; + border: 1px solid #e4e7ed; + border-radius: 6px; + padding: 12px; + background-color: #fafafa; + + /deep/ .el-tree { + .el-tree-node { + .el-tree-node__content { + height: 36px; + + &:hover { + background-color: #f0f7ff; + } + } + + &.is-current { + > .el-tree-node__content { + background-color: #ecf5ff; + color: #409eff; + font-weight: 500; + } + } + } + } +} + +.add-menu-box { + display: flex; + align-items: center; + justify-content: center; + border: 2px dashed #c0c4cc; + border-radius: 6px; + padding: 12px; + text-align: center; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + margin-top: 20px; + background-color: #fafafa; + color: #606266; + + &:hover { + border-color: #409eff; + background-color: #f0f7ff; + color: #409eff; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(64, 158, 255, 0.1); + } + + .add-icon { + font-size: 20px; + font-weight: 600; + margin-right: 8px; + line-height: 1; + } + + div { + font-size: 14px; + font-weight: 500; + } +} + +// 右侧产品卡片样式 +.product-card { + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); + margin-bottom: 20px; + + /deep/ .el-card__body { + padding: 24px; + } +} + +.rigtop { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 24px; + flex-wrap: wrap; + gap: 16px; +} + +.rigtop-left { + flex: 1; + min-width: 0; +} + +.breadcrumb { + margin-top: 8px; + + /deep/ .el-breadcrumb__inner { + color: #909399; + font-size: 13px; + + &:hover { + color: #409eff; + } + } + + /deep/ .el-breadcrumb__separator { + color: #c0c4cc; + } +} + +.current-menu { + font-size: 20px; + font-weight: 600; + color: #303133; + line-height: 1.4; +} + +.add-product-btn { + .el-button { + border-radius: 6px; + padding: 10px 20px; + font-weight: 500; + + i { + margin-right: 4px; + } + } +} + +// 产品表格样式 +.product-table { + margin-bottom: 24px; + + /deep/ .el-table { + border-radius: 6px; + overflow: hidden; + border: 1px solid #ebeef5; + + th { + background-color: #f5f7fa; + color: #303133; + font-weight: 600; + height: 48px; + } + + td { + padding: 16px 0; + } + + .el-table__row { + cursor: pointer; + transition: background-color 0.2s; + + &:hover { + background-color: #f5f7fa; + } + + &.current-row { + background-color: #ecf5ff; + } + } + } +} + +.product-info { + .product-name { + font-size: 14px; + font-weight: 600; + color: #303133; + margin-bottom: 6px; + line-height: 1.4; + } + + .product-desc { + font-size: 12px; + color: #909399; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } +} + +.product-tags { + display: flex; + flex-wrap: wrap; + gap: 4px; + + .el-tag { + border-radius: 4px; + padding: 0 8px; + height: 24px; + line-height: 22px; + font-size: 12px; + + &--info { + background-color: #f4f4f5; + border-color: #e9e9eb; + color: #909399; + } + } +} + +// 操作按钮样式 +.action-buttons { + display: flex; + gap: 8px; + + .el-button { + min-width: 60px; + padding: 7px 15px; + border-radius: 4px; + font-size: 12px; + + &--danger { + background-color: #fef0f0; + border-color: #fbc4c4; + color: #f56c6c; + + &:hover { + background-color: #f56c6c; + color: white; + } + } + } +} + +// 分页样式 +.pagination { + display: flex; + justify-content: flex-end; + margin-top: 24px; + padding-top: 24px; + border-top: 1px solid #ebeef5; + + /deep/ .el-pagination { + .el-pagination__sizes, + .el-pagination__jump { + margin-left: 16px; + } + + .btn-prev, + .btn-next { + border-radius: 4px; + border: 1px solid #d8dce5; + } + + .el-pager { + li { + border-radius: 4px; + border: 1px solid #d8dce5; + margin: 0 4px; + + &.active { + background-color: #409eff; + color: white; + border-color: #409eff; + } + } + } + } +} + +.card-top { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 16px; + border-bottom: 1px solid #e4e7ed; + margin-bottom: 24px; + + .top-tit { + span:first-child { + font-size: 18px; + font-weight: 600; + color: #303133; + display: block; + margin-bottom: 4px; + } + + span:last-child { + font-size: 13px; + color: #909399; + } + } + + .top-btn { + .el-button { + border-radius: 6px; + padding: 10px 24px; + font-weight: 500; + } + } +} + +.card-content { + width: 100%; + + .content-tab { + width: 100%; + + .tab-top { + font-size: 15px; + font-weight: 600; + color: #303133; + margin-bottom: 16px; + } + + .tab-content { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 24px; + + .tab-item { + padding: 10px 24px; + border-radius: 20px; + background-color: #f5f7fa; + color: #606266; + font-size: 14px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid transparent; + + &:hover { + background-color: #e4e7ed; + transform: translateY(-1px); + } + + &.active { + background-color: #409eff; + color: white; + font-weight: 500; + border-color: #409eff; + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3); + } + } + } + } +} + +// 产品详情卡片样式 +.product-detail-card { + border-radius: 8px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); + + /deep/ .el-card__body { + padding: 24px; + } + + .product-basic-info { + padding: 20px; + background-color: #fafafa; + border-radius: 6px; + border: 1px solid #ebeef5; + + /deep/ .el-form-item { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + + .el-form-item__label { + color: #606266; + font-weight: 500; + } + + .el-input, + .el-textarea { + .el-input__inner, + .el-textarea__inner { + border-radius: 4px; + + &:focus { + border-color: #409eff; + } + } + } + + .el-input-number { + .el-input-number__decrease, + .el-input-number__increase { + border-radius: 4px 0 0 4px; + } + + .el-input__inner { + border-radius: 0 4px 4px 0; + } + } + } + } + + .product-detail-content { + margin-top: 16px; + + .editor-container { + /deep/ .el-textarea { + .el-textarea__inner { + border-radius: 6px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 14px; + line-height: 1.6; + padding: 16px; + border: 1px solid #dcdfe6; + + &:focus { + border-color: #409eff; + box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); + } + + &::placeholder { + color: #c0c4cc; + } + } + } + } + } +} + +.empty-detail { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80px 40px; + text-align: center; + + .empty-icon { + font-size: 64px; + margin-bottom: 24px; + opacity: 0.3; + animation: float 3s ease-in-out infinite; + } + + .empty-text { + color: #909399; + font-size: 16px; + line-height: 1.6; + max-width: 300px; + } +} + +// 对话框样式优化 +/deep/ .el-dialog { + border-radius: 8px; + + .el-dialog__header { + padding: 20px 24px 10px; + border-bottom: 1px solid #e4e7ed; + + .el-dialog__title { + font-size: 18px; + font-weight: 600; + color: #303133; + } + } + + .el-dialog__body { + padding: 20px 24px; + + .el-form-item { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } + } + } + + .el-dialog__footer { + padding: 10px 24px 20px; + border-top: 1px solid #e4e7ed; + + .dialog-footer { + .el-button { + border-radius: 6px; + padding: 10px 20px; + min-width: 80px; + + &--primary { + font-weight: 500; + } + } + } + } +} + +// 添加动画效果 +@keyframes float { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} + +// 响应式调整 +@media (max-width: 1200px) { + .mianBox { + flex-direction: column; + } + + .left, + .right { + width: 100%; + } + + .left { + margin-bottom: 16px; + } + + .tree-container { + height: 300px; + } +} + +.pagination-controls{ + width: 100%; + display: flex; + justify-content: center; +} + +@media (max-width: 768px) { + .rigtop { + flex-direction: column; + align-items: stretch; + } + + .add-product-btn { + align-self: flex-start; + } + + .tab-content { + flex-direction: column; + + .tab-item { + width: 100%; + text-align: center; + } + } + + .action-buttons { + flex-direction: column; + gap: 4px; + } +} +// 详情:添加样式 +.content-form { + padding: 20px; + .el-form-item { + margin-bottom: 20px; + } +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #ebeef5; + + h3 { + margin: 0; + font-size: 18px; + color: #303133; + } +} + +.form-list { + margin-top: 20px; +} + +.form-item { + padding: 20px; + margin-bottom: 20px; + border: 1px solid #ebeef5; + border-radius: 4px; + background-color: #fafafa; + + &.main-form-item { + background-color: #f5f7fa; + } +} + +.form-title { + font-size: 16px; + font-weight: bold; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px dashed #ebeef5; + color: #409eff; +} + +.form-actions { + text-align: right; + margin-top: 10px; + padding-top: 10px; + border-top: 1px dashed #ebeef5; + + .el-button { + padding: 0 10px; + } +} + +.saved-list { + margin-bottom: 30px; +} + +.list-item { + padding: 15px; + margin-bottom: 15px; + border: 1px solid #e4e7ed; + border-radius: 4px; + background-color: #fff; + + &.main-item { + background-color: #f8f9fa; + } + + .item-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #f0f0f0; + + .item-title { + font-weight: bold; + color: #606266; + } + } + + .item-content { + display: flex; + align-items: flex-start; + + .item-image { + margin-right: 15px; + flex-shrink: 0; + } + + .item-details { + flex: 1; + + div { + margin-bottom: 5px; + + strong { + color: #606266; + margin-right: 5px; + } + } + } + } +} + +.detail-section { + margin-top: 15px; + padding-top: 15px; + border-top: 1px dashed #e4e7ed; +} + +.detail-list { + .detail-item { + padding: 10px; + margin-bottom: 10px; + background-color: #fff; + border: 1px solid #f0f0f0; + border-radius: 4px; + + .detail-title { + font-weight: bold; + margin-bottom: 8px; + color: #67c23a; + } + + .detail-content { + margin-bottom: 8px; + + div { + margin-bottom: 3px; + + strong { + color: #909399; + margin-right: 5px; + } + } + } + + .detail-actions { + text-align: right; + } + } +} + +.detail-form-section { + margin-top: 15px; + padding: 15px; + background-color: #f9f9f9; + border-radius: 4px; + border: 1px dashed #dcdfe6; +} + +.detail-form-item { + margin-bottom: 15px; + padding: 15px; + background-color: #fff; + border-radius: 4px; + border: 1px solid #ebeef5; +} + +.add-detail-btn { + text-align: center; + margin-top: 10px; +} + +.main-product-form { + padding: 20px; + margin-bottom: 30px; + border: 1px solid #ebeef5; + border-radius: 4px; + background-color: #fafafa; +} + +.card-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid #ebeef5; + + .top-tit { + display: flex; + flex-direction: column; + + span:first-child { + font-size: 18px; + font-weight: bold; + margin-bottom: 5px; + } + + span:last-child { + font-size: 14px; + color: #409eff; + } + } +} + +.no-product-selected { + padding: 80px 20px; + text-align: center; + + .empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 200px; + } +} + +// 详情:为产品表格行添加悬停效果 +.product-table { + /deep/ .el-table__row { + cursor: pointer; + + &:hover { + background-color: #f5f7fa; + } + + &.current-row { + background-color: #ecf5ff; + } + } +} diff --git a/f/web-kboss/src/views/product/allProduct/index.vue b/f/web-kboss/src/views/product/allProduct/index.vue index f4feece..2b954b6 100644 --- a/f/web-kboss/src/views/product/allProduct/index.vue +++ b/f/web-kboss/src/views/product/allProduct/index.vue @@ -81,7 +81,7 @@ diff --git a/f/web-kboss/src/views/product/mainPage/index.vue b/f/web-kboss/src/views/product/mainPage/index.vue index 30ed540..8386db7 100644 --- a/f/web-kboss/src/views/product/mainPage/index.vue +++ b/f/web-kboss/src/views/product/mainPage/index.vue @@ -41,17 +41,28 @@ + + + + + + -
@@ -64,7 +75,8 @@

手机号: {{ userInfo.mobile }}

邮箱: {{ userInfo.email }}

-
·
+ +
账户余额
@@ -128,8 +140,6 @@ export default Vue.extend({ }, viewList: [], navList: [], - // 移除 data 中的 mybalance 定义 - mybalance: 0, todoList: [ { name: '待支付', count: 0 }, { name: '待续费', count: 0 }, @@ -137,14 +147,12 @@ export default Vue.extend({ { name: '站内信', count: 0 } ], messageCenterVisible: false, - // 添加图标路径数组 navIcons: [icon1, icon2, icon3, icon4] } }, created() { - this.initMybalance(); - this.getUnreadMsgCount(); + this.getUnreadMsgCount(); this.fetchTodoCount(); }, mounted() { @@ -168,6 +176,16 @@ export default Vue.extend({ }) }, methods: { + goBaiDu(listUrl) { + this.$store.commit('setRedirectUrl', listUrl); + localStorage.setItem('redirectUrl', listUrl); + this.$router.push({ + name: 'baiduProductShow', + params: { + listUrl: listUrl, + } + }); + }, goBaidu(item) { this.$store.commit('setRedirectUrl', item.url) localStorage.setItem('redirectUrl', item.url) @@ -180,9 +198,7 @@ export default Vue.extend({ } }) }, - // 添加获取导航图标的方法 getNavIcon(index) { - // 如果导航项数量超过图标数量,循环使用图标 const iconIndex = index % this.navIcons.length; return this.navIcons[iconIndex]; }, @@ -190,7 +206,8 @@ export default Vue.extend({ async initMybalance() { const res = await editReachargelogAPI() if (res.status) { - this.mybalance = res.data + // 注意:根据您的 user 模块,这里需要使用 'SETMYBANLANCE' 而不是 'user/setMybalance' + this.$store.commit('SETMYBANLANCE', res.data) } }, async getUnreadMsgCount() { @@ -209,12 +226,10 @@ export default Vue.extend({ this.$message.error('获取未读消息失败'); } }, - // 获取待办事项数量 async fetchTodoCount() { try { const res = await todoCount(); if (res.status && res.data) { - // 更新待办事项数量 this.todoList = this.todoList.map(item => { switch(item.name) { case '待支付': @@ -240,27 +255,17 @@ export default Vue.extend({ this.openMessageCenter(); } else { let query = {}; - switch(todoName) { case '待支付': - query = { - filterType: 'processing' - }; + query = { filterType: 'processing' }; break; case '待续费': - query = { - filterType: 'pendingPayment' - }; + query = { filterType: 'pendingPayment' }; break; case '处理中': - query = { - filterType: 'processing' - }; + query = { filterType: 'processing' }; break; } - - console.log(`跳转到资源概览,筛选类型: ${todoName}`, query); - this.$router.push({ path: '/orderManagement/orderManagement', query: query @@ -367,7 +372,6 @@ export default Vue.extend({ justify-content: center; min-width: 0; - // 修改这里:为图片添加样式 .nav-icon { width: 24px; height: 24px; @@ -375,13 +379,6 @@ export default Vue.extend({ object-fit: contain; } - // 移除原来的图标样式 - // i { - // font-size: 24px; - // margin-bottom: 10px; - // color: #409eff; - // } - &:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2); diff --git a/kgadget/src/baiDuSmsClient.py b/kgadget/src/baiDuSmsClient.py index 5148b11..25de0ae 100644 --- a/kgadget/src/baiDuSmsClient.py +++ b/kgadget/src/baiDuSmsClient.py @@ -31,7 +31,8 @@ class BaiduSMS: # 替换为您的百度短信签名名称 # self.signature_id = 'sms-sign-qQHYeC17077' # 开元云科技 # self.signature_id = 'sms-sign-BqOhYB33019' # 开元云 - self.signature_id = 'sms-sign-LOShPq75464' # 开元云北京 + # self.signature_id = 'sms-sign-LOShPq75464' # 开元云北京 + self.signature_id = 'sms-sign-xQYUwp42637' # 开元云北京 # 短信模板类型映射(键为业务类型,值为对应模板ID) self.sms_types = { "注册登录验证": "sms-tpl-123", # 示例模板ID