Django 简易PACS读片系统

这篇具有很好参考价值的文章主要介绍了Django 简易PACS读片系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、Django中写一个后端接口,给HTML提供dicom文件接口的方式

1、首先创建django项目
1、下载安装跨域的包
pip3 install django-cors-headers
2、使用pycharm创建一个Django项目

Django 简易PACS读片系统,Django,django

3、点击创建在另一个窗口,这个都无所谓,怎么都行,就是打开这个项目
4、创建成功的项目就是下面这个样子

Django 简易PACS读片系统,Django,django

5、先修改几个选项,后面好操作

下面是我的settings设置,我把修改的地方标注出来

"""
Django settings for pacsdemo project.

Generated by 'django-admin startproject' using Django 3.2.18.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
# 添加这个import os
import os
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-uv!_mka##8#citwx_q$o71)@!8tfaa-6wyrb!h8&4fm+m-=-d='

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# 设置所有IP都可以访问,局域网
ALLOWED_HOSTS = ['*']

# Application definition

# 添加跨域设置
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pacs.apps.PacsConfig',
    'corsheaders'  # 跨域设置
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# 新添加的设置
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = False
CORS_ORIGIN_WHITELIST = [
    "http://192.168.0.30:8000",
    "http://localhost:63409",
]
CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW'
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)


ROOT_URLCONF = 'pacsdemo.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates']
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'pacsdemo.wsgi.application'

# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

# 连接本地的mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'pacsdemo',   #  你的数据库名称
        'USER': '******',  # 你的账户
        'PASSWORD': '******',  #你的密码
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

# 设置时间,上海的时间
LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

# 加载静态文件的设置
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

6、把表结构映射到数据库中

连接数据库的设置,没有这个设置,数据库会连接失败

import pymysql
pymysql.install_as_MySQLdb()

Django 简易PACS读片系统,Django,django

7、在终端运行两行命令
python manage.py makemigrations

Django 简易PACS读片系统,Django,django

8、运行第二行命令
python manage.py migrate

Django 简易PACS读片系统,Django,django

9、第一步完成,数据库连接成功,基础设置完成

2、写前端页面,并且和后端接口,传递单个dicom文件,并且显示出来

1、先添加一个路由
from django.conf.urls import include

Django 简易PACS读片系统,Django,django

2、然后在pacs中写urls.py里面的内容
from django.urls import path

from . import views

urlpatterns = [
    path("index/", views.index),  # 设置首页内容
    path("read/", views.read),  # 读dicom文件
    path("read1/", views.read1),  # 读dicom文件
]

Django 简易PACS读片系统,Django,django

3、写这个index的方法,在views.py中
from django.shortcuts import render
from django.http import HttpResponse, FileResponse


# Create your views here.
def index(request):
    return render(request, 'index.html')


def read(request):
    file = open('static/dicom/C9214289', 'rb')
    response = FileResponse(file)
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename="1.dcm"'
    return response


def read1(request):
    file = open('static/dicom/C9214530', 'rb')
    response = FileResponse(file)
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename="2.dcm"'
    return response


Django 简易PACS读片系统,Django,django

4、写index.html的内容

我写的这个html,直接放进去就可以看,其中的内容你可以通过cornerstone.js查看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>pacs</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>


    <script type="text/javascript">

        // 阻止右键点击事件的默认行为
        document.addEventListener('contextmenu', function (event) {
            event.preventDefault();
        });
    </script>
    <script>
        // 监听双击事件,并阻止默认的缩放行为
        document.addEventListener('dblclick', function (event) {
            event.preventDefault();
        });
        document.addEventListener('touchstart', function (event) {
            if (event.touches.length > 1) {
                event.preventDefault();
            }
        }, {passive: false});
    </script>
</head>
<body>
<div>
    <h2>全部都是鼠标左键的操作</h2>
    <button id="wwwc">切换窗宽窗位</button>
    <button id="length">切换测量长度</button>
    <button id="rotate">旋转</button>
    <button id="magnify">透视</button>
    <button id="pan">移动</button>
    <br/>
    <button id="scaleoverlay">尺度</button>
    <button id="zoom">放大</button>
    <button id="angle">测量角度</button>
    <button id="arrowannotate">添加备注</button>
    <button id="bidirectional">交叉线</button>
    <br/>
    <button id="cobbangle">心胸比</button>
    <button id="ellipticalroi">圆</button>
    <button id="freehandroi">随便画</button>
    <button id="probe">探针</button>
    <button id="rectangleroi">方形</button>
    <br/>
    <button id="circlescissors">画圆</button>
    <button id="rectanglescissors">画正方形</button>
</div>
<div id="dicomImage" style="width: 512px;height: 512px;position: absolute"></div>

</body>
<!-- 触控的方法 -->
<script src="https://unpkg.com/hammerjs@2.0.8/hammer.js"></script>
<!-- 基石包,核心包 -->
<script src="https://unpkg.com/cornerstone-core@2.6.1/dist/cornerstone.js"></script>
<!-- Math包,数学包 -->
<script src="https://unpkg.com/cornerstone-math@0.1.10/dist/cornerstoneMath.min.js"></script>
<!-- 图片解析包,解析dcm文件的 -->
<script src="https://unpkg.com/cornerstone-wado-image-loader@4.13.2/dist/cornerstoneWADOImageLoader.bundle.min.js"></script>
<!-- 解析普通图的方法 -->
<script src="https://unpkg.com/cornerstone-web-image-loader@2.1.1/dist/cornerstoneWebImageLoader.min.js"></script>
<!-- 写好方法的包 -->
<script src="https://unpkg.com/cornerstone-tools@6.0.10/dist/cornerstoneTools.js"></script>
<!-- 解析dicom的json信息 -->
<script src="https://unpkg.com/dicom-parser@1.8.21/dist/dicomParser.min.js"></script>

<script>
    cornerstoneTools.external.cornerstone = cornerstone;
    cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
    cornerstoneTools.external.Hammer = Hammer;
    cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
    cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
    // 'dicomweb' 网页上的一种解析的包, http开头的网址 ,获取dicom的文件,并且显示出来
    var imageId = "wadouri:http://127.0.0.1:8000/read";
    var imageIds = ["wadouri:http://127.0.0.1:8000/read", "wadouri:http://127.0.0.1:8000/read1"]

    // 定义stack滚动工具
    const StackScrollMouseWheelTool = cornerstoneTools.StackScrollMouseWheelTool
    // Add our tool, and set it's mode
    const StackScrollTool = cornerstoneTools.StackScrollTool
    //define the stack
    // 设置一个栈
    const stack = {
        currentImageIdIndex: 0,
        imageIds
    }

    // 默认初始化tools
    cornerstoneTools.init()
    // 获取页面显示的dicom id
    var element = document.getElementById('dicomImage');
    cornerstone.enable(element)

    // 测量长度
    const LengthTool = cornerstoneTools.LengthTool;
    cornerstoneTools.addTool(LengthTool)
    // cornerstoneTools.setToolActive('Length', {mouseButtonMask: 1})
    // wwwc
    const WwwcTool = cornerstoneTools.WwwcTool;
    cornerstoneTools.addTool(WwwcTool)
    // cornerstoneTools.setToolActive('Wwwc', {mouseButtonMask: 1})

    // 旋转
    const RotateTool = cornerstoneTools.RotateTool;
    cornerstoneTools.addTool(RotateTool)
    // 透视
    const MagnifyTool = cornerstoneTools.MagnifyTool;
    cornerstoneTools.addTool(MagnifyTool)
    // 移动
    const PanTool = cornerstoneTools.PanTool;
    cornerstoneTools.addTool(PanTool)
    // 尺度
    const ScaleOverlayTool = cornerstoneTools.ScaleOverlayTool;
    cornerstoneTools.addTool(ScaleOverlayTool)
    // 放大
    const ZoomTool = cornerstoneTools.ZoomTool;
    cornerstoneTools.addTool(cornerstoneTools.ZoomTool, {
        // Optional configuration
        configuration: {
            invert: false,
            preventZoomOutsideImage: false,
            minScale: .1,
            maxScale: 20.0,
        }
    });
    // 测量角度
    const AngleTool = cornerstoneTools.AngleTool;
    cornerstoneTools.addTool(AngleTool)

    // 添加备注
    const ArrowAnnotateTool = cornerstoneTools.ArrowAnnotateTool;
    cornerstoneTools.addTool(ArrowAnnotateTool)
    // 交叉线
    const BidirectionalTool = cornerstoneTools.BidirectionalTool;
    cornerstoneTools.addTool(BidirectionalTool)
    // 心胸比
    const CobbAngleTool = cornerstoneTools.CobbAngleTool;
    cornerstoneTools.addTool(CobbAngleTool)
    // 圆
    const EllipticalRoiTool = cornerstoneTools.EllipticalRoiTool;
    cornerstoneTools.addTool(EllipticalRoiTool)
    // 画笔
    const FreehandRoiTool = cornerstoneTools.FreehandRoiTool;
    cornerstoneTools.addTool(FreehandRoiTool)
    // 探针
    const ProbeTool = cornerstoneTools.ProbeTool;
    cornerstoneTools.addTool(ProbeTool)
    // 正方形长方形
    const RectangleRoiTool = cornerstoneTools.RectangleRoiTool;
    cornerstoneTools.addTool(RectangleRoiTool)
    // 直接画圆
    const CircleScissorsTool = cornerstoneTools.CircleScissorsTool;
    cornerstoneTools.addTool(CircleScissorsTool)
    // 通过正方形涂
    const RectangleScissorsTool = cornerstoneTools.RectangleScissorsTool;

    cornerstoneTools.addTool(RectangleScissorsTool)


    // 鼠标中键滚动
    cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
        cornerstone.displayImage(element, image)
        cornerstoneTools.addStackStateManager(element, ['stack'])
        cornerstoneTools.addToolState(element, 'stack', stack)
    })

    cornerstoneTools.addTool(StackScrollMouseWheelTool)
    cornerstoneTools.setToolActive('StackScrollMouseWheel', {})

    function disableAllTools() {
        // 取消左键的功能
        cornerstoneTools.setToolDisabled('Length')
        cornerstoneTools.setToolDisabled('Wwwc')
        cornerstoneTools.setToolDisabled('Rotate')
        cornerstoneTools.setToolDisabled('Magnify')
        cornerstoneTools.setToolDisabled('ScaleOverlay')
        cornerstoneTools.setToolDisabled('Zoom')
        cornerstoneTools.setToolDisabled('Angle')
        cornerstoneTools.setToolDisabled('ArrowAnnotate')
        cornerstoneTools.setToolDisabled('Pan')
        cornerstoneTools.setToolDisabled('Bidirectional')
        cornerstoneTools.setToolDisabled('CobbAngle')
        cornerstoneTools.setToolDisabled('EllipticalRoi')
        cornerstoneTools.setToolDisabled('FreehandRoi')
        cornerstoneTools.setToolDisabled('Probe')
        cornerstoneTools.setToolDisabled('RectangleRoi')
        cornerstoneTools.setToolDisabled('CircleScissors')
        cornerstoneTools.setToolDisabled('RectangleScissors')
    }

    document.getElementById("wwwc").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活窗宽窗位
        cornerstoneTools.setToolActive("Wwwc", {mouseButtonMask: 1})

    })
    document.getElementById("length").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活测量长度
        cornerstoneTools.setToolActive("Length", {mouseButtonMask: 1})

    })
    document.getElementById("rotate").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活旋转
        cornerstoneTools.setToolActive("Rotate", {mouseButtonMask: 1})

    })
    document.getElementById("magnify").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活透视
        cornerstoneTools.setToolActive("Magnify", {mouseButtonMask: 1})

    })
    document.getElementById("pan").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 移动
        cornerstoneTools.setToolActive("Pan", {mouseButtonMask: 1})

    })
    document.getElementById("scaleoverlay").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 尺子
        cornerstoneTools.setToolActive("ScaleOverlay", {mouseButtonMask: 1})

    })
    document.getElementById("zoom").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 放大
        cornerstoneTools.setToolActive("Zoom", {mouseButtonMask: 1})

    })
    document.getElementById("angle").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 角度
        cornerstoneTools.setToolActive("Angle", {mouseButtonMask: 1})

    })
    document.getElementById("arrowannotate").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 添加备注
        cornerstoneTools.setToolActive("ArrowAnnotate", {mouseButtonMask: 1})

    })
    document.getElementById("bidirectional").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活交叉线
        cornerstoneTools.setToolActive("Bidirectional", {mouseButtonMask: 1})

    })
    document.getElementById("cobbangle").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活心胸比
        cornerstoneTools.setToolActive("CobbAngle", {mouseButtonMask: 1})

    })
    document.getElementById("ellipticalroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 圆
        cornerstoneTools.setToolActive("EllipticalRoi", {mouseButtonMask: 1})

    })
    document.getElementById("freehandroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 随便画
        cornerstoneTools.setToolActive("FreehandRoi", {mouseButtonMask: 1})

    })
    document.getElementById("probe").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 探针
        cornerstoneTools.setToolActive("Probe", {mouseButtonMask: 1})

    })
    document.getElementById("rectangleroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("RectangleRoi", {mouseButtonMask: 1})

    })
    document.getElementById("circlescissors").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("CircleScissors", {mouseButtonMask: 1})

    })
    document.getElementById("rectanglescissors").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("RectangleScissors", {mouseButtonMask: 1})

    })

</script>

</html>
5、启动项目
1、第一种,通过pycharm打开

Django 简易PACS读片系统,Django,djangoDjango 简易PACS读片系统,Django,django

2、第二种,命令行的方式
python manage.py runserver
5、查看网页

其中的功能都可以进行操作,后续我进行优化,默认滚动条是切换dicom

http://127.0.0.1:8000/index/

Django 简易PACS读片系统,Django,django文章来源地址https://www.toymoban.com/news/detail-672917.html

6、成功

到了这里,关于Django 简易PACS读片系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Django搭建一个简易AI网站

    处理完项目的环境后,让我们现在创建主项目,在端中运行此命令: 根据Django 文档,django-admin它是一个用于管理任务的命令行实用程序。切换到项目的文件夹,使用命令如下 并创建应用程序assistant,运行命令: 到目前为止,现在应该有一个如下所示的文件夹结构: 让我们

    2024年02月12日
    浏览(33)
  • Django搭建一个简易GPT网站

    处理完项目的环境后,让我们现在创建主项目,在端中运行此命令: 根据Django 文档,django-admin它是一个用于管理任务的命令行实用程序。切换到项目的文件夹,使用命令如下 并创建应用程序assistant,运行命令: 到目前为止,现在应该有一个如下所示的文件夹结构: 让我们

    2024年02月02日
    浏览(45)
  • Python+django+selenium搭建简易自动化测试

    该平台会集成UI自动化及api自动化,里面也会涉及到一些简单的HTML等前端,当然都是很基础的东西。在以后的博客里,我会一点点的尽量写详细,帮助一些测试小白一起成长,当然我也是个小菜鸡。 第一章 django 搭建平台。 1.1搭建环境 Django 官方网站:The web framework for perfe

    2024年02月02日
    浏览(39)
  • 【D01】Django中实现带进度条的倒计时功能(简易版)

    首先说明简易版是只有一个 倒计时 和一个 进度条 ,页面加载后自动开始计时,下次计时需要手动刷新页面。 后续会更新实现完整的倒计时功能的文章 前端框架 你需要准备一些前端框架: Bootstrap4 和 jQuery 安装方法请自行查阅官方文档或教程 Bootstrap4:https://v4.bootcss.com/do

    2023年04月12日
    浏览(40)
  • Django笔记四十三之使用uWSGI部署Django系统

    本文首发于公众号:Hunter后端 原文链接:Django笔记四十三之使用uWSGI部署Django系统 目前部署 Django 的方式一般来说是使用 Nginx + uWSGI + Django 来实现。 处理流程是,当一个请求发送过来会先经过 Nginx,如果是静态文件请求,Nginx 这一层直接处理,如果是后端动态接口,则会发送

    2024年02月05日
    浏览(67)
  • Django开发股票分析系统

    下面是一个简单的示例代码,展示了如何使用Django来创建一个股票管理分析系统。 首先,在你的虚拟环境中安装Django: 然后,创建一个新的Django项目: 进入项目目录: 创建一个新的Django应用: 在 stocks 目录下的 models.py 文件中定义一个股票模型: 在 stocks 目录下的 views.py

    2024年02月16日
    浏览(28)
  • django后台系统Tyadmin

    无意之间发现个django的后台管理框架,仔细与xadmin对比了一下,无论是功能上还是便携性上都与xadmin特别相似,但个人感觉Tyadmin略胜一筹,因为外观上要比xadmin要美观,而且相比起来速度也快,部署甚至也和简单,最重要的是它号称0代码实现后台管理系统,当然如果进行二

    2024年02月14日
    浏览(39)
  • Django基础4——模板系统

    概念: Django模板系统,用于自动渲染一个文本文件,一般用于HTML页面。模板引擎渲染的最终HTML内容返回给客户端浏览器。 模板文件有两部分组成: 静态部分,例如html、css、js 动态部分,django模板语言,类似于jinja语法 Django中的变量: 在函数视图render中的context传入,类似

    2024年02月11日
    浏览(41)
  • Django学习笔记-实现聊天系统

    笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。 聊天系统整体可以分为两部分:输入框与历史记录。 我们需要先修改一下之前代码中的一个小 BUG,当在一个窗口中按 Q 时,另一个窗口中点击鼠标左键也能攻击,因为按下按键的事件被所有窗口都捕

    2024年02月07日
    浏览(41)
  • Django实战:部署项目 【资产管理系统】,Django完整项目学习研究(项目全解析,部署教程,非常详细)

    关于Django,我已经和大家分享了一些知识,考虑到一些伙伴需要在实际的项目中去理解。所以我上传了一套Django的项目学习源码,已经和本文章进行了绑定。大家可以自行下载学习,考虑到一些伙伴是初学者,几年前,编者也是从初学者一路学习到现在。当时,很希望有一套

    2024年02月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包