addproject

This commit is contained in:
qiaoxinjiu
2026-01-22 19:10:37 +08:00
commit 6994b185a3
184 changed files with 21039 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: qiaoxinjiu@sparkedu.com
Create Date: 2026/01/22 5:58 下午
"""
import logging
import os
import sys
# 添加项目根目录到 Python 路径,以便导入 base_framework 模块
current_file_path = os.path.abspath(__file__)
project_root = os.path.abspath(os.path.join(os.path.dirname(current_file_path), '../../../../'))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from base_framework.public_tools import log
from base_framework.public_tools.my_faker import MyFaker
from base_framework.public_tools.runner import Runner
from base_framework.public_tools.pgsqlhelper import PgSqlHelper
from base_framework.public_tools import read_config
from base_framework.public_tools import utils
from base_framework.public_tools import mg_keyword
from zhyy.library.ZZYY_interface import ZhyyInterface
obj_get_log = log.get_logger()
obj_my_faker = MyFaker()
obj_runner = Runner()
obj_pgsql_helper = PgSqlHelper()
obj_get_way = utils.Tools()
obj_mg_keyword = mg_keyword.ManageKeyWord()
class PurchaseOrder(ZhyyInterface):
def __init__(self):
'''
这个是针对于读取配置文件的初始化函数,用于读取默认参数
'''
super().__init__()
self.config_index_path = os.path.dirname(os.path.abspath(__file__))
self.config_index_filePath = os.path.join(self.config_index_path, "purchase.ini")
self.config_index_content = read_config.ReadConfig(filename=self.config_index_filePath)
def kw_zhyy_get_purchase_page_post(self, note, user, **kwargs):
"""
| 功能说明: | 返回采购工作台采购单列表数据 |
| 输入参数: | note | 注释 |
|user | 用户信息,传入 'purchase' 默认读取配置文件里面 'purchase' 对应的默认账号信息|
|supplier_company_ids | 供应商id | 非必填
|payment_status | 付款状态 | 非必填
|status | 采购单状态 | 非必填
|order_sn | 采购单号 | 非必填
|page_no | 页码 | 必填
|page_size | 每页条数 | 必填
| 返回参数: | {"success":true,"message":"success","code":200,"data":
{'todoTask':['PO260116003','PO260115010'],'inProcessTask':['PO260116003','PO260115010']}} | |
| 作者信息: | 谯新久 | 修改时间 | 2022-8-20 |
"""
logging.info("==========={0}===========".format(note))
# 获取所有参数
supplier_company_ids = kwargs.get("supplier_company_ids")
payment_status = kwargs.get("payment_status")
status = kwargs.get("status")
order_sn = kwargs.get("order_sn")
page_no = kwargs.get("page_no")
page_size = kwargs.get("page_size")
# 检查必填参数
if not page_no or not page_size:
raise Exception("页码和每页条数不能为空")
# 组装参数字典,只包含非空字段,参数名使用 pageNo 和 pageSize
request_params = {
"pageNo": page_no,
"pageSize": page_size
}
# 如果字段不为空,才添加到参数字典中
if supplier_company_ids is not None and supplier_company_ids != "":
request_params["supplier_company_ids"] = supplier_company_ids
if payment_status is not None and payment_status != "":
request_params["payment_status"] = payment_status
if status is not None and status != "":
request_params["status"] = status
if order_sn is not None and order_sn != "":
request_params["order_sn"] = order_sn
# 使用 ** 方式解包字典传递参数
get_todo_info = self.kw_in_zhyy_purchase_order_page_post(user=user, **request_params)
print(get_todo_info if get_todo_info else "查询失败")
return get_todo_info
if __name__ == '__main__':
test = PurchaseOrder()
a = test.kw_zhyy_get_purchase_page_post(user='purchase', note="测试", page_no=1, page_size=10)
print(a)

View File

@@ -0,0 +1,88 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: qiaoxinjiu@sparkedu.com
Create Date: 2022/08/20 5:58 下午
"""
import logging
import os
import sys
# 添加项目根目录到 Python 路径,以便导入 base_framework 模块
current_file_path = os.path.abspath(__file__)
project_root = os.path.abspath(os.path.join(os.path.dirname(current_file_path), '../../../../'))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from base_framework.public_tools import log
from base_framework.public_tools.my_faker import MyFaker
from base_framework.public_tools.runner import Runner
from base_framework.public_tools.pgsqlhelper import PgSqlHelper
from base_framework.public_tools import read_config
from base_framework.public_tools import utils
from base_framework.public_tools import mg_keyword
from zhyy.library.ZZYY_interface import ZhyyInterface
obj_get_log = log.get_logger()
obj_my_faker = MyFaker()
obj_runner = Runner()
obj_pgsql_helper = PgSqlHelper()
obj_get_way = utils.Tools()
obj_mg_keyword = mg_keyword.ManageKeyWord()
class PurchaseIndex(ZhyyInterface):
def __init__(self):
'''
这个是针对于读取配置文件的初始化函数,用于读取默认参数
'''
super().__init__()
self.config_index_path = os.path.dirname(os.path.abspath(__file__))
self.config_index_filePath = os.path.join(self.config_index_path, "purchase.ini")
self.config_index_content = read_config.ReadConfig(filename=self.config_index_filePath)
def kw_zhyy_get_todo(self, note, user):
"""
| 功能说明: | 返回采购工作台首页待办任务的PO与在办任务PO |
| 输入参数: | note | 注释 |
|user | 用户信息,传入 'purchase' 默认读取配置文件里面 'purchase' 对应的默认账号信息|
| 返回参数: | {"success":true,"message":"success","code":200,"data":
{'todoTask':['PO260116003','PO260115010'],'inProcessTask':['PO260116003','PO260115010']}} | |
| 作者信息: | 谯新久 | 修改时间 | 2022-8-20 |
"""
logging.info("==========={0}===========".format(note))
get_todo_info = self.kw_in_zhyy_purchase_todo_get(user=user)
if get_todo_info['code'] != 0:
raise Exception("查询采购待办任务失败: {}".format(get_todo_info))
get_todo_info["message"] = "查询采购待办任务成功"
data = get_todo_info.get("data")
if data is None:
raise Exception("返回数据为空data字段不存在")
list_get_todo_task = data.get("todoTask") or []
list_get_process_task = data.get("inProcessTask") or []
list_todo_task_po = []
list_process_task_po = []
for todoTask in list_get_todo_task:
if isinstance(todoTask, dict):
list_todo_task_po.append(todoTask.get("businessSn"))
for processTask in list_get_process_task:
if isinstance(processTask, dict):
list_process_task_po.append(processTask.get("businessSn"))
get_todo_info["data"]["todoTask"] = list_todo_task_po
get_todo_info["data"]["inProcessTask"] = list_process_task_po
if list_todo_task_po:
test_purchase = list_todo_task_po[0]
# 表在public schema中使用public.erp_purchase_order格式
sql = "SELECT * FROM public.erp_purchase_order WHERE order_sn = '{}'".format(test_purchase)
try:
obj_pgsql_helper.select_one(sql)
except Exception as e:
# 如果查询失败,记录日志但不影响主流程
obj_get_log.warning("查询采购订单表失败,订单号:{},错误:{}".format(test_purchase, str(e)))
return get_todo_info
if __name__ == '__main__':
test = PurchaseIndex()
a = test.kw_zhyy_get_todo(user='purchase',note="测试")
print(a)

View File

@@ -0,0 +1,2 @@
[qa-user]
user_info ={"studentId":21797349,"sex":0,"nickName":"auto st test","birthday":1640966400000,"avatar":"https://stalegacy.huohua.cn/image/huohua/avatar/default/default_avatar1.png"}

View File

View File

View File

@@ -0,0 +1,57 @@
# -*- coding:utf-8 -*-
"""
Author: 陈江
Email: chenjiang@huohua.cn
Create Date: 2022/03/03 11:25 下午
"""
from base_framework.public_tools import log
from base_framework.public_tools.sqlhelper import MySqLHelper
obj_log = log.get_logger()
obj_my_sql_helper = MySqLHelper()
class AssetCommon:
def __init__(self):
pass
def get_course_package_info_by_name(self, course_package_name):
"""
功能:根据套餐名称获取套餐基本信息
| 输入参数: | course_package_name string | 套餐名称 |
"""
sql = "SELECT id,code,name,price FROM `peppa`.`course_package` WHERE `name`='{}';".format(course_package_name)
return obj_my_sql_helper.select_one(sql)
def get_order_info_V2(self, **where_condition):
# user_id = None, course_package_id = None, course_id = None, business_line_type = None, order_id = None, order_code = None
ocp = ['user_id', 'business_line_type', 'order_id', 'order_code', 'status']
sprl = ['course_package_id', 'course_id']
where_str = None
for k in where_condition.keys():
t = ''
if k in sprl:
t = 'sprl'
else:
t = 'ocp'
if not where_str:
where_str = '{}.{}=\'{}\''.format(t, k, where_condition.get(k))
else:
where_str = '{} AND {}.{}=\'{}\''.format(where_str, t, k, where_condition.get(k))
if not where_str:
obj_log.error('参数必填')
return False
sql = "SELECT ocp.id as order_id,ocp.code,ocp.audit_status,ocp.status as order_status,ocp.user_id,ocp.user_address_id,ocp.business_line_type,sprl.course_package_id,sprl.course_id,sprl.subscribe_id,sprl.valid as subscribe_pre_valid,sprl.id as subscribe_pre_id FROM order_center.order_course_package ocp LEFT JOIN order_center.subscribe_pre_create_log sprl ON ocp.id=sprl.order_id WHERE {} ORDER BY ocp.id DESC LIMIT 1".format(
where_str.replace('order_id', 'id'))
obj_log.info(sql)
return obj_my_sql_helper.select_one(sql)
if __name__ == '__main__':
user_common_obj = AssetCommon()
print(user_common_obj.get_order_info(**{'order_id': 1193182, 'business_line_type': '1', 'status': 100}))

View File

@@ -0,0 +1,240 @@
# -*- coding:utf-8 -*-
# @Time : 2023/3/7 13:28
# @Author: luozhipeng
# @File : contract_pair_check.py
import os
import sys
input_team_name = sys.argv
BASIC_PATH = os.path.dirname(os.path.abspath(__file__))
TEAM_PATH = os.path.abspath(os.path.join(BASIC_PATH, '../../../{}'.format("base_framework")))
sys.path.append(TEAM_PATH)
PROJECT_PATH = os.path.abspath(os.path.join(BASIC_PATH, '../../..'))
sys.path.append(PROJECT_PATH)
from base_framework.public_tools.sqlhelper import MySqLHelper
from base_framework.public_tools.utils import Tools
import requests
import re
import json
import pymysql
obj_my_sql_helper = MySqLHelper()
class ContractPairCheck():
def __init__(self):
pass
def get_unfinished_interface(self):
sql_get_interface = "SELECT distinct (x.con_url) 提供方接口,x.pro_url 消费方接口,x.con_method 提供方请求方式,x.con_server 提供方服务,x.pro_server 消费方服务,x.at_num 自动化接口数 FROM sparkatp.contract_pair x WHERE x.at_num =0 and x.status =1 and x.con_server in (select si.server_name from sparkatp.swagger_info si where si.team in ('ubrd','GUE') and access_type IN (2)) and x.pro_server not in (select si.server_name from sparkatp.swagger_info si where si.team ='ubrd' and access_type IN (2)) and x.roles = 0 order by x.pro_server,x.con_url"
unfinished_interface = obj_my_sql_helper.select_all(sql_get_interface)
return unfinished_interface
def send_reshult(self):
headers = {"Content-Type": "application/json;charset=UTF-8"}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/9f3556b7-cb60-44bf-adbf-24b5b2552014"
contract_pair_intf = self.get_unfinished_interface()
if len(contract_pair_intf) != 0:
message_data = {"msg_type": "text", "content": {'text': '未完成自动化的契约对接口{}'.format(contract_pair_intf)}}
rsp = requests.post(url=web_hook, json=message_data, headers=headers)
class AutoInterfaceCheck():
def __init__(self):
pass
def get_unfinished_interface(self):
sql_get_interface = """select id,in_url from sparkatp.interface_info a WHERE( a.swagger_id in (SELECT id FROM sparkatp.swagger_info WHERE team in ("UBRD","GUE") and access_type not IN (0)) ) AND a.created_time > "2023-01-01 00:00:50" AND is_used = 1 and (case_numbers IS NULL or case_numbers='') and offline=0 and jira_id is null order by created_time """
unfinished_interface_list = obj_my_sql_helper.select_all(sql_get_interface)
return unfinished_interface_list
def get_interface_jira(self,interface):
sql_req_time = "select max(created_time) created_time from sparkatp.request_parameters rp where rp.interface_id ={}".format(
interface["id"])
req_max_time = obj_my_sql_helper.select_one(sql_req_time)['created_time']
sql_rep_time = "select max(created_time) created_time from sparkatp.response_parameters rp where rp.interface_id ={}".format(
interface["id"])
rep_max_time = obj_my_sql_helper.select_one(sql_rep_time)['created_time']
if rep_max_time and req_max_time:
if rep_max_time <= req_max_time:
sql_req_jira = "select distinct (jira_id) from sparkatp.request_parameters rp where rp.interface_id ={0} and created_time = '{1}'".format(
interface["id"], req_max_time)
interface_jira = obj_my_sql_helper.select_one(sql_req_jira)["jira_id"]
else:
sql_rep_jira = "select distinct (jira_id) from sparkatp.response_parameters rp where rp.interface_id ={0} and created_time = '{1}'".format(
interface["id"], rep_max_time)
interface_jira = obj_my_sql_helper.select_one(sql_rep_jira)["jira_id"]
elif rep_max_time and not req_max_time:
sql_rep_jira = "select distinct (jira_id) from sparkatp.response_parameters rp where rp.interface_id ={0} and created_time = '{1}'".format(
interface["id"], rep_max_time)
interface_jira = obj_my_sql_helper.select_one(sql_rep_jira)["jira_id"]
elif not rep_max_time and req_max_time:
sql_req_jira = "select distinct (jira_id) from sparkatp.request_parameters rp where rp.interface_id ={0} and created_time = '{1}'".format(
interface["id"], req_max_time)
interface_jira = obj_my_sql_helper.select_one(sql_req_jira)["jira_id"]
return interface_jira
def send_result(self):
unfinished_interface_list = self.get_unfinished_interface()
for interface in unfinished_interface_list:
interface['jira'] = self.get_interface_jira(interface)
if not interface['jira']:
interface['qa'] = None
else:
interface['qa'] = self.get_jira_qa(interface['jira'])
headers = {"Content-Type": "application/json;charset=UTF-8"}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/9f3556b7-cb60-44bf-adbf-24b5b2552014"
if len(unfinished_interface_list) != 0:
message_data = {"msg_type": "text", "content": {'text': 'QA公共环境未完成自动化的接口{}'.format(unfinished_interface_list)}}
rsp = requests.post(url=web_hook, json=message_data, headers=headers)
def get_jira_qa(self,jira):
try:
conn = pymysql.connect(host='10.250.200.53',user='root',password='peppa@test',database='tools',charset="utf8",port=3306)
except :
raise pymysql.OperationalError("连接数据库失败")
cn =conn.cursor()
sql = "SELECT tester FROM tools.tm_project where jira_number = '{}'".format(jira)
cn.execute(sql)
qa = cn.fetchall()
cn.close()
conn.close()
if qa:
return qa[0][0]
else:
return None
class CoverageCheck():
# 连接数据库
@staticmethod
def get_select(sql):
try:
conn = pymysql.connect(host='10.250.200.53', user='root', password='peppa@test', database='tools',
charset="utf8", port=3306)
except:
raise pymysql.OperationalError("连接数据库失败")
cn = conn.cursor()
cn.execute(sql)
res = cn.fetchall()
cn.close()
conn.close()
return res
# 获取未搜集覆盖率的项目
@staticmethod
def get_unfinished_coverage():
start_time = Tools().get_format_date(r_type=15, add_days=-2)
end_time = Tools().get_format_date(r_type=16, add_days=-1)
# 查询最近一天上线有后端代码变动,需要搜集覆盖率项目
need_sql = """SELECT env FROM tools.project_plan WHERE ID IN
(SELECT project_id FROM tools.project_tester WHERE tester IN ("陈洁","陈江","罗志鹏","谯新久","刘涛婷"))
AND status IN (14) AND rd_code_add_line>0 AND (it_start_date IS NOT NULL OR qa_start_date IS NOT null)
AND online_date BETWEEN '{}' AND '{}'""".format(start_time, end_time)
need_coverage_list = CoverageCheck().get_select(need_sql)
# 查询已搜集覆盖率项目
sql_implemented_sql = '''SELECT `env_name` FROM `sparkatp`.`build_jacoco` WHERE `team` = 'UBRD' AND `status` = '1'
AND `is_delete` = '0' AND `is_pass` = '1' '''
completed_coverage_list = obj_my_sql_helper.select_all(sql_implemented_sql)
unfinished_coverage_list = []
for item1 in range(0, len(need_coverage_list)):
unfinished_coverage_list.append(need_coverage_list[item1][0])
# 返回未搜集覆盖率的项目
for item in completed_coverage_list:
completed_jira = item["env_name"]
if completed_jira in unfinished_coverage_list:
unfinished_coverage_list.remove(completed_jira)
# 根据unfinished_coverage_list 查jira_name
jira_name_list = []
for item in unfinished_coverage_list:
env_name = item
sql = """SELECT jira_number FROM tools.project_plan WHERE env='{}'""".format(env_name)
jira_name = CoverageCheck().get_select(sql)
jira_name_list.append(jira_name[0][0])
return jira_name_list
# 获取未构建基线用例项目
@staticmethod
def get_not_bulid_jira():
start_time = Tools().get_format_date(r_type=15, add_days=-2)
end_time = Tools().get_format_date(r_type=16, add_days=-1)
# 返回有后端变动的jira (有后端代码变更&上线时间在3天内 + jira存在服务变更项目状态为sim测试
need_sql = """SELECT env FROM tools.project_plan WHERE
ID IN (SELECT project_id FROM tools.project_tester WHERE tester IN ("陈洁","陈江","罗志鹏","谯新久","刘涛婷"))
AND status IN (14) AND rd_code_add_line>0 AND online_date BETWEEN '{}' AND '{}'
AND qa_start_date IS NOT NULL UNION SELECT env FROM tools.project_plan WHERE ID IN (SELECT project_plan_id
FROM tools.project_plan_server) AND jira_number IN (SELECT jira_number FROM tools.tm_project WHERE status
IN (12) AND `tester` IN ("陈洁","陈江","罗志鹏","谯新久","刘涛婷") AND test_qa_time_consume>0)""".format(start_time,
end_time)
need_build_list = CoverageCheck().get_select(need_sql)
# 返回有构建基线用例jira
built_sql = """SELECT DISTINCT special_env FROM sparkatp.build_info WHERE run_type=2 AND team='UBRD' AND STATUS=2"""
built_list = obj_my_sql_helper.select_all(built_sql)
not_bulit_list = []
# 取出有后端改动得jira
for item1 in range(0, len(need_build_list)):
not_bulit_list.append(need_build_list[item1][0])
# 返回未构建基线用例jira
for item in built_list:
completed_jira = item["special_env"]
if completed_jira in not_bulit_list:
not_bulit_list.remove(completed_jira)
jira_name_list = []
for item in not_bulit_list:
env_name = item
sql = """SELECT jira_number FROM tools.project_plan WHERE env='{}'""".format(env_name)
jira_name = CoverageCheck().get_select(sql)
jira_name_list.append(jira_name[0][0])
return jira_name_list
# 发送消息
def send_result(self, type=1):
if type == 1:
jira_list = self.get_unfinished_coverage()
elif type == 2:
jira_list = self.get_not_bulid_jira()
send_list = []
for item in jira_list:
send_dict = {}
send_dict["jira"] = item
qa_list = AutoInterfaceCheck().get_jira_qa(item)
send_dict["qa"] = qa_list
send_list.append(send_dict)
headers = {"Content-Type": "application/json;charset=UTF-8"}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/b6bf33ae-4239-4bef-a8a8-21896e0d1ba1"
if len(jira_list) != 0:
if type == 1:
message_data = {"msg_type": "text",
"content": {'text': '未搜集覆盖率已上线项目{}'.format(send_list)}}
rsp = requests.post(url=web_hook, json=message_data, headers=headers)
elif type == 2:
message_data = {"msg_type": "text",
"content": {'text': '未构建基线用例已上线项目{}'.format(send_list)}}
rsp = requests.post(url=web_hook, json=message_data, headers=headers)
if __name__ == '__main__':
A = ContractPairCheck()
A.send_reshult()
B = AutoInterfaceCheck()
# B.get_unfinished_interface()
# B.get_jira_qa(jira = 'PLATFORM-31791')
B.send_result()
C = CoverageCheck()
C.send_result(type=1)
C.send_result(type=2)

View File

@@ -0,0 +1,31 @@
# -*- coding:utf-8 -*-
"""
Author: 罗志鹏
Email: luozhipeng@huohua.cn
Create Date: 2022/03/03 11:25 下午
"""
from base_framework.public_tools import log
from base_framework.public_tools.sqlhelper import MySqLHelper
obj_log = log.get_logger()
obj_my_sql_helper = MySqLHelper()
class CoursePackageCommon:
def __init__(self):
pass
def get_course_package_info_by_name(self, course_package_name):
"""
功能:根据套餐名称获取套餐基本信息
| 输入参数: | course_package_name string | 套餐名称 |
"""
sql = "SELECT id,code,name,price FROM `peppa`.`course_package` WHERE `name`='{}';".format(course_package_name)
return obj_my_sql_helper.select_one(sql)
if __name__ == '__main__':
user_common_obj = CoursePackageCommon()
user_common_obj.get_course_package_info_by_name('测试杰拉德0325-火花-直播逻辑思维')

View File

@@ -0,0 +1,31 @@
import matplotlib.pyplot as plt
import matplotlib
# 设置字体为支持中文的字体如SimHei
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统
# matplotlib.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # macOS系统
matplotlib.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 数据
categories = ['供应链', '天窗', 'cc', 'la', '题库', '练测', '教务', '教师', '基础', '学生端', '家长端', '活字', '转介绍']
values = [8, 4, 13, 20, 11, 2, 22, 10, 1, 1, 14, 1, 17]
# 创建柱状图
plt.figure(figsize=(10, 6))
bars = plt.bar(categories, values, color='skyblue')
# 添加标题和标签
plt.title('各类别数量统计', fontsize=16)
plt.xlabel('类别', fontsize=12)
plt.ylabel('数量', fontsize=12)
plt.xticks(rotation=45, ha='right') # 旋转X轴标签
# 在每个柱子上方显示数量
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width() / 2, height, str(height),
ha='center', va='bottom', fontsize=10)
# 显示图表
plt.tight_layout()
plt.show()

View File

@@ -0,0 +1,7 @@
[QA]
check_list = ['PEPPA-STUDENT-API','PEPPA-LEARNING-PLAN-LISTENER','PEPPA-LEARNING-PLAN-SERVER','PEPPA-TEACH-BIZ','PEPPA-TEACH-LISTENER','PEPPA-TEACH-TIMETABLE-SERVER','PEPPA-USER-AUTH-API','PEPPA-USER-CENTER-SERVER']
[SIM]
check_list = ['PEPPA-STUDENT-API','PEPPA-LEARNING-PLAN-LISTENER','PEPPA-LEARNING-PLAN-SERVER','PEPPA-TEACH-BIZ','PEPPA-TEACH-LISTENER','PEPPA-TEACH-TIMETABLE-SERVER','PEPPA-USER-AUTH-API','PEPPA-USER-CENTER-SERVER']

View File

@@ -0,0 +1,141 @@
# -*- coding:utf-8 -*-
"""
Author: 罗志鹏
Email: luozhipeng@huohua.cn
Create Date: 2022/07/25 11:25 下午
"""
import requests
import re
import json
class EnvCheck():
def __init__(self):
self.container_ip_list = []
def get_env_container_ip(self,env):
dis_server =[]
dis_ip = []
headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','Accept-Encoding':'gzip, deflate, br'}
if env =='QA':
req = requests.get(url="http://eureka.qa.huohua.cn/",headers=headers)
elif env == 'SIM':
req = requests.get(url="http://eureka.sim.huohua.cn/", headers=headers)
else:
raise RuntimeError("环境选择异常")
req_list =req.text.split('tbody')
# print(req_list[1])
server_str_list = req_list[1].split('<tr>')
check_list = self.get_check_lsit(env=env)
for server in check_list:
if req.text.find(server) ==-1:
dis_server.append(server)
for i in check_list:
for str_ser in server_str_list:
if str_ser.find(i) != -1:
dict_sever = {}
# ip_list = []
str_sername_start = '<td><b>'
str_sername_end = '</b></td>'
server_name = str_ser[str_ser.find(str_sername_start) + 7:str_ser.find(str_sername_end)]
ip_list = re.findall(r'[a-z]://(.*?):8080', str_ser)
dict_sever[server_name] = ip_list
# print(dict_sever)
for ip_ch in ip_list:
url_check = "http://"+ip_ch+':8080/actuator/health'
resp = requests.get(url=url_check)
# print(resp.json())
if resp.json()['status'] != 'UP':
dict_ip = {server_name:ip_ch}
dis_ip.append(dict_ip)
return dis_ip,dis_server
# re_list = []
# server_list = []
# for str_ser in server_check_list:
# print(str_ser)
# print(server_name)
# pattern = re.compile(r'')
# str_server = pattern.search(str_ser)
# server_name = str_ser[str_ser.start():str_ser.end()]
# print(server_name)
# for server in check_list :
# for string_server in server_list:
# if string_server.find(server)!= -1:
# # print(string_server.find(server))
# re_list.append(string_server)
# print(re_list)
# ip_list = []
# for string_server in re_list :
# if string_server.find('http://'):
# pattern = re.compile(r'[a-zA-z]+://[^\s]*:8080')
# str_ip = pattern.search(string_server)
# # print(str_ip.start())
# url = string_server[str_ip.start():str_ip.end()]
# print(url)
def send_result(self):
dis_ip,dis_server = self.get_env_container_ip(env='SIM')
at_user_list = [{"tag": "at", "user_id": "{}".format("7020366259502153730")}]
message_data_SIM_server = {"msg_type": "text", "content": {'text':'SIM服务未找到部署IP{}'.format(dis_server)}}
message_data_SIM_IP = {"msg_type": "text", "content": {'text':'SIM服务部署IP不可用{}'.format(dis_ip)}}
headers = {"Content-Type": "application/json;charset=UTF-8"}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/28b775e7-a863-4807-b280-c82e09be0a80"
if len(dis_server) != 0:
json_data = json.dumps(message_data_SIM_server)
rsp = requests.post(url=web_hook, json=message_data_SIM_server, headers=headers)
if len(dis_ip) != 0:
json_data = json.dumps(message_data_SIM_IP)
rsp = requests.post(url=web_hook, json=message_data_SIM_IP, headers=headers)
dis_ip,dis_server = self.get_env_container_ip(env='QA')
message_data_QA_server = {"msg_type": "text", "content": {'text':'QA服务未找到部署IP{}'.format(dis_server)}}
message_data_QA_IP = {"msg_type": "text", "content": {'text':'QA服务部署IP不可用{}'.format(dis_ip)}}
if len(dis_server) != 0:
json_data = json.dumps(message_data_QA_server)
rsp = requests.post(url=web_hook, data=json_data, headers=headers)
if len(dis_ip) != 0:
json_data = json.dumps(message_data_QA_IP)
rsp = requests.post(url=web_hook, json=message_data_QA_IP, headers=headers)
def get_check_lsit(self,env):
if env == 'QA':
check_list = ['PEPPA-STUDENT-API','PEPPA-LEARNING-PLAN-LISTENER','PEPPA-LEARNING-PLAN-SERVER','PEPPA-TEACH-BIZ','PEPPA-TEACH-LISTENER','PEPPA-TEACH-TIMETABLE-SERVER','PEPPA-USER-AUTH-API','PEPPA-USER-CENTER-SERVER']
return check_list
if env == 'SIM':
check_list = ['PEPPA-STUDENT-API','PEPPA-LEARNING-PLAN-LISTENER','PEPPA-LEARNING-PLAN-SERVER','PEPPA-TEACH-BIZ','PEPPA-TEACH-LISTENER','PEPPA-TEACH-TIMETABLE-SERVER','PEPPA-USER-AUTH-API','PEPPA-USER-CENTER-SERVER']
return check_list
if __name__ == '__main__':
# o ='"http://10.251.187.248:8080/actuator/info" "http://10.251.187.248:8080/actuator/info"'
# i =re.findall(r'[a-z]://(.*?):8080',o)
# print(a)
A=EnvCheck()
A.send_result()

View File

@@ -0,0 +1,141 @@
# encoding: UTF-8
import time
import subprocess
from subprocess import PIPE,Popen
import os
class OSType:
WIN, LINUX, UNKNOWN = range(3)
def __init__(self):
pass
@staticmethod
def get_type():
import platform
system_name = platform.system()
if system_name.lower() == 'windows':
return OSType.WIN
elif system_name.lower() == 'linux':
return OSType.LINUX
else:
return OSType.UNKNOWN
class tool(object):
def __init__(self):
self.env_port = 5011
def run_process(self, cmd_str, out_p=False):
"""
run command
cmd_str unicode string.
"""
if OSType.WIN == OSType.get_type():
# cmd_str = cmd_str.encode('gbk')
cmd_str = cmd_str
elif OSType.LINUX == OSType.get_type():
cmd_str = cmd_str.encode('utf-8')
else:
raise RuntimeError("your os is not support.")
close_fds = False if OSType.WIN == OSType.get_type() else True
if out_p:
p = subprocess.Popen(cmd_str, shell=True, close_fds=close_fds, stdout=PIPE)
p.wait()
return p.returncode, p.stdout.read()
else:
c = self.get_devnull()
p = subprocess.Popen(cmd_str, shell=True, close_fds=close_fds, stdout=c)
# for line in p.stdout.readline():
# print(line)
# p.stdout.close()
p.communicate()
return p.returncode, None
def adb_cmd(self,cmd):
process = Popen(cmd, shell=True, stderr=PIPE, stdout=PIPE)
(stdout, stdrr) = process.communicate()
stdout = stdout.decode('gbk') # 返回字段中存在中文使用gbk
return stdout, stdrr
def get_devnull(self):
try:
return subprocess.DEVNULL
except AttributeError:
# Python 2.x or older
return open(os.devnull, 'r+')
def _kills_pid(self):
if OSType.WIN == OSType.get_type():
kill_pid_cmd = "taskkill /f /pid {}".format(self.pid)
elif OSType.LINUX == OSType.get_type():
kill_pid_cmd = "kill -9 {}".format(self.pid)
else:
raise RuntimeError("your os is not support.")
res_code, res_context = self.run_process(kill_pid_cmd)
if res_code:
raise RuntimeError("kill pid: {} failed. error: {}".format(self.pid, res_context))
def check_port(self):
if OSType.WIN == OSType.get_type():
find_pid_win_cmd = 'netstat -ano | findstr {} | findstr LISTENING'.format(self.env_port)
print(find_pid_win_cmd)
res_code, res_context = self.run_process(find_pid_win_cmd, out_p=True)
if res_code == 0:
if len(res_context) > 0:
try:
self.pid = str(res_context).split()[-1].replace("\\r\\n'", "")
self._kills_pid()
except IndexError:
pass
elif OSType.LINUX == OSType.get_type():
find_pid_linux_cmd = "lsof -i:{}".format(self.env_port)
res_code, res_context = self.run_process(find_pid_linux_cmd, out_p=True)
if res_code == 0:
# 获取pid
if len(res_context) > 0:
try:
self.pid = str(res_context).split("\n")[1].split()[1]
self._kills_pid()
except IndexError:
pass
else:
raise RuntimeError("your os is not support.")
def run_manage(self):
count = 3
while count > 0:
self.run_manages()
find_pid_linux_cmd = "lsof -i:{}".format(self.env_port)
res_code, res_context = self.run_process(find_pid_linux_cmd, out_p=True)
print(res_code, "---res_code---", res_context, "---res_context---")
if len(res_context) > 0:
time.sleep(2)
pid = str(res_context).split("\n")[1].split()[1]
print(pid, "pid####")
count -= 1
if pid:
break
else:
continue
else:
break
def run_manages(self):
lod = "nohup python3 platform_tools/aida/manage.py &."
sh_lod = "./5011.sh"
self.run_process(sh_lod)
# subprocess.call(["./5011.sh"])
# self.run_process(lod)
if __name__ == '__main__':
test = tool()
test.check_port()
time.sleep(3)
test.run_manage()

View File

@@ -0,0 +1,105 @@
import os
import subprocess
from urllib.parse import urlparse
import argparse
class HarmonyAppInstaller:
def __init__(self) -> None:
self.project_path = os.getcwd()
self.temp_dir = os.path.join(self.project_path, "temp")
def _run_command(self, command: str) -> str:
result = subprocess.run(command, shell=True, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"Command failed: {command}\nError: {result.stderr}")
return result.stdout
def install(self, appUniqId, packageId):
import requests
import os
import shutil
# Create or clean temp directory
if os.path.exists(self.temp_dir):
shutil.rmtree(self.temp_dir)
os.makedirs(self.temp_dir)
url = "https://api.qa.huohua.cn/api/versions"
headers = {
'Content-Type': 'application/json',
'huohua-podenv': 'HHC-111781'
}
params = {
'version': '25.1.2.1',
'platform': 'harmonyos',
'appUniqId': appUniqId,
'packageId': packageId
}
response = requests.get(url, headers=headers, params=params)
response_data = response.json()
if not response_data.get('success'):
raise Exception(f"API request failed: {response_data.get('message')}")
app_version = response_data.get('data', {}).get('app_version', {})
download_url = app_version.get('url')
if not download_url:
raise Exception("No download URL found in response")
# Get the filename from the URL
hap_filename = os.path.basename(urlparse(download_url).path)
if not hap_filename.endswith('.hap'):
hap_filename = 'eduparent.hap' # fallback name if URL doesn't end with .hap
# Download the HAP file
hap_file_path = os.path.join(self.temp_dir, hap_filename)
download_response = requests.get(download_url, stream=True)
download_response.raise_for_status()
with open(hap_file_path, 'wb') as f:
for chunk in download_response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
# Execute HDC commands
device_path = f"data/local/tmp/{hap_filename}"
print(f'hdc file send "{hap_file_path}" "{device_path}"')
# Push HAP file to device
self._run_command(f'hdc file send "{hap_file_path}" "{device_path}"')
try:
# Install HAP package
print(f'hdc shell bm install -p "{device_path}"')
self._run_command(f'hdc shell bm install -p "{device_path}"')
finally:
# Clean up: Remove HAP file from device
print(f'hdc shell rm -rf "{device_path}"')
self._run_command(f'hdc shell rm -rf "{device_path}"')
return hap_file_path
def main():
parser = argparse.ArgumentParser(description='Install HarmonyOS application')
parser.add_argument('--app-uniq-id', required=True, help='Unique ID of the application')
parser.add_argument('--package-id', required=True, help='Package ID for the application')
args = parser.parse_args()
try:
installer = HarmonyAppInstaller()
hap_path = installer.install(args.app_uniq_id, args.package_id)
print(f"Successfully installed HAP from: {hap_path}")
except Exception as e:
print(f"Error: {str(e)}")
exit(1)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,257 @@
# -*- coding:utf-8 -*-
import sys
import xml.etree.ElementTree as ET
WORKSPACE = sys.argv[1]
sys.path.append(WORKSPACE)
import json
import requests
import os
import re
from bs4 import BeautifulSoup
from html.parser import HTMLParser
handle_parser = HTMLParser()
BUILD_INFO = {}
class handle_to_jenkins():
'''
处理关于jenkins的执行相关方法
'''
def __init__(self):
self.dict_info = {}
self.list_info = []
def GetJenkinsVar(self, key):
'''
获取jenkins上获得的参数信息
'''
try:
value = os.environ.get(key)
except Exception:
value = os.environ.get(key.upper())
if (not value):
value = ''
return value
def kw_to_get_dd_token(self, environment):
"""
功能: 根据传入环境获取不同的token信息
"""
sim = "40696c86-264a-4222-a40c-cfd64a05dffd"
product = "40696c86-264a-4222-a40c-cfd64a05dffd"
if environment.lower() == "sim" or environment.lower() == "qa":
return sim
else:
return product
def send_message_by_dingding(self, data, environment="qa"):
'''
发送钉钉消息
'''
token = self.kw_to_get_dd_token(environment=environment)
# web_hook = "https://oapi.dingtalk.com/robot/send?access_token={}".format(token)
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/{}".format(token)
headers = {"Content-Type": "application/json"}
json_data = json.dumps(data)
rsp = requests.post(url=web_hook, data=json_data, headers=headers)
return rsp
# print(data)
def send_feishu(self,inferfaces):
'''
发送飞书
:return:
'''
at_user_list = [{"tag": "at", "user_id": "{}".format("7020366259502153730")}]
message_data = {"msg_type": "post", "content": {
"post": {"zh_cn": {"title": "有存在的接口未实现自动化哦",
"content": [[{"tag": "text", "text": "问题数据:"}],
[{"tag": "text", "text": "{}".format(inferfaces)}],
at_user_list]}}}}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/40696c86-264a-4222-a40c-cfd64a05dffd"
headers = {"Content-Type": "application/json"}
json_data = json.dumps(message_data)
print(json_data)
rsp = requests.post(url=web_hook, data=json_data, headers=headers)
return rsp
def handle_send_message(self,root):
'''
处理对应所有人根据job名称匹配来发送@的消息
'''
list_name_phone = {"陈江": "13458500234", "张楠": "", "罗志鹏": "",
"蒲思宇": "", "陈洁": "15328118883", "刘涛婷": "18328504751", "谯新久": "18202810506"}
job_name = self.GetJenkinsVar("JOB_TO_NAME")
job_url = self.GetJenkinsVar("JOB_TO_URL")
enviroment = self.GetJenkinsVar("JOB_ENVIRONMENT")
# job_name = "123"
# job_url = "http://10.250.200.1:8080/jenkins/job/QA%E7%8E%AF%E5%A2%83%E5%B7%A1%E6%A3%80/2387/robot/report/report.html"
# enviroment = "PRODUCT"
dict_info = self.get_fail_test_case(son_node=root)
BUILD_INFO = dict_info.get("BUILD_INFO")
fail_info = dict_info.get("INFO")
list_phone = []
if BUILD_INFO:
for key, value in BUILD_INFO.items():
list_phone.append(list_name_phone.get(key))
print(list_phone)
print("+++++++{0}+++++{1}".format(job_name, job_url))
if re.search("PRODUCT", enviroment):
# message_data = {"msg_type": "text", "content": {
# "text": "线上巡检:线上环境出现了问题,请点击进行查看{0},以下是错误日志:{1}".format(job_url + "robot/report/report.html",fail_info)},
# "at": {"atMobiles": list_phone}}
at_user_list = [{"tag": "at", "user_id": "{}".format("7020366258071715842")}]
message_data = {"msg_type": "post", "content": {
"post": {"zh_cn": {"title": "线上环境巡检",
"content": [[{"tag": "text", "text": "线上环境出现了问题:"}],
[{"tag": "a", "text": "点击查看","href":"".format(job_url + "robot/report/report.html")}],
at_user_list]}}}}
print(message_data)
self.send_message_by_dingding(message_data,environment="product")
return enviroment
if re.search("QA", enviroment) or re.search("SIM", enviroment):
message_data = {"msg_type": "text", "content": {
"text": "{0}环境构建出问题了哦,请点击进行查看{1},以下是错误日志:{2}".format(enviroment, job_url + "robot/report/report.html",fail_info)},
"at": {"atMobiles": list_phone}}
print(message_data)
self.send_message_by_dingding(message_data)
return enviroment
for key, value in list_name_phone.items():
if re.search(key, job_name):
message_data = {"msg_type": "text", "content": {
"text": "亲爱的{0}同学,你的独立环境构建出问题了哦,请点击进行查看{1}".format(key, job_url + "robot/report/report.html")},
"at": {"atMobiles": [value]}}
self.send_message_by_dingding(message_data)
return value
else:
return "这个job:{}没有找到人".format(job_name)
def get_fail_test_case(self,son_node, father_node=None, grandpa_node=None):
"""
功能遍历xml文件的所有节点搜索构建失败的用例信息
"""
children_node = son_node.getchildren()
if len(children_node) == 0:
# if son_node.tag == 'doc':
# print(son_node.text)
# if son_node.tag == 'msg' and son_node.attrib['level'] == 'FAIL':
# # print(son_node.text)
# # print(son_node.attrib['timestamp'])
# print(children_node)
if son_node.tag == 'status' and son_node.attrib['status'] == 'FAIL' and 'critical' in son_node.attrib:
# print(father_node.attrib["name"])
tag = self.find_tags(father_node)
# a = self.find_error(father_node)
# print(a)
info_error = self.check_log_info(son_node.text)
INFO = "用例名称:" + father_node.attrib["name"] +"。人员:" + tag + "。失败日志:" + str(info_error)
run_time = son_node.attrib['endtime']
# print(info_error)
# print(son_node.text)
# self.check_log_info(text=son_node.text)
run_time = "{}-{}-{} {}".format(run_time[0:4], run_time[4:6], run_time[6:8], run_time[9:17])
reason = son_node.text.replace('"', '\\"')
# 满足构建时间,同时数据库中没有数据,才入库
# print(run_time)
if tag in BUILD_INFO:
BUILD_INFO[tag] += 1
else:
BUILD_INFO[tag] = 1
# print(BUILD_INFO)
# print(tag)
self.list_info.append(INFO)
self.dict_info["BUILD_INFO"] = BUILD_INFO
self.dict_info["INFO"] = self.list_info
# print(tag)
run_time = run_time
author = tag
case_name = father_node.attrib['name']
file_path = grandpa_node.attrib['source']
reason = reason[0:4500]
return self.dict_info
for child in children_node:
self.dict_info = self.get_fail_test_case(child, son_node, father_node)
return self.dict_info
def check_log_info(self,text):
'''
过滤精确日志信息
'''
soup = BeautifulSoup(text, features="lxml")
list_info = []
for a in soup.find_all(name='span'):
dict_info = {}
if a.text == "Old message:":
dict_info["old_message"] = a.nextSibling
list_info.append(dict_info)
elif a.text == "New message:":
dict_info["new_message"] = a.nextSibling
list_info.append(dict_info)
# print(a.nextSibling)
if list_info:
return list_info
else:
return text
def find_tags(self,root):
"""
功能在xml文件中搜索失败用对应的作者
"""
children_node = root.getchildren()
for child in children_node:
if child.tag == 'tags':
tags = child.getchildren()
for tag in tags:
if 'qa-' in tag.text.lower():
return tag.text[3:len(tag.text)]
return "无作者标签"
def find_error(self,root):
"""
功能在xml文件中查询失败日志
"""
children_node = root.getchildren()
for child in children_node:
if child.tag == 'kw':
msgs = child.getchildren()
for msg in msgs:
a = msg.tag
# t = msg.attrib['level']
l = msg.text
# print(msg.attrib['timestamp'])
if msg.tag == 'msg' and msg.attrib['level'] == 'FAIL':
print(msg.attrib)
s = msg.text
return msg.text
return ""
def run(self):
'''
运行入口
'''
# FILE_PATH = "D:/output2.xml"
FILE_PATH = os.path.abspath(os.path.join(WORKSPACE, 'Report/out/output.xml'))
root = ET.parse(FILE_PATH).getroot()
# self.get_fail_test_case(son_node=root)
self.handle_send_message(root=root)
if __name__ == '__main__':
test = handle_to_jenkins()
# FILE_PATH = "D:/output1.xml"
# FILE_PATH = os.path.abspath(os.path.join(WORKSPACE, 'Report/out/output.xml'))
# root = ET.parse(FILE_PATH).getroot()
# print(test.get_fail_test_case(son_node=root))
test.run()
# test.handle_send_message(root=root)

View File

@@ -0,0 +1,331 @@
# -*- coding:utf-8 -*-
"""
人员当日jira任务、故事状态流转
"""
import os, sys
file_dir = os.path.dirname(__file__)
project_dir = os.path.abspath(os.path.join(file_dir, "..", "..", ".."))
sys.path.append(project_dir)
from jira import JIRA
from base_framework.public_tools.utils import Tools
from base_framework.public_tools.read_config import ReadConfig
from base_framework.platform_tools.Message_service.Feishu_api import FeiShuMessage,get_user_name_by_email_prefix,get_feishu_config_value
from configparser import ConfigParser
from base_framework.base_config.current_pth import *
import datetime
tools = Tools()
ReadConfig = ReadConfig(filename=la_config_path)
FS_INFO = [{"team": "TO", "users": "wuyonggang,xuwenjun,luohong"},
{"team": "TO-RD", "users": "fengtian,guosongchao,zhaoxiaofang,"
"zhuliang,majincheng,gaozhijun,liuxuegang,"
"zhangxiong"},
{"team": "USER-FE", "users": "zhaofei,liuxinlin,qingchen,yefei,xiangming,jianghao,jianglingmin,xuchangle,"
"libaicheng,gouyuheng,jixiang.dong,baiyang01"}
]
class JiraApi:
def __init__(self):
self.jira = JIRA(server='https://jira.bg.huohua.cn/',
basic_auth=("wuyonggang", "Mima@123"))
def close_jira_subtask(self, user_name):
"""
功能: 关闭指定人员名下当天结束的子任务
请求参数 user_name 指定人员jira登录名type: list
"""
bad_name = []
right_name = []
for j in user_name:
if j not in ReadConfig.get_sections():
bad_name.append(j)
elif j in ReadConfig.get_sections():
right_name.append(j)
success = []
false = []
today_time = tools.get_format_date(r_type=1)
work_start_time = datetime.datetime.strptime('{0} 10:00:00'.format(today_time), '%Y-%m-%d %H:%M:%S')
for name in right_name:
jira = JIRA(server='https://jira.bg.huohua.cn/', basic_auth=(name, ReadConfig.get_value(name, 'password')))
jql = 'project = HHC AND issuetype = 子任务 AND status in (重新打开, 启动, 需求池, 暂停, 计划, 产品需求设计,' \
' 产品需求内审, 需求评审, 排期, 执行, 开发, 待测试, QA测试, SIM验证, 验证中, 待办, 处理中, 关闭) AND resolution = Unresolved' \
' AND (QA in ({0}) OR assignee in ({1})) ORDER BY priority DESC, updated DESC'.format(name,name)
issues = jira.search_issues(jql, fields='')
# if len(issues) == 0: break
not_need_closed = 0
for i in issues:
s = list(jira.transitions(i))
close_status_id = [x['id'] for x in s if x['name'] == '关闭']
if str(i.fields.status) == '处理中':
if i.fields.aggregatetimeestimate != None:
if i.fields.aggregatetimeestimate > 28800:
jira.add_worklog(i, timeSpent='7', started=work_start_time)
elif 0 < i.fields.aggregatetimeestimate <= 28800:
jira.add_worklog(i, timeSpent='{0}'.format(i.fields.aggregatetimeestimate / 3600),
started=work_start_time)
else:
jira.add_worklog(i, timeSpent='8', started=work_start_time)
if str(i.fields.status) == '处理中' and str(i.fields.customfield_13406) == today_time:
jira.transition_issue(i, int(close_status_id[0]))
else:
not_need_closed += 1
issues2 = jira.search_issues(jql, fields='')
if not_need_closed == len(issues2):
success.append(name)
else:
false.append(name)
return "{0}今日结束的子任务已关闭成功; {1}今日结束的子任务关闭失败; {2}没有进行账号配置".format(success, false, bad_name)
def start_jira_subtask(self, user_name):
"""
功能: 将待开始为今天的子任务状态流转为“处理中”
请求参数 user_name 指定人员jira登录名type: list
"""
bad_name = []
right_name = []
for j in user_name:
if j not in ReadConfig.get_sections():
bad_name.append(j)
elif j in ReadConfig.get_sections():
right_name.append(j)
success = []
false = []
for name in right_name:
jira = JIRA(server='https://jira.bg.huohua.cn/', basic_auth=(name, ReadConfig.get_value(name, 'password')))
jql = 'project = HHC AND issuetype = 子任务 AND status in (重新打开, 启动, 需求池, 暂停, 计划, 产品需求设计, 产品需求内审, 需求评审, ' \
'排期, 执行, 开发, 待测试, QA测试, SIM验证, 验证中, 待办, 关闭) AND resolution = Unresolved' \
' AND (QA in ({0}) OR assignee in ({1})) ORDER BY priority DESC, updated DESC'.format(name,name)
today_time = tools.get_format_date(r_type=1)
issues = jira.search_issues(jql, fields='')
# if len(issues) == 0: break
not_need_update = 0
for i in issues:
s = list(jira.transitions(i))
start_status_id = [x['id'] for x in s if x['name'] == '处理中']
if str(i.fields.status) == '待办' and str(i.fields.customfield_12700) == today_time:
jira.transition_issue(i, int(start_status_id[0]))
else:
not_need_update += 1
issues2 = jira.search_issues(jql, fields='')
if not_need_update == len(issues2):
success.append(name)
else:
false.append(name)
return "{0}今日开始的子任务已将状态修改为“处理中”‘; {1}今日开始的子任务状态修改失败; {2}没有进行账号配置".format(success, false, bad_name)
def change_story(self, user_name, type):
"""
功能: 将提测时间为今天的指定人员名下的故事状态修改至“QA测试”
请求参数 user_name 指定人员jira登录名type: list
type (故事需要修改至的状态 1提测日为今天状态修改至【QA测试】 2上线日为今天状态修改至【关闭】)
"""
bad_name = []
right_name = []
for j in user_name:
if j not in ReadConfig.get_sections():
bad_name.append(j)
elif j in ReadConfig.get_sections():
right_name.append(j)
success = []
false = []
for name in right_name:
jira = JIRA(server='https://jira.bg.huohua.cn/', basic_auth=(name, ReadConfig.get_value(name, 'password')))
jql = "project = HHC AND issuetype = 故事 AND " \
"status in (重新打开, 启动, 需求池, 暂停, 计划, 产品需求设计, 产品需求内审, 需求评审, 排期, 执行, 开发, 待测试, 验证中, 待办, QA测试, SIM验证, 处理中, 关闭)" \
" AND resolution = Unresolved AND QA in ({0}) ORDER BY priority DESC, updated DESC".format(name)
today_time = tools.get_format_date(r_type=1)
issues = jira.search_issues(jql, fields='')
# if len(issues) == 0 : break
x = 0
need_update = 0
if type == 1: # 将故事状态一直流转至“QA测试”
for i in issues:
if str(i.fields.status) == 'QA测试' or str(i.fields.status) == 'SIM验证': need_update += 1
if str(i.fields.customfield_10504) == today_time:
if str(i.fields.status) != 'QA测试' and str(i.fields.status) != 'SIM验证':
need_update += 1
for j in range(8):
jira.transition_issue(i, int(jira.transitions(i)[2]['id']))
issues_2 = jira.search_issues(jql, fields='') # 重新获取所有故事
status_now = issues_2[x].fields.status
print(status_now)
if str(status_now) == 'QA测试' or str(status_now) == 'SIM验证':
break
x += 1
jql2 = "project = HHC AND issuetype = 故事 AND " \
"status in (重新打开, 启动, 需求池, 暂停, 计划, 产品需求设计, 产品需求内审, 需求评审, 排期, 执行, 开发, 待测试, 验证中, 待办, 处理中, 关闭)" \
" AND resolution = Unresolved AND QA in ({0}) ORDER BY priority DESC, updated DESC".format(name)
issues2 = jira.search_issues(jql2, fields='')
if len(issues2) == len(issues) - need_update:
success.append(name)
else:
false.append(name)
elif type == 2: # 直接将故事关闭
for i in issues:
if str(i.fields.customfield_10606) == today_time:
jira.transition_issue(i, int(jira.transitions(i)[1]['id']), comment="已上线") # 将故事修改为关闭状态
need_update += 1
issues2 = jira.search_issues(jql, fields='')
if len(issues2) + need_update == len(issues):
success.append(name)
else:
false.append(name)
return "{0}今日的故事已将状态修改成功!; {1}今日的故事状态修改失败; {2}没有进行账号配置".format(success, false, bad_name)
def change_jira_status(self, user_name):
"""
功能: 判断当前时间是否在下午18:00点以前来选择打开或关闭【子任务】和【故事】
请求参数 user_name 指定人员jira登录名type: list
"""
time_now = tools.get_format_date(r_type=4)
time_now2 = '{0} 18:00:00'.format(time_now[0:10:1])
if time_now < '{0} 18:00:00'.format(time_now2):
a = self.start_jira_subtask(user_name)
b = self.change_story(user_name, type=1)
return a + '\n' + b
elif time_now >= '{0} 18:00:00'.format(time_now2):
a = self.close_jira_subtask(user_name)
b = self.change_story(user_name, type=2)
return a + '\n' + b
def query_jira_subtask(self, user_name, begin_date=0, end_date=0):
"""
| 功能 | 查询用户对应的jira子任务 |
| 入参 | user_name | 用户名字 |
| | begin_date | 开始时间0-今天X-未来X天-X-过去的X天 |
| | end_date | 开始时间0-今天X-未来X天-X-过去的X天 |
"""
b_date = tools.get_format_date(r_type=1, add_days=int(begin_date))
e_date = tools.get_format_date(r_type=1, add_days=int(end_date))
jql = "issuetype = 子任务 AND 计划开始时间 <= {} AND 计划结束时间 >= {} AND assignee in ({}) ORDER BY cf[12700] ASC"\
.format(b_date, e_date, user_name)
issues = self.jira.search_issues(jql, fields='')
# print(jql)
return issues
# for item in issues:
# print("{0}:{1}, 当前状态:{2}".format(item.key, item.fields.summary, item.fields.status))
def query_jira_by_id(self, jira_id):
"""
| 功能 | 跟进jira的id查询具体详情 |
| 入参 | jira_id | jira的id |
"""
jql = "id={}".format(jira_id)
issues = self.jira.search_issues(jql, fields='')
if len(issues) == 0:
raise Exception("根据jira_id未查询到对应的jira信息请检查....")
rd = issues[0].fields.assignee.displayName
qa = issues[0].fields.reporter.displayName
title = issues[0].fields.summary
status = issues[0].fields.status
j_time = issues[0].fields.created
j_time = j_time[0:10] + ' ' + j_time[11:19]
return {"jira_rd": rd,
"jira_qa": qa,
"jira_title": title,
"jira_time": j_time,
"jira_status": str(status)}
def query_overdue_issues(self, user_name):
"""
| 功能 | 查询逾期的子任务和故事 |
| 入参 | 无 |
"""
today = tools.get_format_date()
check_time = tools.get_format_date(r_type=4)
if check_time < "{} 17:00:00".format(today):
jql = "issuetype in (故事,子任务) AND (计划结束时间<now() OR 计划上线时间<now()) AND status!=关闭 AND " \
"(assignee={0} OR QA={0})".format(user_name)
else:
jql = "issuetype in (故事,子任务) AND (计划结束时间<=now() OR 计划上线时间<=now()) AND status!=关闭 AND " \
"(assignee={0} OR QA={0})".format(user_name)
issues = self.jira.search_issues(jql, fields='')
return issues
def check_overdue_issues(self):
"""检查预期未关闭的故事和子任务"""
today = tools.get_format_date()
fs = FS_INFO[0]
user_list = fs['users'].split(',')
remind_info = []
for user in user_list:
issues = self.query_overdue_issues(user_name=user)
if issues:
for issue in issues:
issue_info = [user, issue.key]
remind_info.append(issue_info)
if remind_info:
msg = "【JIRA任务延期提醒{}】:\n".format(today)
for info in remind_info:
user_name = get_user_name_by_email_prefix(email_prefix=info[0])
open_id = get_feishu_config_value(option_key=user_name)
at_msg = " |--<at user_id='{}'>{}</at>".format(open_id, user_name)
msg = msg + at_msg + ": https://jira.bg.huohua.cn/browse/{}\n".format(info[1])
msg = msg + " |--请及时关闭以上逾期任务..."
print(msg)
fs = FeiShuMessage(team=fs['team'])
fs.send_text(msg=msg)
else:
print("++++++++++++++++++++++")
print("| 所有任务或故事均已关闭 |")
print("++++++++++++++++++++++")
def check_pdp_standard(self):
"""查找当天有无子任务,没有则发送飞书消息提醒"""
# 非工作日构建
today = tools.get_format_date()
if not tools.check_the_date_is_a_working_day(today):
print("### 非工作日,不检查....")
return False
for fs in FS_INFO:
user_list = fs['users'].split(',')
need_remind_user = []
for user in user_list:
issues = self.query_jira_subtask(user_name=user)
if not issues:
need_remind_user.append(user)
if need_remind_user:
msg = "【JIRA子任务提醒{}】:\n |--".format(today)
for user in need_remind_user:
user_name = get_user_name_by_email_prefix(email_prefix=user)
open_id = get_feishu_config_value(option_key=user_name)
at_msg = "<at user_id='{}'>{}</at>".format(open_id, user_name)
msg = msg + at_msg
msg = msg + "\n |--请及时添加与今日工作对应的子任务哦..."
print(msg)
fs = FeiShuMessage(team=fs['team'])
fs.send_text(msg=msg)
else:
print("++++++++++++++++++++++++++++++++")
print("| {} 满足pdp规范无须提示 |".format(fs['team']))
print("++++++++++++++++++++++++++++++++")
if __name__ == '__main__':
# 关闭自动修改jira的代码不要再打开了...
# lp = Jira_About()
# print(lp.change_jira_status(['liupeng', 'zhourenhua', 'xuwenjun', 'lichao04', 'wanggang02', 'baoli']))
# 以下内容若有修改请勿上传否则会影响jira监控的每日构建
# 1.获取命令行参数
cmd_params = sys.argv
try:
index = cmd_params.index('-t')
except ValueError:
raise Exception("类型参数必填pdp-检查PDP规范overdue-检查预期未关闭的故事和子任务....")
else:
check_type = cmd_params[index + 1]
if check_type.lower() not in ("pdp", "overdue"):
raise Exception("目前仅支持pdp和overdue但你输入的是{}".format(check_type))
jira = JiraApi()
if check_type.lower() == "pdp":
jira.check_pdp_standard()
elif check_type.lower() == "overdue":
jira.check_overdue_issues()

View File

@@ -0,0 +1,45 @@
import requests
def fetch_kibana_logs(query, time_range, index_pattern):
kibana_url = "https://logstashlog-kibana.qc.huohua.cn/login" # 替换为实际的Kibana URL
search_endpoint = f"{kibana_url}/app/kibana" # Kibana搜索API的URL
headers = {
"Content-Type": "application/json",
}
user = "elastic"
pwd = "s3dr40O,&j"
payload = {
"query": query,
"timeRange": time_range,
"index": index_pattern
}
try:
response = requests.post(kibana_url, headers=headers,auth=(user, pwd), json=payload)
response.raise_for_status()
logs = response.json()
# 处理日志数据
# ...
return logs
except requests.exceptions.RequestException as e:
print(f"Error fetching Kibana logs: {str(e)}")
return None
query = "error" # 搜索关键字
time_range = "now-1d/d" # 过去一天内的日志
index_pattern = "my-logs-*" # 匹配以 "my-logs-" 开头的索引
logs = fetch_kibana_logs(query, time_range, index_pattern)
if logs:
# 处理日志数据
for log in logs:
# 对每条日志进行操作
print(log)
else:
# 处理错误情况
print("Failed to fetch Kibana logs.")

View File

@@ -0,0 +1,204 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: qiaoxinjiu@sparkedu.com
Create Date: 2022/05/08 5:58 下午
"""
import os
from urllib import parse
from base_framework.public_tools import read_config
import requests
import sys
import json
class auth_login():
def __init__(self):
self.config_login_path = os.path.dirname(os.path.abspath(__file__))
self.config_login_filePath = os.path.join(self.config_login_path, "../Config/team_config.ini")
self.config_login_content = read_config.ReadConfig(filename=self.config_login_filePath)
def get_json_result(self, url, request_data=None, headers=None, send_way="GET"):
"""
# url: 测试的url
# request_data: url请求时发送的数据
# headers: url请求时发送的消息头
# 功能获取json格式的数据
"""
if send_way == "GET":
response = requests.request(send_way, url, headers=headers, params=json.dumps(request_data))
else:
response = requests.request(send_way, url, headers=headers, data=json.dumps(request_data))
try:
response_data = json.loads(response.text)
except:
info = sys.exc_info()
response_data = info[1], info[2]
return response_data
def get_m_online_token(self):
'''
获取家长端线上登录的token
:param username:
:param password:
:return:
'''
headers = {
"Content-Type": "application/json;charset=UTF-8",
"sso-client-id": "gmp"
}
get_login_info = eval(
self.config_login_content.get_value(sections="m-userinfo", options="login_parent_info")) # 获取配置文件中的默认请求参数值
get_url_info = eval(self.config_login_content.get_value(sections="m-userinfo", options="parent_url"))
m_token = requests.post(url=get_url_info.get("login_url"), json=get_login_info, verify=False, headers=headers)
if m_token.status_code == 200:
token = m_token.json()
token = token['data']['token']
return token
else:
raise KeyError('获取 parent token失败')
def get_student_online_token(self):
'''
获取学生端线上登录的token
:param username:
:param password:
:return:
'''
headers = {
"Content-Type": "application/json;charset=UTF-8",
"sso-client-id": "gmp"
}
get_login_info = eval(
self.config_login_content.get_value(sections="m-userinfo", options="login_student_info")) # 获取配置文件中的默认请求参数值
get_url_info = eval(self.config_login_content.get_value(sections="m-userinfo", options="student_url"))
m_token = requests.post(url=get_url_info.get("login_url"), json=get_login_info, verify=False, headers=headers)
if m_token.status_code == 200:
token = m_token.json()
token = token['data']['token']
return token
else:
raise KeyError('获取 parent token失败')
def get_m_headers(self, m_token):
'''
获取请求的header
:return:
'''
headers = {
"Content-Type": "application/json;charset=UTF-8",
"sso-client-id": "gmp",
"user-token": m_token,
}
return headers
def get_parent_config_info(self, url_name):
'''
获取家长端配置文件中的url信息
:return:
'''
get_parent_url_info = eval(self.config_login_content.get_value(sections="m-userinfo", options="parent_url"))
get_realm_name = eval(self.config_login_content.get_value(sections="m-userinfo", options="realm_name"))
get_url = get_realm_name.get("parent_api") + get_parent_url_info.get(url_name)
return get_url
def get_visaprk_parent_config_info(self, url_name):
'''
获取海外家长端配置文件中的url信息
:return:
'''
get_parent_url_info = eval(self.config_login_content.get_value(sections="m-userinfo", options="parent_course_url"))
get_realm_name = eval(self.config_login_content.get_value(sections="m-userinfo", options="realm_name"))
get_url = get_realm_name.get("parent_vispark_api") + get_parent_url_info.get(url_name)
return get_url
def get_student_config_info(self, url_name):
'''
获取学生端配置文件中的url信息
:return:
'''
get_student_url_info = eval(self.config_login_content.get_value(sections="m-userinfo", options="student_url"))
get_realm_name = eval(self.config_login_content.get_value(sections="m-userinfo", options="realm_name"))
get_url = get_realm_name.get("student_api") + get_student_url_info.get(url_name)
return get_url
class m_parent():
def __init__(self):
self.get_url = auth_login()
def get_parentPayEditionPage(self):
'''
首页轮播页面展示
:return:
'''
m_token = self.get_url.get_m_online_token()
headers = self.get_url.get_m_headers(m_token=m_token)
url = self.get_url.get_parent_config_info(url_name="parentPayEditionPage_url")
get_response_data = self.get_url.get_json_result(url=url, headers=headers, request_data={"terminalType": 5})
return get_response_data
def get_recommendedCourse(self):
'''
家长端获取课程信息
:return:
'''
m_token = self.get_url.get_m_online_token()
headers = self.get_url.get_m_headers(m_token=m_token)
url = self.get_url.get_parent_config_info(url_name="recommendedCourse_url")
get_response_data = self.get_url.get_json_result(url=url, headers=headers)
return get_response_data
def get_trial_level(self,courseSubtype):
'''
获取试听课级别
ap为21cp为20
:return:
'''
m_token = self.get_url.get_m_online_token()
headers = self.get_url.get_m_headers(m_token=m_token)
url = self.get_url.get_visaprk_parent_config_info(url_name="get_trial_url")
request_url = url +"?courseSubtype={0}&subjectType=1".format(courseSubtype)
get_response_data = self.get_url.get_json_result(url=request_url, headers=headers)
# 针对ap或者cp获取级别查看是否存在重复的level
list_level = []
for trial_data in get_response_data.get("data"):
list_level.append(trial_data.get("level"))
set_level = set(list_level)
dict_response = {}
for level in set_level:
if list_level.count(level) > 1:
dict_response[level] = list_level.count(level)
if dict_response:
return {"code":500,"data":dict_response}
else:
return {"code":200,"data":dict_response}
class student_verity():
def __init__(self):
self.get_url = auth_login()
def get_schedule_count(self):
'''
:return:
'''
m_token = self.get_url.get_m_online_token()
headers = self.get_url.get_m_headers(m_token=m_token)
url = self.get_url.get_student_config_info(url_name="scheduleCount_url")
print(url)
get_response_data = self.get_url.get_json_result(url=url, headers=headers, request_data={"subjectType": 4})
return get_response_data
if __name__ == '__main__':
test = auth_login()
test1 = m_parent()
test2 = student_verity()
# print(test.get_student_online_token())
# print(test1.get_recommendedCourse())
print(test1.get_trial_level(courseSubtype=22))
# print(test2.get_schedule_count())

View File

@@ -0,0 +1,19 @@
import pika
# 设置RabbitMQ服务器的连接参数使用自定义端口9876
connection_params = pika.ConnectionParameters('rocketmq.qa.huohua.cn', 9876)
connection = pika.BlockingConnection(connection_params)
channel = connection.channel()
# 声明一个队列,如果队列不存在则会创建
queue_name = 'my_queue'
channel.queue_declare(queue=queue_name)
# 发布消息到指定的队列
message = 'Hello, World!'
channel.basic_publish(exchange='',
routing_key=queue_name,
body=message)
print(f" [x] Sent '{message}'")
# 关闭连接
connection.close()

View File

@@ -0,0 +1,56 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: qiaoxinjiu@sparkedu.com
Create Date: 2022/05/08 5:58 下午
"""
import os
from PIL import Image
def image_gray(img):
# 打开图片
img = Image.open(img)
# 计算平均灰度值
gray_sum = 0
count = 0
for x in range(img.width):
for y in range(img.height):
if img.mode == "RGB":
r, g, b = img.getpixel((x, y))
gray_sum += (r + g + b) / 3
elif img.mode == "L":
gray_value = img.getpixel((x, y))
gray_sum += gray_value
count += 1
avg_gray = gray_sum / count
return avg_gray
def find_image(folder_path):
# 定义一个列表存储图片路径
images = []
# 遍历文件夹下的所有文件
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
# 处理每个文件,将其添加到列表中
images.append(file_path)
return images
def assert_run(folder_path):
images = find_image(folder_path)
for img in images:
gray = image_gray(img)
# 灰度值小于50将认为是黑图
if gray < 50:
print(img, "", gray)
if __name__ == "__main__":
# image_gray()
# find_image()
folder_path = r'D:\picture'
assert_run(folder_path)

View File

@@ -0,0 +1,211 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: xinjiu.qiao@allschool.com
Create Date: 2022/04/26 5:58 下午
"""
import os
import sys
input_team_name = sys.argv
BASIC_PATH = os.path.dirname(os.path.abspath(__file__))
TEAM_PATH = os.path.abspath(os.path.join(BASIC_PATH, '../../../{}'.format("base_framework")))
sys.path.append(TEAM_PATH)
PROJECT_PATH = os.path.abspath(os.path.join(BASIC_PATH, '../../..'))
sys.path.append(PROJECT_PATH)
from base_framework.public_tools.sqlhelper import MySqLHelper
import json
import requests
obj_mysql_helper = MySqLHelper()
class Handle_tools:
def __init__(self):
pass
def query_interface_sql(self):
'''
查询qa的余量接口信息
:return:
'''
query_sql = ''' SELECT in_url,controller_name
FROM
sparkatp.interface_info
WHERE
id IN (
SELECT
a.id
FROM
(SELECT * from sparkatp.interface_info) a
WHERE
( a.swagger_id in (SELECT id FROM sparkatp.swagger_info WHERE team="UBRD") )
AND a.created_time > "2022-01-01 00:00:50"
AND is_used = 1 and at_numbers = 0 and offline=0 and jira_id is null) ORDER BY created_time'''
query_sql_r = """SELECT
si.id AS interface_id,
rpgm.jira_id,
si.in_url
FROM
(
SELECT
ii.id,
ii.in_url,
ii.jira_id
FROM
sparkatp.interface_info ii
WHERE
ii.swagger_id IN ( SELECT id FROM sparkatp.swagger_info WHERE team = "UBRD" )
AND ii.created_time > "2022-01-01 00:00:50"
AND ii.is_used = 1
AND ii.at_numbers = 0
AND ii.offline = 0
AND ii.jira_id IS NULL
) si
INNER JOIN (
SELECT
rp.interface_id,
rp.jira_id,
MAX( modified_time )
FROM
request_parameters rp
WHERE
rp.jira_id IS NOT NULL
AND rp.jira_id <> 'None'
AND rp.jira_id <> ''
GROUP BY
rp.interface_id
) rpgm ON rpgm.interface_id = si.id;"""
# query_sql = " SELECT * FROM sparkatp.interface_info WHERE id IN (SELECT a.id FROM(SELECT * from sparkatp.interface_info) a WHERE( a.swagger_id in (SELECT id FROM sparkatp.swagger_info WHERE team='UBRD') ) AND a.created_time > '2022-01-01 00:00:50' AND is_used = 1 and at_numbers = 0 and offline=0 and jira_id is null) ORDER BY created_time"
query_sql_r_result = obj_mysql_helper.select_all(query_sql_r)
query_sql_dict = {}
query_sql_dict_temp = {}
# <class 'dict'>: {'interface_id': 924646, 'jira_id': 'HHC-48875', 'in_url': 'http://peppa-parent-api.qa.huohua.cn/classes/audition/enter'}
for qsrr in query_sql_r_result:
in_url = "{}_{}".format(str(qsrr.get('interface_id')).strip(' '), qsrr.get('in_url').strip(' '))
if qsrr.get('jira_id') in query_sql_dict.keys():
if in_url in query_sql_dict.get(qsrr.get('jira_id')):
pass
else:
query_sql_dict[qsrr.get('jira_id')].append(in_url)
else:
query_sql_dict[qsrr.get('jira_id')] = [in_url]
query_sql_s = """SELECT
si.id AS interface_id,
rpgm.jira_id,
si.in_url
FROM
(
SELECT
ii.id,
ii.in_url,
ii.jira_id
FROM
sparkatp.interface_info ii
WHERE
ii.swagger_id IN ( SELECT id FROM sparkatp.swagger_info WHERE team = "UBRD" )
AND ii.created_time > "2022-01-01 00:00:50"
AND ii.is_used = 1
AND ii.at_numbers = 0
AND ii.offline = 0
AND ii.jira_id IS NULL
) si
INNER JOIN (
SELECT
rp.interface_id,
rp.jira_id,
MAX( modified_time )
FROM
response_parameters rp
WHERE
rp.jira_id IS NOT NULL
AND rp.jira_id <> 'None'
AND rp.jira_id <> ''
GROUP BY
rp.interface_id
) rpgm ON rpgm.interface_id = si.id;"""
query_sql_s_result = obj_mysql_helper.select_all(query_sql_s)
for qsrs in query_sql_s_result:
in_url = "{}_{}".format(str(qsrs.get('interface_id')).strip(' '), qsrs.get('in_url').strip(' '))
if qsrs.get('jira_id') in query_sql_dict.keys():
if in_url in query_sql_dict[qsrs.get('jira_id')]:
pass
else:
query_sql_dict[qsrs.get('jira_id')].append(in_url)
else:
query_sql_dict[qsrs.get('jira_id')] = [in_url]
return query_sql_dict
def send_log_info(self):
'''
每天进行日志提醒
:return:
'''
feishu_name_id = {"罗志鹏": "7020366259502153730", "谯新久": "7020366258071715842",
"陈洁": "7020370251997069314", "蒲思宇": "7076270364313108481", "张楠": "7076270369128349697",
"刘涛婷": "7020366262240854017"}
order_list = ["谯新久", "陈洁", "刘涛婷", "罗志鹏", "蒲思宇", "张楠"]
# for name in order_list:
def send_feishu(self, inferfaces):
'''
发送飞书
:return:
'''
at_user_list = [{"tag": "at", "user_id": "{}".format("7020366259502153730")}]
message_data = {"msg_type": "post", "content": {
"post": {"zh_cn": {"title": "有存在的接口未实现自动化哦",
"content": [[{"tag": "text", "text": "问题数据:"}],
[{"tag": "text", "text": "{}".format(inferfaces)}],
at_user_list]}}}}
web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/40696c86-264a-4222-a40c-cfd64a05dffd"
headers = {"Content-Type": "application/json"}
json_data = json.dumps(message_data)
print(json_data)
rsp = requests.post(url=web_hook, data=json_data, headers=headers)
return rsp
def send_message_by_feishu(self, web_hook, data):
headers = {"Content-Type": "application/json"}
json_data = json.dumps(data)
rsp = requests.post(url=web_hook, data=json_data, headers=headers)
return rsp
def compare_txt(self, su_t, st_t):
'''
对比两个文档,返回不同的信息
:param su_t:
:param st_t:
:return:
'''
file_object1 = open(su_t, 'r', encoding='utf-8')
file_object2 = open(st_t, 'r', encoding='utf-8')
try:
while True:
line = file_object1.readline()
lines = file_object2.readline()
if line.strip() != lines.strip():
print("pc :", line)
print("right:", lines)
else:
continue
finally:
file_object1.close()
file_object2.close()
if __name__ == '__main__':
test = Handle_tools()
# get_interfaces = test.query_interface_sql()
# if get_interfaces:
# test.send_feishu(json.dumps(get_interfaces))
# else:
# print("都已经完成")
su_t = r"D:\UiVispark\spark1.txt"
st_t = r"D:\UiVispark\spark2.txt"
test.compare_txt(st_t=st_t,su_t=su_t)

View File

@@ -0,0 +1 @@
host_list = [{"ip":'127.0.0.1',"host_names":"ts.sim.huohua.cn"},{"ip":'127.0.0.1',"host_names":"student-api.sim.huohua.cn"}]

View File

@@ -0,0 +1,263 @@
# -*- coding:utf-8 -*-
# @Time : 2023/7/5 10:27
# @Author: luozhipeng
# @File : host_update.py
import os
from python_hosts import Hosts, HostsEntry
import sys
LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
BASE_PROJECT_PATH = os.path.abspath(os.path.join(LOCAL_PATH, '../../../{}'.format("UBRD")))
BASIC_PATH = os.path.abspath(os.path.join(LOCAL_PATH, '../../../'))
sys.path.append(BASE_PROJECT_PATH)
sys.path.append(BASIC_PATH)
from base_framework.public_tools.utils import Tools
from base_framework.public_tools.apollo import Apollo
import requests, time
import os
import sys
import socket
import subprocess
import requests
import urllib.parse
obj_apollo = Apollo()
obj_tools = Tools()
class HostUpdate:
def __init__(self):
if sys.platform.startswith('win'):
self.hosts_location = Hosts(path='C:\Windows\System32\drivers\etc\hosts')
elif sys.platform.startswith('darwin'):
self.hosts_location = Hosts(path='\etc\hosts')
def host_update_by_host_dict(self, host_dict_list: list):
entry_list = []
for host in host_dict_list:
new_entry = HostsEntry(entry_type='ipv4', address=host['ip'], names=[host['host_name'], ''])
entry_list.append(new_entry)
self.hosts_location.add(entry_list)
self.hosts_location.write()
def host_remove_intercept(self,address,name):
self.hosts_location.remove_all_matching(address,name)
self.hosts_location.write()
def get_ip_by_host_domain(self,domain: str):
ip=socket.gethostbyname(domain)
return ip
def wait_dns_flush(self,ip,domain):
count=1
while True:
cmd1="ipconfig /flushdns"
result1=subprocess.run(cmd1,capture_output=True,text=True)
output1=result1.stdout
print(output1)
cmd2="ping {}".format(domain)
result2=subprocess.run(cmd2,capture_output=True,text=True)
output2=result2.stdout
print(output2)
cmd="ipconfig /displaydns"
result=subprocess.run(cmd,capture_output=True,text=True)
output=result.stdout
print(output)
if output is None:
output=''
if ip in output:
break
if count >= 30:
break
count=count + 1
host_list=[{"ip": ip,"host_name": domain}]
self.host_remove_intercept(ip,domain)
self.host_update_by_host_dict(host_list)
time.sleep(2)
class CoreApollo:
def __init__(self,show_username=None,password=None,current_evn=None):
if not show_username:
self.show_username="liuruiquan"
if not password:
self.password="lrq5823LRQ"
self.apollo_url="http://apollo.qa.huohua.cn/signin"
if not current_evn:
self.current_evn="SIM"
self.apollo_host="http://apollo.qa.huohua.cn"
self.session=self.core_apollo_login()
def core_apollo_login(self):
post_data=dict()
post_data['login-submit']='登录'
post_data['username']=self.show_username
post_data['password']=self.password
req_session=requests.Session()
resp=req_session.post(url=self.apollo_url,data=post_data)
return req_session
def get_key(self,server,cluster,key,project):
req_url="%s/apps/%s/envs/%s/clusters/%s/namespaces" % (
self.apollo_host,server,self.current_evn,cluster)
resp=self.session.get(url=req_url).json()
for item in resp:
base_info=item.get('baseInfo')
items=item.get('items')
if not base_info['namespaceName'].lower() == project.lower():
continue
for key_info in items:
item_detail=key_info["item"]
if item_detail["key"] == key:
return key_info["item"]
else:
return None
def set_key(self,key,value,cluster='default',server="",project=None):
if server:
self.server=server
req_url="%s/apps/%s/envs/%s/clusters/%s/namespaces/%s/item" % (
self.apollo_host,self.server,self.current_evn,cluster,project)
items=self.get_key(server,cluster,key,project)
if items is None:
items=dict()
items["value"]=value
items["key"]=key
items["tableViewOperType"]='create'
items["addItemBtnDisabled"]=True
else:
items["value"]=value
items["tableViewOperType"]='update'
update_resp=self.session.put(url=req_url,json=items)
assert update_resp.status_code == 200
release_body=dict()
release_time_stamp=time.localtime()
release_time='%s-release' % time.strftime("%Y%m%d%H%M%S",release_time_stamp)
release_body["isEmergencyPublish"]=False
release_body["releaseComment"]=""
release_body["releaseTitle"]=release_time
release_url="%s/apps/%s/envs/%s/clusters/%s/namespaces/%s/releases" % (
self.apollo_host,self.server,self.current_evn,cluster,project)
resp=self.session.post(url=release_url,json=release_body)
assert resp.status_code == 200
time.sleep(5)
def set_user_force_true(self,vlaue="true"):
self.set_key(value=vlaue,key="user-token.forceFallback",server="peppa-core-api",cluster="check"
,project="application")
def set_teacher_force_true(self,vlaue="true"):
self.set_key(value=vlaue,key="sso-token.forceFallback",server="peppa-core-api",cluster="check"
,project="application")
class EduClassroom:
def kw_ubrd_get_online_test_classroom(self,post_data_input=None):
post_data = dict()
host = "sso.huohua.cn"
api_url = "https://{}/authentication/form".format(host)
show_username = "liuruiquan"
username = "liuruiquan"
password = "lrq5823LRQ"
post_data['showUsername'] = show_username
post_data['username'] = username
post_data['password'] = password
user_agent = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
deviceid = {"SSO_DEVICE_ID":"8dfbecf2-064a-4e3f-ac2b-fc09a2401416"}
req_session = requests.session()
req_session.cookies.update(deviceid)
req_session.headers.update(user_agent)
resp = req_session.post(
url=api_url,
data=post_data,
allow_redirects=False)
# token_header = {"accesstoken": token}
# req_session.headers.update(token_header)
# print(token_header)
client_id = "tic-payment-admin"
origin_url="aHR0cHM6Ly9zc28uaHVvaHVhLmNuLw=="
# origin_url="aHR0cHM6Ly9zc28uc2ltLmh1b2h1YS5jbi8="
redirect_uri = "https://{}/uim/authorize_proxy?client_id={}&debug_mode=1&origin_url={}".format(host,client_id,origin_url)
print(redirect_uri)
token_code_url = "https://{}/oauth/authorize?client_id={}&response_type=code&".format(host,client_id,redirect_uri)
authorize_data = {"redirect_uri": redirect_uri}
authorize_data_uri =urllib.parse.urlencode(authorize_data)
resp = req_session.get(
url=token_code_url+authorize_data_uri,
data=authorize_data,
allow_redirects=False)
print(resp.url)
print(resp.headers)
print(resp)
# token_url = "https://{}/uim/authorize_proxy?client_id={}&debug_mode=1&origin_url={}&code={}".format(host,client_id,origin_url,code)
token_url= resp.headers["Location"]
# authorize_code_data = {"client_id":"tic-payment-admin","debug_mode": 1,"origin_url": origin_url,"code":code}
print(token_url,"token_url")
# print(authorize_code_data)
resp = req_session.get(
url=token_url,
# data=authorize_code_data,
allow_redirects=False)
print(resp)
print(resp.url)
for key, value in req_session.cookies.items():
if key == 'peppa_sso_token':
token = value
token_header = {"accesstoken": token}
req_session.headers.update(token_header)
print(token_header)
print(value)
break
op_time = obj_tools.get_format_date(r_type=4,add_minutes=10)
print(op_time)
create_classroom_json = {"courseId":1898,"unionFlag":0,"lessonId":49264,"planStudentCount":4,"timezoneName":"Asia/Shanghai","openTime":op_time,"overseasTag":0,"secondOpenTime":op_time,"teacherId":36573,"type":100}
api_url_created_classroom = "https://teach-api.huohua.cn/peppa-teach-api/classroom"
create_classroom_resp = req_session.post(
url=api_url_created_classroom,
json=create_classroom_json)
# print(req_session.headers)
# print(req_session.cookies)
# print(resp.content)
# print(resp.url)
print(create_classroom_resp.json())
classroom_id = create_classroom_resp.json()['data']["classroomId"]
print(create_classroom_resp.json())
#
# return req_session
add_student_json = {"classroomId":classroom_id,"studentId":274886,"userId":275774,"joinType":0,"ignoreClassHour":1}
api_url_add_student = "https://teach-api.huohua.cn/peppa-teach-api/classroom_student/add"
add_student_resp = req_session.post(
url=api_url_add_student,
json=add_student_json)
print(add_student_resp.json())
# return req_session
add_student_json1 = {"classroomId":classroom_id,"studentId":5635578,"userId":5646962,"joinType":0,"ignoreClassHour":1}
add_student_resp1 = req_session.post(
url=api_url_add_student,
json=add_student_json1)
print(add_student_resp1.json())
if __name__ == '__main__':
host_list = [{"ip": "127.0.0.1", "host_name": "ts.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "its.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "student-api.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "sentry.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "gray.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "classroom-api.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "logserver.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "zipkin.sim.huohua.cn"},
{"ip": "127.0.0.1", "host_name": "gs.sim.huohua.cn"}]
A = EduClassroom()
A.kw_ubrd_get_online_test_classroom()

View File

@@ -0,0 +1,142 @@
import os
import re
import threading
class StatisticalFunction:
def __init__(self):
self.java_dir =[]
self.zh_file = []
self.python_dir = []
self.robot_dir = []
def check_lang_every_word(self,file_path):
""" 获取文件中注释外含中文的文档 """
# file_path ='C:\\Users\\HuoH # a=time.time()ua\\Downloads\\peppa-parent-api\\src\\main\\java\\com\\peppa\\parent\\api\\common\\ApiErrorEnum.java'
with open(file_path,'r',encoding='utf-8') as text:
all_content = text.read()
all_content = all_content.encode('utf-8')
all_content = all_content.decode('utf-8','ignore')
yy= re.sub("\/\*\*.*?\*\*\/", "",all_content) # 去除多行注释
yy = re.sub("\/\*[\w\W]*?\*\/|\/\/.*", "", yy) # 去除文本注释
yy = re.sub("(?<!:)\/\/.*", "", yy) # 去除行注释
yy=yy.replace(" ","")
yy=yy.replace('\n','')
# for eachline in text.read():
# line = eachline.strip()
# l2 =line.encode('utf-8')
# l1=l2.decode('utf-8','ignore')
# lineTuple = langid.classify(l1)
# for word in yy:
# lineTuple = langid.classify(word)
# if lineTuple[0] == "zh":
# if file_path not in zh_file:
# zh_file.append(file_path)
zhPattern = re.compile(u'[\u4e00-\u9fa5]+')
match = zhPattern.search(yy)
if match:
print(match,'\n',file_path)
self.zh_file.append(file_path)
# b =time.time()
# print(b-a)
def get_java_file(self,path):
"""获取所有java文件"""
for root, dirs, files in os.walk(path):
for file in files :
if file.endswith('.java'):
# print(os.path.join(root, file))
self.java_dir.append(os.path.join(root, file))
if dirs:
for dir_single in dirs:
if re.match('__',dir_single) :
print(dir_single)
# print(os.path.join(root, dirs[0]))
self.get_java_file(os.path.join(root,dir_single))
return self.java_dir
def muti_threading(self):
# 多线程调用
threads =[]
for file_zh in self.java_dir:
threads.append(
threading.Thread(target=self.check_lang_every_word,args=(file_zh,))
)
for thread in threads:
thread.start()
# print(thread.name)
for thread in threads:
thread.join()
# print(thread.name,"结束")
print("end")
def get_python_file(self,path):
"""获取所有python文件"""
for root, dirs, files in os.walk(path):
for file in files :
if file.endswith('.py'):
# print(os.path.join(root, file))
self.python_dir.append(os.path.join(root, file))
if dirs:
for dir_single in dirs:
if re.match('__',dir_single) :
print(dir_single)
# print(os.path.join(root, dirs[0]))
self.get_python_file(os.path.join(root,dir_single))
return self.python_dir
def get_robot_file(self,path):
"""获取所有robot文件"""
for root, dirs, files in os.walk(path):
for file in files :
if file.endswith('.robot'):
# print(os.path.join(root, file))
self.robot_dir.append(os.path.join(root, file))
if dirs:
for dir_single in dirs:
if re.match('__',dir_single) :
print(dir_single)
# print(os.path.join(root, dirs[0]))
self.get_robot_file(os.path.join(root,dir_single))
return self.robot_dir
@staticmethod
def get_class_function(class_ubrd):
ubrd_function = []
all_function = dir(class_ubrd)
for function in all_function:
if 'kw_in_ubrd' in function :
ubrd_function.append(function)
return ubrd_function
@staticmethod
def statistical(ubrd_function,dir_robot_python):
dict_function = {}
for function in ubrd_function:
count_num_all = 0
for dir_a in dir_robot_python:
with open(dir_a,'r',encoding='utf-8') as text:
all_content = text.read()
count_num_file = all_content.count(function)
count_num_all = count_num_all +count_num_file
count_num_all = count_num_all-1
if count_num_all in dict_function:
dict_function[count_num_all] += 1
else:
dict_function[count_num_all] = 1
return dict_function
if __name__ == '__main__':
pass

View File

@@ -0,0 +1,64 @@
import datetime, time
import random
class UbrdNowTime:
@staticmethod
def kw_ubrd_get_now_time():
now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
return now_time
def get_few_days_before_or_after_current_time(self, n=0):
"""
| 功能说明: | 获取当前时间的前几天或后几天的日期 |
| 输入参数: | n | 前n天或后n天,通过正负数来区分 |
| 输入参数: | hms | 1表示返回时分秒为当前时间0表示00:00:00 |
| 返回参数: | newtime_str | 当前时间的前几天或后几天的具体日期|
| 作者信息: | 刘睿权 | 修改时间 20211025|
举例说明:
| get_few_days_before_or_after_current_time | -7 |表示当前时间往后推7天的日期|
"""
nowtime = datetime.datetime.now()
Newnowtime = nowtime - datetime.timedelta(days=n)
return datetime.datetime.strftime(Newnowtime, '%Y-%m-%d %H:%M:%S')
@staticmethod
def kw_change_format_time(r_date):
get_time = r_date / 1000
time_array = time.localtime(get_time)
other_style_time = time.strftime("%Y-%m-%d %H:%M:%S", time_array)
return other_style_time
@staticmethod
def kw_ubrd_get_random_time():
'''
获取一个随机的时间
:param r_date:
:return:
'''
get_random_week = random.randint(0, 11)
get_minite_time = get_random_week * 5
if get_minite_time == 0:
get_time = "00"
elif get_minite_time == 5:
get_time = "05"
else:
get_time = str(get_minite_time)
return get_time
@staticmethod
def kw_ubrd_get_week_day(type):
now = datetime.datetime.now()
# 计算当前周的周一和下周一的日期
current_weekday = now.weekday() # 获取当前日期的星期几星期一为0星期日为6
current_monday = now - datetime.timedelta(days=current_weekday) # 当前周的周一
next_monday = current_monday + datetime.timedelta(days=7) # 下周一
# 设置时间为0点
if type == "1":
current_day = current_monday.replace(hour=0, minute=0, second=0, microsecond=0)
else:
current_day = next_monday.replace(hour=0, minute=0, second=0, microsecond=0)
return current_day
if __name__ == '__main__':
print(UbrdNowTime.kw_ubrd_get_week_day(type=2))

View File

@@ -0,0 +1,272 @@
# -*- coding:utf-8 -*-
"""
Author: 罗志鹏
Email: luozhipeng@huohua.cn
Create Date: 2022/03/03 11:25 下午
"""
from base_framework.public_tools import log
from base_framework.public_tools.sqlhelper import MySqLHelper
from library.UBRD_interface import UBRDInterface
from base_framework.public_tools.edu_user_helper import EDUUserHelper
from base_framework.public_tools.redis_api import RedisApi
from base_framework.public_tools.read_config import ReadConfig
from base_framework.base_config.current_pth import env_choose_path
from redis import Redis
from base_framework.public_tools.runner import Runner
from base_framework.public_tools.utils import Tools
from base_framework.public_business.common.UBRD.UBRD_public_business import BaseLogic
from base_framework.public_business.common.UBRD.kw.user_keyword import UserKW
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
obj_runner = Runner()
obj_log = log.get_logger()
obj_my_sql_helper = MySqLHelper()
obj_edu_user_helper = EDUUserHelper()
obj_redis_api = RedisApi()
obj_tools = Tools()
obj_base_logic = BaseLogic()
user_kw_obj = UserKW()
class UserCommon(UBRDInterface):
def __init__(self):
super().__init__()
self.evn_cfg = ReadConfig(env_choose_path)
self.current_business = self.evn_cfg.get_value(sections="run_evn_name", options="current_business")
@staticmethod
def update_user_pwd_by_phone(phone):
"""
功能初始化用户密码为A123456
| 输入参数: | phone string | 手机号 |
| 作者: | lzp | 2022.03.07 |
"""
sql_user_by_phone = "SELECT x.id FROM ucenter.user_profile x WHERE x.phone IN ('{0}')".format(phone)
user_by_phone = obj_my_sql_helper.select_all(sql_user_by_phone)
if isinstance(user_by_phone, tuple):
raise RuntimeError("未找到手机号为{0}的用户".format(phone))
sql_update_pwd = "update ucenter.user_profile set auth_hash = '2ad5381b6a2952287a95b9accb0bb51c'," \
"auth_salt='fFRzeLZGR5' WHERE phone IN ('{0}')".format(phone)
obj_my_sql_helper.update(sql_update_pwd)
obj_log.info('成功更新{0}用户密码为A123456'.format(phone))
def update_teacher_pwd_by_classroom(self, classroom_Code):
"""
功能初始化教师账号密码为Huohua123456
| 输入参数: | classroom_Code string | 课堂code |
| 作者: | lzp | 2022.03.07 |
"""
teacher_info = self.get_teacher_info_by_classroom(classroom_Code)
sql_update_pwd = "update account.account set pwd = 'e1NTSEF9dzE4ZlFhRytVNzZWeFVKMFFIV2VUNy83U2hxOE5oNUhMT0doTnc9PQ==' WHERE id ={0}".format(
teacher_info["account_id"])
obj_my_sql_helper.update(sql_update_pwd)
obj_log.info('成功更新{0}课堂教师{1}密码为Mima@123'.format(classroom_Code, teacher_info["phone"]))
def update_teacher_pwd_by_classroom_2(self,classroom_Code):
"""
功能初始化教师账号密码为MIma@123456
| 输入参数: | classroom_Code string | 课堂code |
| 作者: | lrq | 2024.06.12 |
"""
teacher_info = self.get_teacher_info_by_classroom(classroom_Code)
sql_update_pwd = "update account.account set pwd = 'e1NTSEF9dzE4ZlFhRytVNzZWeFVKMFFIV2VUNy83U2hxOE5oNUhMT0doTnc9PQ==' WHERE id ={0}".format(teacher_info["account_id"])
obj_my_sql_helper.update(sql_update_pwd)
obj_log.info('成功更新{0}课堂教师{1}密码为MIma@123456'.format(classroom_Code,teacher_info["phone"]))
def update_teacher_pwd_by_teacher_id(self, teacher_id):
"""
功能初始化教师账号密码为Huohua123456
| 输入参数: | classroom_Code string | 课堂code |
| 作者: | lzp | 2022.03.07 |
"""
teacher_info = self.get_teacher_info_by_teacher_id(teacher_id)
sql_update_pwd = "update account.account set pwd = 'e1NTSEF9dzE4ZlFhRytVNzZWeFVKMFFIV2VUNy83U2hxOE5oNUhMT0doTnc9PQ==' WHERE id ={0}".format(
teacher_info["account_id"])
obj_my_sql_helper.update(sql_update_pwd)
obj_log.info('成功更新{0}教师{1}密码为Mima@123'.format(teacher_id, teacher_info["phone"]))
def get_chess_classroom_by_mcr_code(self, mcr_code):
"""
功能:获取课堂教师信息 仅支持emp教师
| 输入参数: | teacher_id int | 老师id |
| 作者: | lzp | 2022.03.07 |
"""
sql_chess_classroom = "SELECT x.relation_classroom_code FROM learning_plan.classroom_relation x WHERE x.classroom_code IN ('{0}') and status =1 and relation_type = 1".format(
mcr_code)
chess_classroom = obj_my_sql_helper.select_all(sql_chess_classroom)
return chess_classroom
def get_teacher_info_by_teacher_id(self, teacher_id):
"""
功能:获取课堂教师信息 仅支持emp教师
| 输入参数: | teacher_id int | 老师id |
| 作者: | lzp | 2022.03.07 |
"""
sql_phone_by_classroom_code = "select tp.id,e.phone,tp.account_id from emp.employee e inner join teach_teacher.teacher_profile tp on tp.employee_id = e.id inner join account.account a on a.id= tp.account_id where tp.id = {0}".format(
teacher_id)
teacher_info = obj_my_sql_helper.select_all(sql_phone_by_classroom_code)
return teacher_info[0]
def get_teacher_info_by_classroom(self, classroom_Code):
"""
功能:获取课堂教师信息 仅支持emp教师
| 输入参数: | classroom_Code string | 课堂code |
| 作者: | lzp | 2022.03.07 |
"""
sql_phone_by_classroom_code = "select c.teacher_id,e.phone,tp.account_id from emp.employee e inner join teach_teacher.teacher_profile tp on tp.employee_id = e.id inner join teach_classes.classroom c on c.teacher_id = tp.id inner join account.account a on a.id= tp.account_id where c.code = '{0}'".format(
classroom_Code)
teacher_info = obj_my_sql_helper.select_all(sql_phone_by_classroom_code)
return teacher_info[0]
def get_student_info_by_phone(self, phone):
"""
功能:根据手机号码获取学生基本信息
| 输入参数: | phone string | 手机号 |
"""
user_info = user_kw_obj.kw_ubrd_public_get_user_info_by_phone(phone)
sql = "SELECT id studentId FROM ucenter.student_profile where user_id ='{}'".format(user_info["user_id"])
return obj_my_sql_helper.select_one(sql)
def get_classroom_info_by_code(self, code):
"""
功能:根据课堂号获取课堂信息
| 输入参数: | phone string | 手机号 |
"""
sql = "SELECT id,code,classes_id,classes_code,course_id,course_name,lesson_id,lesson_name,teacher_id,open_time,close_time,is_closed,status FROM teach_classes.classroom where code = '{0}'".format(
code)
return obj_my_sql_helper.select_one(sql)
def register_by_code_phone(self, phone, countryCode=86):
auth_code_send_result = obj_base_logic.logic_public_send_auth_code(
{'h': {'accept-language': 'en'}, 'phone': phone, 'countryCode': '{}'.format(countryCode), 'authType': 2,
'verifyAppId': 2})
obj_log.info(auth_code_send_result)
sms_code = obj_edu_user_helper.get_sms_code_by_phone(phone)
obj_log.info(sms_code)
login_post_result = self.kw_in_ubrd_login_post(
**{'phone': phone, 'countryCode': '86', 'password': 'A123456', 'authCode': sms_code})
obj_log.info(login_post_result)
# 更新密码
obj_my_sql_helper.update(
"update ucenter.user_profile set auth_hash = 'e2a0c8ec7503d1bfea587d5ffa0efc2f',auth_salt='fTvsqofig7' WHERE phone='{}'".format(
phone))
def get_change_pwd_vcode_by_sms_code(self, phone):
""" 获取学生端修改密码验证码 """
sms_code = obj_edu_user_helper.get_sms_code_by_phone(phone)
return sms_code
def get_register_vccode_by_redis(self, phone):
"""
获取学生端注册验证码
"""
key = "api:AUTH_CODE:{0}_SIGN_IN".format(phone)
obj_log.info(key)
return self.get_student_key_value_by_redis(key, 9)
def delete_change_student_pwd_limit_redis(self, phone):
"""
功能:删除学生端修改密码次数限制缓存
| 作者: | lzp | 2021.08. 15 |
"""
key_1 = "GRANULARITY:PHONE_AUTH_RECEIVE_COUNT_CHANNEL_MOBILE_API{0}".format(phone)
key_2 = "GRANULARITY:PHONE_AUTH_RECEIVE_COUNT_CHANNEL_MOBILE_API{0}_1".format(phone)
self.delete_student_key_redis(key_1, 9)
self.delete_student_key_redis(key_2, 9)
def delete_student_key_redis(self, key: object, db: object):
"""
删除指定key
"""
if self.current_business == "hh":
host = 'redis.qa.huohua.cn'
password = 'AcUVeRb8lN'
port = 6379
elif self.current_business == "hhi":
host = 'redis.qa.visparklearning.com'
password = 'hxTjlWBYdK6UpAGF'
port = 6379
else:
raise RuntimeError("读取本地配置环境失败未能正常连接redis")
pool = Redis(host=host, port=port, password=password, db=db)
pool.delete(key)
def get_student_key_value_by_redis(self, key, db):
"""
获取指定key的value
"""
if self.current_business == "hh":
host = 'redis.qa.huohua.cn'
password = 'AcUVeRb8lN'
port = 6379
elif self.current_business == "hhi":
host = 'redis.qa.visparklearning.com'
password = 'hxTjlWBYdK6UpAGF'
port = 6379
else:
raise RuntimeError("读取本地配置环境失败未能正常连接redis")
pool = Redis(host=host, port=port, password=password, db=db, decode_responses=True)
value = pool.get(key)
return value
def check_data_in_list(self, array: list, item):
"""
判断某个数据是否在数组中
"""
if item in array:
return True
else:
return False
def update_classroom_data_to_join(self, classroom_id):
"""
更新学习服务课堂数据
"""
open_time_timestamp = obj_tools.get_format_date(r_type=12)
close_time_timestamp = obj_tools.get_format_date(r_type=12, add_hours=1)
open_time_standard_time = obj_tools.get_format_date(r_type=4)
close_time_standard_time = obj_tools.get_format_date(r_type=4, add_hours=1)
# 更新学员课表数据
sql_learning_schedule = "update learning_plan.learning_schedule set open_time ='{0}',close_time = '{1}' " \
"where classroom_id = {2}".format(open_time_standard_time, close_time_standard_time,
classroom_id)
obj_my_sql_helper.update(sql_learning_schedule)
# 更新教师课表数据
sql_teaching_schedule = "update learning_plan.teaching_schedule set open_time ='{0}',close_time = '{1}', class_status =0 " \
"where classroom_id = {2}".format(open_time_timestamp, close_time_timestamp,
classroom_id)
obj_my_sql_helper.update(sql_teaching_schedule)
def check_data_in_db(self, sql, retry_count):
"""
判断某个数据是否在数据库中
"""
obj_my_sql_helper.check_result_exist(sql, retry_count=retry_count)
def encryption_aes(self,data,key=None):
if not key:
key = b"y3wa93twda35eqer"
cipher = AES.new(key, AES.MODE_ECB)
padded_data = pad(data.encode(), AES.block_size) # PKCS5Padding
encrypted_data = cipher.encrypt(padded_data)
return base64.b64encode(encrypted_data).decode()
if __name__ == '__main__':
user_common_obj = UserCommon()
a = 138475
s=user_common_obj.update_teacher_pwd_by_teacher_id(teacher_id=183152 )
print(s)
# print(user_common_obj.get_user_info_by_phone('13458500234'))
# phone_dict ={'phone': '65-98760021'}
# user_common_obj.get_register_vccode_by_redis('65-98760021')
# user_common_obj.update_classroom_data_to_join(classroom_id=500852944)

View File

@@ -0,0 +1,20 @@
# -*- coding:utf-8 -*-
# @Time : 2022/11/22 18:48
# @Author: luozhipeng
# @File : user_message.py
class ClassesReminder():
def __init__(self):
pass
def before_24h_reminder(self):
pass
def absence_classes_reminder(self):
pass
def before_1h_reminder(self):
pass
def before_2min_reminder(self):
pass

View File

@@ -0,0 +1,9 @@
# 存放小组内的配置信息
[m-userinfo]
login_sso_info = {"user":"liuruiquan","password":"lrq5823LRQ"}
login_parent_info ={"phone":"15328118883","password":"a123456","loginType":2,"countryCode":"null","userType":1,"subjectType":0}
login_student_info ={"phone":"18202810506","countryCode":86,"password":"A123456","authCodeType":2,"loginType":2}
realm_name = {"parent_api":"https://parent-api.huohua.cn","student_api":"https://student-api.huohua.cn","parent_vispark_api":"https://pst-gw.huohua.cn"}
parent_url = {"login_url":"https://m.huohua.cn/passport/login","parentPayEditionPage_url":"/parentPayEditionPage/user_info","recommendedCourse_url":"/personal_center/recommendedCourse"}
student_url = {"login_url":"https://core-api.huohua.cn/token","scheduleCount_url":"/learning/schedule/count/4"}
parent_course_url = {"get_trial_url":"/parent/audition/classes/overseas/course"}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

View File

@@ -0,0 +1,37 @@
# -*- coding:utf-8 -*-
"""
Author: qiaoxinjiu
Email: qiaoxinjiu@qq.com
Create Date: 2026/01/17 5:58 下午
"""
from base_framework.public_tools.mg_keyword import ManageKeyWord
from base_framework.public_tools import utils
from zhyy.library.BusinessKw.SZPurchase.index import PurchaseIndex
obj_get_way = utils.Tools()
obj_purchase_kw = PurchaseIndex()
obj_manage_kw = ManageKeyWord()
class PurchaseLogic():
def __init__(self):
pass
def logic_zhyy_sz_purchase_todo_task(self, post_data_input, phone=None):
"""
| 功能说明: | 深圳采购待办任务处理 |
| 请求参数名 | 说明 | 类型 | 条件 | 是否必填 | |
| userName | 登录名 | string |None | 0 |
作者信息: | 谯新久 | 2026/01/17 |
"""
try:
post_data_input = eval(post_data_input)
except:
post_data_input = post_data_input
return
if __name__ == '__main__':
pass

View File

@@ -0,0 +1,68 @@
# -*-coding:utf-8-*
import os
import sys
# 添加项目根目录到 Python 路径,以便导入 base_framework 模块
current_file_path = os.path.abspath(__file__)
project_root = os.path.abspath(os.path.join(os.path.dirname(current_file_path), '../../'))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from base_framework.public_tools import utils
from base_framework.public_tools.log import get_logger
from base_framework.public_tools.runner import Runner
from base_framework.public_tools.utils import Tools
from base_framework.public_tools import check_resp, convert_json, get_user, custom_check_resp
from base_framework.public_tools.eureka_api import EurekaAPI
import requests
obj_runner = Runner()
obj_log = get_logger()
tools = Tools()
obj_tool = utils.Tools()
s = requests.session()
eureka = EurekaAPI()
class ZhyyInterface:
def __init__(self):
self.domain_url = eureka.get_url_from_config()
def kw_in_zhyy_purchase_todo_get(self, is_check='', **kwargs):
"""
查询采购待办任务 + POST + interface id: 88383
url: http://peppa-personas-server.qa.huohua.cn/crowd_pack_query/list
| 请求参数名 | 说明 | 类型 | 条件 | 是否必填 |
| is_check | is_check默认空不校验返回有值就校验返回 | string | 业务case的时候需要传入值 | False |
"""
user, kwargs = get_user(kwargs)
kwargs = convert_json(kwargs)
url = "%s/erp/purchase-workbench/get-todo" % self.domain_url
obj_log.info("your input:{0}".format(kwargs))
resp = obj_runner.call_rest_api(API_URL=url, req_type="GET", user=user)
check_resp(is_check, resp)
return resp
def kw_in_zhyy_purchase_order_page_post(self, is_check='', **kwargs):
"""
查询采购单列表 + POST + interface id: 88383
url: http://peppa-personas-server.qa.huohua.cn/admin-api/erp/purchase-order/page
| 请求参数名 | 说明 | 类型 | 条件 | 是否必填 |
| is_check | is_check默认空不校验返回有值就校验返回 | string | 业务case的时候需要传入值 | False |
| pageNum | 页码 | integer | None | 0 |
| pageSize | 每页条数 | integer | None | 0 |
"""
user, kwargs = get_user(kwargs)
kwargs = convert_json(kwargs)
url = "%s/erp/purchase-order/page" % self.domain_url
obj_log.info("your input:{0}".format(kwargs))
resp = obj_runner.call_rest_api(API_URL=url, req_type="POST", json=kwargs, user=user)
check_resp(is_check, resp)
return resp
if __name__ == '__main__':
test = ZhyyInterface()
# print(test.domain_url)
a = test.kw_in_zhyy_purchase_todo_get(
user="purchase")
print(a)

134
zhyy/library/__init__.py Normal file
View File

@@ -0,0 +1,134 @@
# coding: utf-8
import importlib
import os
import re
import sys
import traceback
from base_framework.base_config.current_pth import env_choose_path
from base_framework.public_tools.read_config import ReadConfig
from base_framework.public_tools.log import get_logger
evn_cfg = ReadConfig(env_choose_path)
team = evn_cfg.get_value(sections="run_evn_name", options="current_team")
__all__ = ['KwLibrary']
cls_list_all = list()
cls_list_father = list()
cls_list_children = list()
t_c_list = list()
obj_log = get_logger()
def is_import(root):
black_list = [os.sep.join(['platform', 'tools']),'scene_server']
import_flag = True
for black_item in black_list:
if black_item in root:
# print(3, root)
import_flag = False
return import_flag
def class_import(path_list):
root_path = os.path.abspath(os.path.join(os.getcwd(), "../"))
module_path = root_path + os.sep + os.sep.join(path_list)
sys.path.append(module_path)
for root, dirs, files in os.walk(module_path):
# if is_import(root):
for file in files:
if os.path.splitext(file)[1] == '.py' and not file.startswith('__'):
with open(os.sep.join([root, file]), encoding="utf-8") as f:
for line in f.readlines():
cls_match = re.match(r"class\s(.*?)[\(:]", line)
if cls_match:
cls_name = cls_match.group(1)
try:
if cls_name not in ["Runner"]:
# module_list = root.split(os.sep)[len(os.getcwd().split(os.sep)) - 1:]
# module_list.append(os.path.splitext(file)[0])
# module = importlib.import_module('.'.join(module_list))
module_path_list = root.split(os.sep)
module_path_list.append(os.path.splitext(file)[0])
module_path = ''
for index in range(len(module_path_list)):
if module_path_list[index].lower() == 'base_framework' or module_path_list[index].lower() == 'library':
tmp_path = module_path_list[index:]
for path in tmp_path:
module_path = module_path + path + '.'
break
module_path = module_path[0:-1]
module = importlib.import_module(module_path)
class_attr = getattr(module, cls_name)
t_c_list.append(class_attr)
# if class_attr:
# if class_attr.__bases__[0] == object:
# cls_list_children.append(class_attr)
# else:
# cls_list_father.append(class_attr)
except:
traceback.print_exc()
print("ERROR import", file, cls_name)
def sort_class(class_list):
"""
功能将所有的class按继承关系排序子类在前父类在后用于startup启动加载
"""
while len(class_list) > 0:
# cls_list_len = len(cls_list_all)
tmp_class_list = []
del_list = []
for index in range(len(class_list)):
if not cls_list_all:
# 先找出所有的父类是object的基类
if class_list[index].__bases__[0] == object:
# while class_list[index].__bases__[0] == object:
tmp_class_list.append(class_list[index])
del_list.append(class_list[index])
else:
# 寻找前一步晒出基类的子类
if class_list[index].__bases__[0] in cls_list_all[len(cls_list_all) - 1]:
tmp_class_list.append(class_list[index])
del_list.append(class_list[index])
if len(tmp_class_list) > 0:
# 如果父类在已选出的类中,则保存该类
cls_list_all.append(tmp_class_list)
for item in del_list:
class_list.remove(item)
else:
# 如果父类都不在已选出的类中则全部按父类是object处理
cls_list_all.append(class_list)
class_list = []
class_import(["base_framework", "public_tools"])
class_import(["base_framework", "public_business"])
class_import([team, "library"])
# BaseLibrary = type('BaseLibrary', tuple(cls_list_father + cls_list_children), {})
sort_class(t_c_list)
c_len = len(cls_list_all)
obj_cls_tuple = ()
while c_len > 0:
obj_cls_tuple += tuple(cls_list_all[c_len - 1], )
c_len = c_len - 1
print(obj_cls_tuple)
BaseLibrary = type('BaseLibrary', obj_cls_tuple, {})
class KwLibrary(BaseLibrary):
def __init__(self):
class_len = 0
for base in BaseLibrary.__bases__:
try:
if hasattr(base, '__init__'):
if '__init__' in base.__dict__.keys():
if base.__bases__[0] != object or len(base.__init__.__code__.co_varnames) == 1:
base.__init__(self)
print(base)
# obj_log.info("init class:{} success...".format(base))
class_len += 1
except Exception as e:
if base.__bases__[0] == object:
print("INIT", e, base, base.__dict__)
# obj_log.info("import files num: {}".format(class_len))
print("import files num: {}".format(class_len))

Binary file not shown.

Binary file not shown.