Files
dify-plus/api/controllers/console/app/ai_draw_extnd.py
T
npc0-hue 17832f2424 fix: Dify 1.8.1问题修复
本次提交整合了多个功能改进和问题修复:

主要功能:
- 批量工作流处理功能完善,支持 Excel 上传和进度跟踪
- 管理中心反向代理和转发配置优化
- 用户同步添加互斥锁,防止并发问题
- 计费系统和额度显示优化
- AI 绘图功能扩展

前端改进:
- 文本生成应用显示修复
- 批量任务进度展示优化
- 按钮样式和 CSS 优化,禁止换行
- 多语言支持完善(新增印尼语等)
- 构建镜像逻辑优化
- 批量处理进度管理器实现

后端改进:
- Docker Compose 配置升级
- 队列任务和 Worker Pool 优化
- Admin API 初始化和验证逻辑改进
- 数据库迁移和初始化完善
- 静态变量处理优化
- URL 签名助手实现
- Celery 扩展优化
- 代码和导入包问题修复(idea 自动调整代码位置)

技术改进:
- 兼容性修复 (flask-restx, jschardet)
- 钉钉 Web API 版本更新
- 代码格式化和导入包问题修复
- 日志处理优化
- 工作流循环管理优化

Docker 相关:
- Nginx 配置更新
- 容器启动脚本优化
- 镜像构建流程改进
- docker-compose.dify-plus.yaml 大幅更新

管理后台:
- 工作流批量处理 API 实现
- 工作池初始化
- 批量工作流服务实现
- 转发扩展配置
- 用户服务扩展
2025-10-17 23:04:25 +08:00

183 lines
6.8 KiB
Python

"""
转发相关接口
Created on 2024-03-21
"""
import concurrent.futures
import logging
from flask import Response, current_app, request
from flask_restful import Resource
from controllers.console import api
from libs.login_extend import repost_login_required
from services.ai_draw_extend import AiDrawForwarding
from services.billing_extend import AiDrawBilling
logging.basicConfig(level=logging.DEBUG)
# 创建一个线程池
executor = concurrent.futures.ThreadPoolExecutor()
class AiDrawTransit(Resource):
def __init__(self, *args, **kwargs):
# Destination address
self.target_url = current_app.config.get("HOSTED_FETCH_APP_TEMPLATES_MODE")
def get(self, path):
pass
def post(self, path):
pass
def put(self, path):
pass
def delete(self, path):
pass
def patch(self, path):
pass
def options(self, path):
pass
@repost_login_required
def dispatch_request(self, *args, **kwargs):
# Replace with the address of the target server
print('1111')
path = kwargs.get("path", "")
path_list = path.split("/")
auth_header = request.headers.get("Authorization")
if auth_header is None:
auth_header = "Bearer " + request.cookies.get("x-token")
if len(path_list) < 1:
return Response("router error", status=500)
# obtains forwarding domain name
logging.warning("obtains forwarding domain name: {}".format(path_list[0]))
forwarding = AiDrawForwarding.get_forwarding(path_list[0])
print(forwarding)
logging.warning("forwarding: {}".format(forwarding.id))
if forwarding is None:
return Response("router is none", status=500)
# 使用线程池来运行异步函数
return AiDrawBilling.billing_forward(forwarding, path_list, kwargs, auth_header, path)
# class YouDaoTranslationPictures(Resource):
# """有道翻译图片接口"""
#
# @setup_required
# @login_required
# def post(self):
# """
# 翻译图片接口
# ---
# 请求参数:
# - images: list[str] base64编码的图片列表
# - language: str 目标语言代码
# 返回:
# - code: int 状态码
# - message: str 提示信息
# - data: list[str] 翻译后的base64图片列表
# """
# parser = reqparse.RequestParser()
# parser.add_argument("language", type=str, required=True, location="json")
# parser.add_argument("image", type=str, required=True, location="json")
# parser.add_argument("from_code", type=str, required=True, location="json")
# args = parser.parse_args()
#
# if not args.image or not args.language:
# response_data = {"code": 400, "message": '参数错误:images和language不能为空', "data": None}
# response = make_response(response_data)
# self._add_cors_headers(response)
# return response
#
# # 翻译图片
# forwarding = AiDrawForwarding.get_forwarding("youdao_ocr_translate")
# if forwarding is not None:
# AiDrawBilling.calculate_user_billing_information(current_user.id, forwarding.id, "/translate", args)
# img_url, err = AiDrawBilling.ocr_translate(
# image_base64=args.image,
# from_code=args.from_code,
# to_lang_code=args.language,
# )
# if err != "":
# response_data = {"code": 500, "message": err, "data": None}
# response = make_response(response_data)
# self._add_cors_headers(response)
# return response
# else:
# # Extend start: 绘图 翻译图片有道的base64改储存到本地
# try:
# # 解码 base64 图片数据
# extension = 'png'
# mime_type = 'image/png'
#
# # 确保 base64 字符串格式正确
# base64_data = img_url
# # 如果 img_url 已经包含 data URL 前缀,提取纯 base64 部分
# if base64_data.startswith('data:image/'):
# base64_data = base64_data.split(',', 1)[1]
#
# # 添加必要的 padding
# missing_padding = len(base64_data) % 4
# if missing_padding:
# base64_data += '=' * (4 - missing_padding)
#
# # 解码 base64 数据
# image_content = base64.b64decode(base64_data)
#
# # 生成文件名
# filename = f"translated_image_{uuid.uuid4().hex[:8]}.{extension}"
#
# # 使用 FileService 保存文件
# upload_file = FileService.upload_file(
# filename=filename,
# content=image_content,
# mimetype=mime_type,
# user=current_user
# )
#
# # 生成可访问的 URL
# base_url = dify_config.FILES_URL
# image_preview_url = f"{base_url}/files/{upload_file.id}/image-preview"
# signed_url = UrlSigner.get_signed_url(
# url=image_preview_url,
# sign_key=upload_file.id,
# prefix="image-preview"
# )
#
# response_data = {
# 'code': 200,
# 'message': '翻译成功',
# 'data': {
# 'image_url': signed_url,
# 'file_id': upload_file.id
# }
# }
# response = make_response(response_data)
# self._add_cors_headers(response)
# return response
#
# except Exception as e:
# logging.error(f"保存翻译图片失败: {str(e)}")
# response_data = {"code": 500, "message": f'保存翻译图片失败: {str(e)}', "data": None}
# response = make_response(response_data)
# self._add_cors_headers(response)
# return response
# # Extend stop: 绘图 翻译图片有道的base64改储存到本地
#
def _add_cors_headers(self, response):
"""添加CORS头部"""
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS, DELETE"
response.headers["Access-Control-Max-Age"] = "3600"
response.headers["Access-Control-Allow-Headers"] = "x-requested-with,Authorization,token, content-type"
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["X-Accel-Redirect"] = ""
api.add_resource(AiDrawTransit, "/extend/<path:path>")
# api.add_resource(YouDaoTranslationPictures, "/youdao/translation/pictures")