模块缝合完成

This commit is contained in:
aiShuiJiaoDeXioShou 2024-09-19 01:44:07 +08:00
parent 1714f45ef5
commit 3ce5aa3711
8 changed files with 354 additions and 43 deletions

9
acdr-ui/env/.env vendored
View File

@ -7,10 +7,11 @@ VITE_WX_APPID = 'wxf2c6d4b7361366b4'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base # h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/acdr/ VITE_APP_PUBLIC_BASE=/acdr/
VITE_SERVER_BASEURL = 'http://47.99.70.12:28184/api' # VITE_SERVER_BASEURL = 'http://47.99.70.12:28184/api'
# VITE_UPLOAD_BASEURL = 'http://47.99.70.12:28184' # VITE_UPLOAD_BASEURL = 'http://47.99.70.12:28184'
# VITE_SERVER_BASEURL = 'http://localhost:28184/api' # VITE_SERVER_BASEURL = 'http://localhost:28184/api'
VITE_WS_BASEURL = 'ws://47.99.70.12:28184/api' VITE_SERVER_BASEURL = 'http://localhost:48080/app-api'
# VITE_WS_BASEURL = 'ws://47.99.70.12:28184/api'
VITE_UPLOAD_BASEURL = 'http://localhost:28184' VITE_UPLOAD_BASEURL = 'http://localhost:28184'
VITE_OSS_BASEURL = 'http://116.204.119.171:9000/linghe' VITE_OSS_BASEURL = 'http://116.204.119.171:9000/linghe'
@ -25,8 +26,8 @@ SHOPRO_VERSION = v1.8.3
SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn SHOPRO_BASE_URL = http://api-dashboard.yudao.iocoder.cn
# 后端接口 - 测试环境(通过 process.env.NODE_ENV = development # 后端接口 - 测试环境(通过 process.env.NODE_ENV = development
# SHOPRO_DEV_BASE_URL = http://127.0.0.1:48080 SHOPRO_DEV_BASE_URL = http://127.0.0.1:48080
SHOPRO_DEV_BASE_URL = http://47.99.70.12:48080 # SHOPRO_DEV_BASE_URL = http://47.99.70.12:48080
### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc ### SHOPRO_DEV_BASE_URL = http://yunai.natapp1.cc
# 后端接口前缀(一般不建议调整) # 后端接口前缀(一般不建议调整)

View File

@ -1,6 +1,6 @@
{ {
"name": "宠屋", "name": "宠屋",
"appid": "H57F2ACE4", "appid": "__UNI__9D479DC",
"description": "", "description": "",
"versionName": "1.0.0", "versionName": "1.0.0",
"versionCode": "100", "versionCode": "100",

View File

@ -38,7 +38,7 @@ import { ref, onMounted, onUnmounted } from 'vue'
import { httpGet, httpPost } from '@/utils/http' import { httpGet, httpPost } from '@/utils/http'
import { useUserStore } from '@/store/user' import { useUserStore } from '@/store/user'
import TopBar from '@/components/TopBar.vue' import TopBar from '@/components/TopBar.vue'
import { imgUrl } from '@/utils/commUtils' import { imgUrl, toast, toPath } from "@/utils/commUtils";
const userStore = useUserStore() const userStore = useUserStore()
@ -50,26 +50,15 @@ let timer = null
const sendCode = async () => { const sendCode = async () => {
if (countdown.value === 0) { if (countdown.value === 0) {
if (!phoneNumber.value) { if (!phoneNumber.value) {
uni.showToast({ toast('请输入手机号')
title: '请输入手机号',
icon: 'none',
})
return return
} }
console.log('发送验证码到', phoneNumber.value)
const res = await httpGet('/public/getCode', { phone: phoneNumber.value }) const res = await httpGet('/public/getCode', { phone: phoneNumber.value })
console.log(res)
countdown.value = 60 countdown.value = 60
if (res.code == 200) { if (res.code === 200) {
uni.showToast({ toast(res.message)
title: res.message,
icon: 'none',
})
} else { } else {
uni.showToast({ toast(res.message)
title: res.message,
icon: 'none',
})
} }
timer = setInterval(() => { timer = setInterval(() => {
countdown.value -= 1 countdown.value -= 1
@ -96,29 +85,24 @@ const login = async () => {
return return
} }
const res = await httpPost('/public/login', {}, { phone: phoneNumber.value, code: code.value }) const res = await httpPost('/public/login', {}, { phone: phoneNumber.value, code: code.value })
if (res.code == 200) { if (res.code === 200) {
uni.showToast({ toast(res.message)
title: res.message, const data = res.data
icon: 'none', userStore.setUserInfo({
id: data.userId ,
token: data.accessToken,
expiresTime: data.expiresTime,
refreshToken: data.refreshToken
}) })
userStore.setUserInfo({ token: res.data.userToken, shopLoginUser: res.data.shopLoginUser })
const userRes = await httpGet('/user/userinfo') const userRes = await httpGet('/user/userinfo')
if (userRes.code == 200) { if (userRes.code === 200) {
userStore.setUserInfo(userRes.data) userStore.setUserInfo(userRes.data)
uni.switchTab({ toPath('/')
url: '/pages/index/index',
})
} else { } else {
uni.showToast({ toast(userRes.message || '登录失败请重新登录!')
title: userRes.message,
icon: 'none',
})
} }
} else { } else {
uni.showToast({ toast(res.message || '登录失败请重新登录!')
title: res.message,
icon: 'none',
})
} }
} }

View File

@ -6,17 +6,16 @@ const initState = {
avatar: '', avatar: '',
id: null, id: null,
name: '', name: '',
phone: '', mobile: '',
email: '', cardId: '',
typeId: '',
createTime: '', createTime: '',
updateTime: '', updateTime: '',
token: '', token: '',
sex: '', sex: '',
openid: '', // 微信openid如果不为空就证明用户是用微信登录的
isRealName: false, isRealName: false,
isPetNursery: false, isPetNursery: false,
shopLoginUser: null, expiresTime: '',
refreshToken: '',
} }
export const useUserStore = defineStore( export const useUserStore = defineStore(

View File

@ -0,0 +1,45 @@
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image
class GIFMakerApp:
def __init__(self, root):
self.root = root
self.root.title("GIF Maker")
# 选择图片按钮
self.select_button = tk.Button(root, text="选择图片", command=self.select_images)
self.select_button.pack(pady=10)
# 保存 GIF 按钮
self.save_button = tk.Button(root, text="保存 GIF", command=self.save_gif, state=tk.DISABLED)
self.save_button.pack(pady=10)
self.images = [] # 保存选择的图片
def select_images(self):
# 选择多张图片
image_paths = filedialog.askopenfilenames(title="选择图片", filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp"), ("All files", "*.*")])
if image_paths:
self.images = [Image.open(image_path) for image_path in image_paths] # 打开所有选择的图片
messagebox.showinfo("已选择图片", f"已选择 {len(self.images)} 张图片")
self.save_button.config(state=tk.NORMAL) # 启用保存按钮
def save_gif(self):
if not self.images:
messagebox.showwarning("警告", "没有选择图片!")
return
# 设置保存文件名
save_path = filedialog.asksaveasfilename(defaultextension=".gif", filetypes=[("GIF files", "*.gif")])
if save_path:
# 保存为GIF指定每帧的时间间隔
self.images[0].save(save_path, save_all=True, append_images=self.images[1:], duration=10, loop=0)
messagebox.showinfo("成功", f"GIF 已保存到: {save_path}")
# 启动 GUI 应用
if __name__ == "__main__":
root = tk.Tk()
app = GIFMakerApp(root)
root.geometry("300x200")
root.mainloop()

View File

@ -0,0 +1,126 @@
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import os
class ImageCropApp:
def __init__(self, root):
self.root = root
self.root.title("Multi Image Crop Tool")
# 选择图片按钮
self.select_button = tk.Button(root, text="选择图片", command=self.select_images)
self.select_button.pack(pady=10)
# 画布,用于显示图片
self.canvas = tk.Canvas(root, cursor="cross")
self.canvas.pack(fill=tk.BOTH, expand=True)
self.images = [] # 用于保存选择的多张图片路径
self.image = None # 当前显示的图片
self.rect_start_x = 0
self.rect_start_y = 0
self.rect_end_x = 0
self.rect_end_y = 0
self.rect = None
self.tk_image = None
self.save_dir = None # 保存路径
self.image_display_width = 0 # 显示图片的宽度
self.image_display_height = 0 # 显示图片的高度
self.image_original_width = 0 # 图片的原始宽度
self.image_original_height = 0 # 图片的原始高度
# 鼠标事件
self.canvas.bind("<Button-1>", self.start_selection)
self.canvas.bind("<B1-Motion>", self.update_selection)
self.canvas.bind("<ButtonRelease-1>", self.finish_selection)
def select_images(self):
# 多文件选择
image_paths = filedialog.askopenfilenames(title="选择多张图片", filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp"), ("All files", "*.*")])
if image_paths:
self.images = list(image_paths) # 将文件路径保存为列表
self.load_first_image()
def load_first_image(self):
# 加载第一张图片并显示在画布上
if self.images:
self.image = Image.open(self.images[0])
self.image_original_width, self.image_original_height = self.image.size # 获取原始尺寸
self.display_image()
def display_image(self):
# 调整图片大小适应窗口
self.image.thumbnail((self.root.winfo_width(), self.root.winfo_height())) # 缩放图片
self.tk_image = ImageTk.PhotoImage(self.image)
self.image_display_width, self.image_display_height = self.image.size # 显示的宽高
self.canvas.create_image(0, 0, anchor="nw", image=self.tk_image)
def start_selection(self, event):
# 记录起始点
self.rect_start_x = event.x
self.rect_start_y = event.y
# 创建一个选择框
self.rect = self.canvas.create_rectangle(self.rect_start_x, self.rect_start_y, self.rect_start_x, self.rect_start_y, outline="red", width=2)
def update_selection(self, event):
# 更新选择框大小
self.rect_end_x = event.x
self.rect_end_y = event.y
self.canvas.coords(self.rect, self.rect_start_x, self.rect_start_y, self.rect_end_x, self.rect_end_y)
def finish_selection(self, event):
self.rect_end_x = event.x
self.rect_end_y = event.y
self.crop_images()
def crop_images(self):
if self.images:
# 计算图像与显示窗口的比例
x_ratio = self.image_original_width / self.image_display_width
y_ratio = self.image_original_height / self.image_display_height
# 获取选择框的坐标,并转换为图片的实际坐标
left = min(self.rect_start_x, self.rect_end_x) * x_ratio
top = min(self.rect_start_y, self.rect_end_y) * y_ratio
right = max(self.rect_start_x, self.rect_end_x) * x_ratio
bottom = max(self.rect_start_y, self.rect_end_y) * y_ratio
# 让用户选择保存文件夹,只选择一次
if self.save_dir is None:
self.save_dir = filedialog.askdirectory(title="选择保存文件夹")
if not self.save_dir:
messagebox.showwarning("警告", "未选择保存文件夹,操作已取消")
return
for image_path in self.images:
img = Image.open(image_path)
img_original_width, img_original_height = img.size # 获取每张图片的原始大小
# 根据比例缩放选择区域并裁剪
left_scaled = left * (img_original_width / self.image_original_width)
top_scaled = top * (img_original_height / self.image_original_height)
right_scaled = right * (img_original_width / self.image_original_width)
bottom_scaled = bottom * (img_original_height / self.image_original_height)
cropped_image = img.crop((left_scaled, top_scaled, right_scaled, bottom_scaled))
# 自动生成默认文件名
base_name = os.path.basename(image_path)
default_filename = f"cropped_{base_name}"
# 保存路径与文件名
save_path = os.path.join(self.save_dir, default_filename)
cropped_image.save(save_path)
print(f"图片已保存到: {save_path}")
messagebox.showinfo("成功", "所有图片裁剪完成!")
# 启动 GUI 应用
if __name__ == "__main__":
root = tk.Tk()
app = ImageCropApp(root)
root.geometry("800x600") # 设置初始窗口大小
root.mainloop()

View File

@ -0,0 +1,83 @@
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk, ImageGrab
class ImageCropApp:
def __init__(self, root):
self.root = root
self.root.title("Image Crop Tool")
# 选择图片按钮
self.select_button = tk.Button(root, text="选择图片", command=self.select_image)
self.select_button.pack(pady=10)
# 画布,用于显示图片
self.canvas = tk.Canvas(root, cursor="cross")
self.canvas.pack(fill=tk.BOTH, expand=True)
self.image = None # 用于保存选择的图片
self.rect_start_x = 0
self.rect_start_y = 0
self.rect_end_x = 0
self.rect_end_y = 0
self.rect = None
self.tk_image = None
# 鼠标事件
self.canvas.bind("<Button-1>", self.start_selection)
self.canvas.bind("<B1-Motion>", self.update_selection)
self.canvas.bind("<ButtonRelease-1>", self.finish_selection)
def select_image(self):
image_path = filedialog.askopenfilename(title="选择图片", filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp"), ("All files", "*.*")])
if image_path:
self.image = Image.open(image_path)
self.display_image()
def display_image(self):
# 调整图片大小适应窗口
self.image.thumbnail((self.root.winfo_width(), self.root.winfo_height()))
self.tk_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor="nw", image=self.tk_image)
def start_selection(self, event):
# 记录起始点
self.rect_start_x = event.x
self.rect_start_y = event.y
# 创建一个选择框
self.rect = self.canvas.create_rectangle(self.rect_start_x, self.rect_start_y, self.rect_start_x, self.rect_start_y, outline="red", width=2)
def update_selection(self, event):
# 更新选择框大小
self.rect_end_x = event.x
self.rect_end_y = event.y
self.canvas.coords(self.rect, self.rect_start_x, self.rect_start_y, self.rect_end_x, self.rect_end_y)
def finish_selection(self, event):
self.rect_end_x = event.x
self.rect_end_y = event.y
self.crop_image()
def crop_image(self):
if self.image:
# 获取选择框的坐标
left = min(self.rect_start_x, self.rect_end_x)
top = min(self.rect_start_y, self.rect_end_y)
right = max(self.rect_start_x, self.rect_end_x)
bottom = max(self.rect_start_y, self.rect_end_y)
# 根据选择框坐标进行裁剪
cropped_image = self.image.crop((left, top, right, bottom))
# 让用户选择保存路径
save_path = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png"), ("All files", "*.*")])
if save_path:
cropped_image.save(save_path)
messagebox.showinfo("成功", f"图片已保存到: {save_path}")
# 启动 GUI 应用
if __name__ == "__main__":
root = tk.Tk()
app = ImageCropApp(root)
root.geometry("800x600") # 设置初始窗口大小
root.mainloop()

View File

@ -0,0 +1,73 @@
import tkinter as tk
from tkinter import filedialog, messagebox
import cv2
import os
# GUI 界面
class VideoToFramesApp:
def __init__(self, root):
self.root = root
self.root.title("Video to Frames Converter")
# 文件选择按钮
self.select_button = tk.Button(
root, text="选择视频文件", command=self.select_video
)
self.select_button.pack(pady=10)
# 选择输出文件夹按钮
self.select_folder_button = tk.Button(
root, text="选择输出文件夹", command=self.select_output_folder
)
self.select_folder_button.pack(pady=10)
# 开始转换按钮
self.convert_button = tk.Button(
root, text="开始转换", command=self.convert_video
)
self.convert_button.pack(pady=10)
self.video_path = None
self.output_folder = None
def select_video(self):
self.video_path = filedialog.askopenfilename(
title="选择视频文件",
filetypes=(("MP4 files", "*.mp4"), ("All files", "*.*")),
)
if self.video_path:
messagebox.showinfo("文件已选择", f"已选择视频文件:{self.video_path}")
def select_output_folder(self):
self.output_folder = filedialog.askdirectory(title="选择输出文件夹")
if self.output_folder:
messagebox.showinfo("文件夹已选择", f"输出文件夹:{self.output_folder}")
def convert_video(self):
if not self.video_path or not self.output_folder:
messagebox.showwarning("错误", "请先选择视频文件和输出文件夹!")
return
try:
cap = cv2.VideoCapture(self.video_path)
count = 0
while True:
ret, frame = cap.read()
if not ret:
break
frame_filename = os.path.join(self.output_folder, f"frame_{count}.jpg")
cv2.imwrite(frame_filename, frame)
count += 1
cap.release()
messagebox.showinfo("成功", f"成功提取了 {count} 帧图片")
except Exception as e:
messagebox.showerror("错误", f"发生错误:{e}")
# 启动 GUI 应用
if __name__ == "__main__":
root = tk.Tk()
app = VideoToFramesApp(root)
root.mainloop()