Merge branch 'refs/heads/master' into dev

# Conflicts:
#	MangoServer/src/auto_test/auto_ui/views/ui_case.py
#	MangoServer/src/auto_test/auto_user/views/user.py
#	MangoServer/src/settings/master.py
#	MangoServer/src/settings/prod.py
#	MangoServer/src/settings/test.py
#	mango-console/.env.test
#	mango-console/src/views/config/test-files/index.vue
#	mango-console/src/views/uitest/page/elements/index.vue
This commit is contained in:
毛鹏
2025-03-01 20:36:51 +08:00
24 changed files with 187 additions and 226 deletions

View File

@@ -1,23 +1,18 @@
FROM python:3.10.16-slim AS builder
WORKDIR /app
RUN echo "deb http://mirrors.aliyun.com/debian bookworm main non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian bookworm-updates main non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian bookworm-backports main non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian-security bookworm-security main non-free non-free-firmware" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
COPY . .
FROM python:3.10.16-slim
WORKDIR /app
RUN echo "deb http://mirrors.aliyun.com/debian bookworm main non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian bookworm-updates main non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian bookworm-backports main non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian-security bookworm-security main non-free non-free-firmware" >> /etc/apt/sources.list
RUN echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
echo "deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
echo "deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -4,7 +4,7 @@ import atexit
import time
from django.apps import AppConfig
from src.auto_test.auto_api.service.test_case.case_flow import CaseFlow
from src.auto_test.auto_api.service.test_case.case_flow import ApiCaseFlow
class AutoApiConfig(AppConfig):
@@ -21,7 +21,7 @@ class AutoApiConfig(AppConfig):
atexit.register(self.shutdown)
def test_case_consumption(self):
self.case_flow = CaseFlow()
self.case_flow = ApiCaseFlow()
self.api_task = Thread(target=self.case_flow.process_tasks)
self.api_task.daemon = True
self.api_task.start()

View File

@@ -10,37 +10,36 @@ from queue import Queue
import time
from mangokit import Mango
from mangokit import singleton
from src.models.system_model import ConsumerCaseModel
from src.settings import IS_SEND_MAIL
from src.tools.log_collector import log
@singleton
class CaseFlow:
class ApiCaseFlow:
queue = Queue()
max_tasks = 2
def __init__(self):
self.executor = ThreadPoolExecutor(max_workers=self.max_tasks)
self.running = True
executor = ThreadPoolExecutor(max_workers=max_tasks)
running = True
def stop(self):
self.running = False
@classmethod
def stop(cls):
cls.running = False
def process_tasks(self):
@classmethod
def process_tasks(cls):
case_model = None
while self.running:
while cls.running:
try:
if not self.queue.empty():
case_model = self.queue.get()
self.executor.submit(self.execute_task, case_model)
if not cls.queue.empty():
case_model = cls.queue.get()
cls.executor.submit(cls.execute_task, case_model)
time.sleep(0.1)
except Exception as error:
trace = traceback.format_exc()
log.system.error(f'API线程池发生异常{error},报错:{trace}')
if IS_SEND_MAIL:
Mango.s(self.process_tasks, error, trace, case_model=case_model)
Mango.s(cls.process_tasks, error, trace, case_model=case_model)
@classmethod
def execute_task(cls, case_model: ConsumerCaseModel):

View File

@@ -17,7 +17,7 @@ from src.auto_test.auto_system.service.tasks.add_tasks import AddTasks
from src.auto_test.auto_system.views.product_module import ProductModuleSerializers
from src.auto_test.auto_system.views.project_product import ProjectProductSerializersC
from src.auto_test.auto_user.views.user import UserSerializers
from src.enums.tools_enum import StatusEnum, AutoTestTypeEnum
from src.enums.tools_enum import StatusEnum, TestCaseTypeEnum
from src.models.api_model import ApiCaseResultModel
from src.tools.decorator.error_response import error_response
from src.tools.log_collector import log
@@ -100,9 +100,9 @@ class ApiCaseViews(ViewSet):
test_env=request.data.get('test_env'),
is_notice=StatusEnum.FAIL.value,
user_id=request.user['id'],
_type=AutoTestTypeEnum.API.value,
)
add_tasks.add_test_suite_details(case_id_list)
for case_id in case_id_list:
add_tasks.add_test_suite_details(case_id, TestCaseTypeEnum.API)
return ResponseData.success(RESPONSE_MSG_0111)
@action(methods=['get'], detail=False)

View File

@@ -10,36 +10,34 @@ from queue import Queue
import time
from mangokit import Mango
from mangokit import singleton
from src.models.system_model import ConsumerCaseModel
from src.settings import IS_SEND_MAIL
from src.tools.log_collector import log
@singleton
class CaseFlow:
class PytestCaseFlow:
queue = Queue()
max_tasks = 2
executor = ThreadPoolExecutor(max_workers=max_tasks)
running = True
def __init__(self):
self.executor = ThreadPoolExecutor(max_workers=self.max_tasks)
self.running = True
@classmethod
def stop(cls):
cls.running = False
def stop(self):
self.running = False
def process_tasks(self):
while self.running:
@classmethod
def process_tasks(cls):
while cls.running:
try:
if not self.queue.empty():
case_model = self.queue.get()
self.executor.submit(self.execute_task, case_model)
if not cls.queue.empty():
case_model = cls.queue.get()
cls.executor.submit(cls.execute_task, case_model)
time.sleep(0.1)
except Exception as error:
trace = traceback.format_exc()
log.system.error(f'Pytest线程池发生异常{error},报错:{trace}')
if IS_SEND_MAIL:
Mango.s(self.process_tasks, error, trace)
Mango.s(cls.process_tasks, error, trace)
@classmethod
def execute_task(cls, case_model: ConsumerCaseModel):

View File

@@ -111,21 +111,19 @@ class ChatConsumer(WebsocketConsumer):
pass
else:
obj.send(send_data.model_dump_json())
if DEBUG:
log.system.info(
f'发送的用户{send_data.user}\n'
f'发送的客户端类型{ClientTypeEnum.get_value(1)}\n'
f'发送的数据:{send_data.model_dump_json() if send_data.data else None}'
)
log.system.warning(
f'发送的用户:{send_data.user}'
f'发送的客户端类型{ClientTypeEnum.get_value(1)}'
f'发送的数据{send_data.model_dump_json() if send_data.data else None}'
)
elif send_data.is_notice == ClientTypeEnum.ACTUATOR.value:
obj = SocketUser.get_user_client_obj(send_data.user)
obj.send(send_data.model_dump_json())
if DEBUG:
log.system.info(
f'发送的用户{send_data.user}\n'
f'发送的客户端类型{ClientTypeEnum.get_value(2)}\n'
f'发送的数据:{send_data.model_dump_json() if send_data.data else None}'
)
log.system.warning(
f'发送的用户:{send_data.user}'
f'发送的客户端类型{ClientTypeEnum.get_value(2)}'
f'发送的数据{send_data.model_dump_json() if send_data.data else None}'
)
def inside_send(self,
msg: str,

View File

@@ -0,0 +1,19 @@
# Generated by Django 4.1.5 on 2025-02-28 10:14
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auto_system', '0006_remove_projectproduct_auto_type'),
]
operations = [
migrations.AlterField(
model_name='testsuite',
name='tasks',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='auto_system.tasks'),
),
]

View File

@@ -253,7 +253,7 @@ class TestSuite(models.Model):
project_product = models.ForeignKey(to=ProjectProduct, to_field="id", on_delete=models.PROTECT)
test_env = models.SmallIntegerField(verbose_name="测试环境")
user = models.ForeignKey(to=User, to_field="id", verbose_name='用例执行人', on_delete=models.PROTECT)
tasks = models.ForeignKey(to=Tasks, to_field="id", on_delete=models.PROTECT)
tasks = models.ForeignKey(to=Tasks, to_field="id",on_delete=models.SET_NULL, null=True)
status = models.SmallIntegerField(verbose_name="测试结果")
is_notice = models.SmallIntegerField(verbose_name="是否发送通知")

View File

@@ -12,9 +12,11 @@ from django.db.utils import Error
from django.utils import timezone
from mangokit import Mango
from src.auto_test.auto_api.service.test_case.case_flow import CaseFlow
from src.auto_test.auto_api.service.test_case.case_flow import ApiCaseFlow
from src.auto_test.auto_pytest.service.test_case.case_flow import PytestCaseFlow
from src.auto_test.auto_system.models import TestSuiteDetails, TestSuite
from src.enums.tools_enum import TaskEnum, AutoTestTypeEnum
from src.auto_test.auto_ui.service.test_case.case_flow import UiCaseFlow
from src.enums.tools_enum import TaskEnum, TestCaseTypeEnum
from src.exceptions import MangoServerError
from src.models.system_model import ConsumerCaseModel
from src.settings import IS_SEND_MAIL
@@ -42,7 +44,7 @@ class ConsumerThread:
).first()
if test_suite_details:
test_suite = TestSuite.objects.get(id=test_suite_details.test_suite.id)
api_case_model = ConsumerCaseModel(
case_model = ConsumerCaseModel(
test_suite_details=test_suite_details.id,
test_suite=test_suite_details.test_suite.id,
case_id=test_suite_details.case_id,
@@ -50,15 +52,8 @@ class ConsumerThread:
user_id=test_suite.user.id,
tasks_id=test_suite.tasks.id if test_suite.tasks else None,
)
if test_suite_details.type == AutoTestTypeEnum.UI.value:
self.ui(0, test_suite, test_suite_details)
elif test_suite_details.type == AutoTestTypeEnum.API.value:
self.api(api_case_model)
else:
self.mango_pytest(test_suite, test_suite_details)
test_suite_details.retry += 1
test_suite_details.push_time = timezone.now()
test_suite_details.save()
self.send_case(test_suite, test_suite_details, case_model)
self.update_status_proceed(test_suite, test_suite_details)
if time.time() - reset_tims > self.clean_time * 60:
reset_tims = time.time()
@@ -74,48 +69,25 @@ class ConsumerThread:
if IS_SEND_MAIL:
Mango.s(self.consumer, error, trace, )
def ui(self, environment_error, test_suite, test_suite_details):
def send_case(self, test_suite, test_suite_details, case_model: ConsumerCaseModel, retry=0, max_retry=3):
retry += 1
try:
if test_suite_details.type == TestCaseTypeEnum.UI.value:
UiCaseFlow.add_task(case_model)
elif test_suite_details.type == TestCaseTypeEnum.API.value:
ApiCaseFlow.add_task(case_model)
else:
PytestCaseFlow.add_task(case_model)
log.system.info(
f'推送UI任务成功数据{{"case_id":{test_suite_details.case_id},"test_suite":{test_suite_details.test_suite.id},"test_suite_details":{test_suite_details.id}}}')
self.update_status_proceed(test_suite, test_suite_details)
f'推送{TestCaseTypeEnum.get_value(test_suite_details.type)}任务成功,test_suite_details":{test_suite_details.id}')
except MangoServerError as error:
log.system.warning(f'UI测试任务发生已知错误忽略错误等待重新开始{error.msg}')
except Exception as error:
self.consumer_error(test_suite, test_suite_details, error, traceback.format_exc())
def api(self, case_model: ConsumerCaseModel):
try:
CaseFlow().add_task(case_model)
log.system.info(
f'推送API任务成功数据{{"case_id":{test_suite_details.case_id},"test_suite":{test_suite_details.test_suite.id},"test_suite_details":{test_suite_details.id}}}')
self.update_status_proceed(test_suite, test_suite_details)
except MangoServerError as error:
log.system.warning(f'API测试任务发生已知错误忽略错误等待重新开始{error.msg}')
except Exception as error:
self.consumer_error(test_suite, test_suite_details, error, traceback.format_exc())
def mango_pytest(self, case_model: ConsumerCaseModel):
try:
send_case = CmdTest(
user_id=test_suite.user.id,
username=test_suite.user.username,
test_env=test_suite_details.test_env,
tasks_id=test_suite.tasks.id,
is_notice=test_suite.is_notice,
is_send=True
)
send_case.test_case(
test_suite=test_suite_details.test_suite.id,
test_suite_details=test_suite_details.id
)
log.system.info(
f'推送UI任务成功数据{{"case_id":{test_suite_details.case_id},"test_suite":{test_suite_details.test_suite.id},"test_suite_details":{test_suite_details.id}}}')
self.update_status_proceed(test_suite, test_suite_details)
except MangoServerError as error:
log.system.warning(f'UI测试任务发生已知错误忽略错误等待重新开始{error.msg}')
except Exception as error:
self.consumer_error(test_suite, test_suite_details, error, traceback.format_exc())
if retry > max_retry:
self.consumer_error(test_suite, test_suite_details, error, traceback.format_exc())
return
else:
self.send_case(test_suite, test_suite_details, case_model, retry, max_retry)
def clean_proceed(self):
"""
@@ -148,12 +120,17 @@ class ConsumerThread:
def update_status_proceed(self, test_suite, test_suite_details):
test_suite.status = TaskEnum.PROCEED.value
test_suite.save()
test_suite_details.status = TaskEnum.PROCEED.value
test_suite_details.retry += 1
test_suite_details.push_time = timezone.now()
test_suite_details.save()
def consumer_error(self, test_suite, test_suite_details, error, trace):
test_suite.status = TaskEnum.FAIL.value
test_suite.save()
test_suite_details.status = TaskEnum.FAIL.value
test_suite_details.error_message = f'发生未知异常,请联系管理员处理,类型:{AutoTestTypeEnum.get_value(test_suite.type)},异常内容{error}'
test_suite_details.error_message = f'测试{TestCaseTypeEnum.get_value(test_suite_details.type)}类型:,异常类型{error},报错内容:{trace}'
test_suite.save()
if IS_SEND_MAIL:
Mango.s(self.consumer_error, error, trace)

View File

@@ -3,51 +3,23 @@
# @Description:
# @Time : 2024-11-23 20:38
# @Author : 毛鹏
import traceback
from concurrent.futures import ThreadPoolExecutor
from queue import Queue
import time
from mangokit import Mango
from mangokit import singleton
from src.auto_test.auto_system.models import TestSuite, TestSuiteDetails
from src.auto_test.auto_system.service.socket_link.socket_user import SocketUser
from src.auto_test.auto_ui.service.test_case.test_case import TestCase
from src.enums.tools_enum import TaskEnum
from src.models.system_model import ConsumerCaseModel
from src.settings import IS_SEND_MAIL
from src.tools.log_collector import log
@singleton
class CaseFlow:
queue = Queue()
max_tasks = 2
class UiCaseFlow:
current_index = 0
def __init__(self):
self.executor = ThreadPoolExecutor(max_workers=self.max_tasks)
self.running = True
def stop(self):
self.running = False
def process_tasks(self):
while self.running:
try:
if not self.queue.empty():
case_model: ConsumerCaseModel = self.queue.get()
self.executor.submit(self.execute_task, case_model, 0, 3)
time.sleep(0.2)
except Exception as error:
trace = traceback.format_exc()
log.ui.error(f'UI线程池发生异常{error},报错:{trace}')
if IS_SEND_MAIL:
Mango.s(self.process_tasks, error, trace)
@classmethod
def execute_task(cls, case_model: ConsumerCaseModel, retry=0, max_retry=3):
retry += 1
user_list = [i for i in SocketUser.user if i.client_obj]
if not user_list:
log.system.warning('用户列表为空,无法发送任务,请先保持至少一个执行器是登录状态~')
@@ -57,6 +29,7 @@ class CaseFlow:
cls.current_index = (cls.current_index + 1) % len(user_list)
user = user_list[cls.current_index]
except IndexError:
time.sleep(3)
return cls.execute_task(case_model, retry, max_retry)
send_case = TestCase(
user_id=user.user_id,
@@ -87,4 +60,4 @@ class CaseFlow:
@classmethod
def add_task(cls, case_model: ConsumerCaseModel):
cls.queue.put(case_model)
cls.execute_task(case_model)

View File

@@ -16,7 +16,7 @@ from src.auto_test.auto_ui.models import UiCase
from src.auto_test.auto_ui.service.test_case.test_case import TestCase
from src.auto_test.auto_user.views.user import UserSerializers
from src.enums.system_enum import ClientNameEnum
from src.enums.tools_enum import StatusEnum, AutoTestTypeEnum
from src.enums.tools_enum import StatusEnum, TestCaseTypeEnum
from src.tools.decorator.error_response import error_response
from src.tools.view.model_crud import ModelCRUD
from src.tools.view.response_data import ResponseData
@@ -104,7 +104,8 @@ class UiCaseViews(ViewSet):
is_notice=StatusEnum.FAIL.value,
user_id=request.user['id'],
)
add_tasks.add_test_suite_details(case_id_list, AutoTestTypeEnum.UI.value)
for case_id in case_id_list:
add_tasks.add_test_suite_details(case_id, TestCaseTypeEnum.UI)
return ResponseData.success(RESPONSE_MSG_0074, value=(ClientNameEnum.DRIVER.value,))
@action(methods=['POST'], detail=False)

View File

@@ -5,6 +5,7 @@
# @Author : 毛鹏
import os
from datetime import datetime
from urllib.parse import unquote
import time
from django.forms import model_to_dict
@@ -14,8 +15,8 @@ from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.viewsets import ViewSet
from src import settings
from mangokit import EncryptionTool
from src import settings
from src.auto_test.auto_system.service.menu import ad_routes
from src.auto_test.auto_user.models import User
from src.auto_test.auto_user.views.role import RoleSerializers
@@ -218,9 +219,7 @@ class LoginViews(ViewSet):
@error_response('user')
@action(methods=['get'], detail=False)
def get_download(self, request: Request):
file_name = request.query_params.get('file_name')
file_name = unquote(request.query_params.get('file_name'))
file_path = os.path.join(settings.BASE_DIR, 'upload_template', file_name)
response = FileResponse(open(file_path, 'rb'))
response['Content-Disposition'] = f'attachment; filename="{file_name}"'
response = FileResponse(open(file_path, 'rb'), as_attachment=True, filename=file_name)
return response

View File

@@ -12,10 +12,10 @@ IS_SQLITE = False # 是否选用sqlite作为数据源默认使用mysql
# ************************ Mysql配置 ************************ #
MYSQL_PORT = 3306
MYSQL_DB_NAME = 'mango_server'
MYSQL_DB_NAME = 'dev_mango_server'
MYSQL_USER = 'root'
MYSQL_PASSWORD = 'mP123456&'
MYSQL_IP = '172.27.190.172'
MYSQL_IP = '172.25.239.230'
# ************************ DEBUG配置 ************************ #
# 这里也控制了是否使用minio

View File

@@ -28,13 +28,13 @@ IS_DEBUG_LOG = False
REDIS = False
# ************************ Minio配置 ************************ #
IS_MINIO = True
MINIO_STORAGE_ENDPOINT = 'minio:9000' # 访问IP+端口
MINIO_STORAGE_ACCESS_KEY = 'Qs6vh4jyQtakTPcjpGTD' # ACCESS_KEY
MINIO_STORAGE_SECRET_KEY = 'l9kmezbVChMieUtmCWg5MDIcRYetThnK0t8NkkTk' # SECRET_KEY
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
if IS_MINIO:
MINIO_STORAGE_ENDPOINT = 'minio:9000' # 访问IP+端口
MINIO_STORAGE_ACCESS_KEY = 'Qs6vh4jyQtakTPcjpGTD' # ACCESS_KEY
MINIO_STORAGE_SECRET_KEY = 'l9kmezbVChMieUtmCWg5MDIcRYetThnK0t8NkkTk' # SECRET_KEY
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
# ************************ 是否允许删除 ************************ #
IS_DELETE = True

View File

@@ -28,13 +28,13 @@ IS_DEBUG_LOG = False
REDIS = False
# ************************ Minio配置 ************************ #
IS_MINIO = True
MINIO_STORAGE_ENDPOINT = 'minio:9000'
MINIO_STORAGE_ACCESS_KEY = 'MCIK0dsiAFwgjthxlTdA'
MINIO_STORAGE_SECRET_KEY = '0rx2pFV3bc5q7q0hj7c66bRlcVhozKbv5E05Tqkx'
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
if IS_MINIO:
MINIO_STORAGE_ENDPOINT = 'minio:9000'
MINIO_STORAGE_ACCESS_KEY = 'MCIK0dsiAFwgjthxlTdA'
MINIO_STORAGE_SECRET_KEY = '0rx2pFV3bc5q7q0hj7c66bRlcVhozKbv5E05Tqkx'
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
# ************************ 是否允许删除 ************************ #
IS_DELETE = False

View File

@@ -29,13 +29,15 @@ REDIS = False
# ************************ Minio配置 ************************ #
IS_MINIO = True
MINIO_STORAGE_ENDPOINT = 'minio:9000' # 访问IP+端口
MINIO_STORAGE_ACCESS_KEY = 'Qs6vh4jyQtakTPcjpGTD' # ACCESS_KEY
MINIO_STORAGE_SECRET_KEY = 'l9kmezbVChMieUtmCWg5MDIcRYetThnK0t8NkkTk' # SECRET_KEY
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
if IS_MINIO:
MINIO_STORAGE_ENDPOINT = 'minio:9000' # 访问IP+端口
MINIO_STORAGE_USE_HTTPS = False # 如果使用 HTTPS设置为 True
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'mango-file' # 桶名称
MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True # 桶不存在时自动创建
# MINIO_STORAGE_ACCESS_KEY = 'jkPxfhklQqhUmDEpP0po' # ACCESS_KEY
# MINIO_STORAGE_SECRET_KEY = 'aQriZMcIH8rVXc5uNpondikDNOLdPbsba77dT6mF' # SECRET_KEY
MINIO_STORAGE_ACCESS_KEY = 'eQUpBpIGUgHc1f2nZbte' # 家里的
MINIO_STORAGE_SECRET_KEY = 'AqNnxHTrxVAZtPUgu6lLEArekqjHfMtku4tM1qgz' # 家里的
# ************************ 是否允许删除 ************************ #
IS_DELETE = True
# *************** 是否发送error日志协助芒果修复问题 *************** #

View File

@@ -1,6 +1,6 @@
BUILD_PATH=/
VITE_APP_ENV='test'
VITE_APP_BASE_URL = 'http://172.27.182.168:8000'
VITE_APP_SOCKET_URL = 'ws://172.27.182.168:8000/web/socket?'
VITE_APP_MINIO_URL = 'http://172.27.182.168:9000'
VITE_APP_BASE_URL = 'http://172.25.239.230:8000'
VITE_APP_SOCKET_URL = 'ws://172.25.239.230:8000/web/socket?'
VITE_APP_MINIO_URL = 'http://172.25.239.230:9000'
VITE_IS_INDEX_WINDOW = 'true'

View File

@@ -14,6 +14,9 @@ export function getUserFile(type = 0) {
export function postUserFile(data: object) {
return post({
url: '/system/file',
headers: {
'Content-Type': 'multipart/form-data',
},
data: () => {
return data
},

View File

@@ -5,7 +5,11 @@
<div class="container">
<span>测试文件</span>
</div>
<a-upload @before-upload="beforeUpload" :show-file-list="false" />
<a-upload
@before-upload="beforeUpload"
:show-file-list="false"
:before-upload="beforeUpload"
/>
</a-space>
<a-tabs />
@@ -28,14 +32,14 @@
:data-index="item.key"
:fixed="item.fixed"
>
<template v-if="item.key === 'index'" :class="record" #cell="{ record }">
<template v-if="item.key === 'index'" #cell="{ record }">
{{ record.id }}
</template>
<template v-else-if="item.key === 'actions'" #cell="{ record }">
<a-button type="text" size="mini" @click="onDownload(record)">下载 </a-button>
<a-button type="text" size="mini" @click="onDownload(record)">下载</a-button>
<a-button status="danger" type="text" size="mini" @click="onDelete(record)"
>删除</a-button
>
>删除
</a-button>
</template>
</a-table-column>
</template>
@@ -47,16 +51,15 @@
<script lang="ts" setup>
import { usePagination, useRowKey, useRowSelection, useTable } from '@/hooks/table'
import { Message, Modal } from '@arco-design/web-vue'
import { onMounted, nextTick } from 'vue'
import { nextTick, onMounted } from 'vue'
import { tableColumns } from './config'
import { deleteUserFile, getUserFile, postUserFile } from '@/api/system/file_data'
import { useProject } from '@/store/modules/get-project'
import { minioURL } from '@/api/axios.config'
const pagination = usePagination(doRefresh)
const { onSelectionChange } = useRowSelection()
const table = useTable()
const rowKey = useRowKey('id')
const projectInfo: any = useProject()
function doRefresh() {
getUserFile()
@@ -67,25 +70,6 @@
.catch(console.log)
}
function downFile() {
let aLink = document.createElement('a')
aLink.href = '文件地址'
}
// function onDownload(record: any) {
// get({
// url: userFilesDownload,
// data: () => {
// return {
// project_id: record.project_id,
// file_name: record.file_name,
// }
// },
// })
// .then((res) => {})
// .catch(console.log)
// }
function onDelete(record: any) {
Modal.confirm({
title: '提示',
@@ -141,6 +125,7 @@
document.body.removeChild(aLink)
}
}
onMounted(() => {
nextTick(async () => {
doRefresh()

View File

@@ -80,7 +80,7 @@
<p>元素下标{{ item.sub ? item.sub : '-' }}</p>
<div v-if="item.status === 0">
<a-image
:src="minioURL + '/failed_screenshot/' + item.picture_path"
:src="minioURL + '/mango-file/failed_screenshot/' + item.picture_path"
title="失败截图"
width="260"
style="margin-right: 67px; vertical-align: top"

View File

@@ -272,7 +272,7 @@
<p>元素下标:{{ item.sub ? item.sub : '-' }}</p>
<div v-if="item.status === 0">
<a-image
:src="minioURL + '/failed_screenshot/' + item.picture_path"
:src="minioURL + '/mango-file/failed_screenshot/' + item.picture_path"
title="失败截图"
width="260"
style="margin-right: 67px; vertical-align: top"

View File

@@ -72,9 +72,9 @@
</template>
<template v-else-if="item.dataIndex === 'type'" #cell="{ record }">
<a-tag :color="enumStore.colors[record.type]" size="small">{{
enumStore.element_ope[record.type].title
}}</a-tag>
<a-tag :color="enumStore.colors[record.type]" size="small"
>{{ enumStore.element_ope[record.type].title }}
</a-tag>
</template>
<template v-else-if="item.dataIndex === 'actions'" #cell="{ record }">
<a-button type="text" size="mini" @click="onTest(record)">调试</a-button>
@@ -92,7 +92,7 @@
<a-card title="最近一次步骤执行过程" style="overflow: hidden" :bordered="false">
<a-collapse
:default-active-key="data.eleResultKey"
v-for="item of pageData.record.result_data?.element_result_list"
v-for="item of data.result_data?.element_result_list"
:bordered="false"
:key="item.id"
destroy-on-hide
@@ -128,7 +128,7 @@
<p>元素下标{{ item.sub ? item.sub : '-' }}</p>
<div v-if="item.status === 0">
<a-image
:src="minioURL + '/failed_screenshot/' + item.picture_path"
:src="minioURL + '/mango-file/failed_screenshot/' + item.picture_path"
title="失败截图"
width="260"
style="margin-right: 67px; vertical-align: top"
@@ -285,12 +285,12 @@
getUiPageStepsDetailed,
getUiPageStepsDetailedAss,
getUiPageStepsDetailedOpe,
getUiPageStepsDetailedTest,
postUiPageStepsDetailed,
putUiPagePutStepSort,
putUiPageStepsDetailed,
getUiPageStepsDetailedTest,
} from '@/api/uitest/page-steps-detailed'
import { getUiStepsTest } from '@/api/uitest/page-steps'
import { getUiSteps, getUiStepsTest } from '@/api/uitest/page-steps'
import { getUiUiElementName } from '@/api/uitest/element'
import useUserStore from '@/store/modules/user'
import { useEnum } from '@/store/modules/get-enum'
@@ -314,6 +314,7 @@
uiPageName: [],
type: 0,
plainOptions: [],
result_data: {},
})
const visible1 = ref(false)
@@ -323,6 +324,7 @@
border: 'none',
overflow: 'hidden',
})
function changeStatus(event: number) {
data.type = event
for (let i = formItems.length - 1; i >= 0; i--) {
@@ -410,7 +412,7 @@
deleteUiPageStepsDetailed(record.id, record.page_step.id)
.then((res) => {
Message.success(res.msg)
getUiRunSort()
doRefresh()
})
.catch(console.log)
},
@@ -474,7 +476,7 @@
postUiPageStepsDetailed(value, route.query.id)
.then((res) => {
Message.success(res.msg)
getUiRunSort()
doRefresh()
})
.catch(console.log)
} else {
@@ -482,7 +484,7 @@
putUiPageStepsDetailed(value, route.query.id)
.then((res) => {
Message.success(res.msg)
getUiRunSort()
doRefresh()
})
.catch(console.log)
}
@@ -493,7 +495,7 @@
window.history.back()
}
function getUiRunSort() {
function doRefresh() {
getUiPageStepsDetailed(route.query.id)
.then((res) => {
data.dataList = res.data
@@ -637,13 +639,20 @@
.catch(console.log)
}
onMounted(() => {
nextTick(async () => {
await getUiRunSortAss()
await getUiRunSortOpe()
await getEleName()
getUiRunSort()
})
function doRefreshSteps(pageStepsId: any) {
getUiSteps({ id: pageStepsId })
.then((res) => {
data.result_data = res.data[0].result_data
})
.catch(console.log)
}
onMounted(async () => {
doRefresh()
doRefreshSteps(pageData.record.id)
getUiRunSortAss()
getUiRunSortOpe()
getEleName()
})
</script>
<style>

View File

@@ -1,7 +1,7 @@
import { FormItem } from '@/types/components'
import { reactive, ref } from 'vue'
import { Message } from '@arco-design/web-vue'
export const columns = reactive([
export const columns: any = reactive([
{
title: '元素名称',
dataIndex: 'name',

View File

@@ -4,8 +4,12 @@
<a-card title="页面元素详情" :bordered="false">
<template #extra>
<a-space>
<a-upload @before-upload="beforeUpload" :show-file-list="false" />
<a-button type="primary" size="small" @click="onDownload">下载模版</a-button>
<a-upload
type="primary"
size="small"
@before-upload="beforeUpload"
:show-file-list="false"
/>
<a-button type="primary" size="small" @click="doAppend">增加</a-button>
<a-button status="danger" size="small" @click="doResetSearch">返回</a-button>
</a-space>
@@ -182,8 +186,7 @@
import { assForm, eleForm } from '@/views/uitest/page/elements/config'
import useUserStore from '@/store/modules/user'
import { useEnum } from '@/store/modules/get-enum'
import { postUserFile } from '@/api/system/file_data'
import { minioURL } from '@/api/axios.config'
import { baseURL } from '@/api/axios.config'
const userStore = useUserStore()
const enumStore = useEnum()
@@ -500,7 +503,7 @@
}
function onDownload() {
const file_name = '元素批量上传模版.xlsx'
const file_path = `${minioURL}/download?file_name=${file_name}`
const file_path = `${baseURL}/download?file_name=${encodeURIComponent(file_name)}`
let aLink = document.createElement('a')
aLink.href = file_path
aLink.download = file_name