DPS_Manage/Page/Window_ExPluginInfo_Goods.qml

558 lines
17 KiB
QML
Raw Permalink Normal View History

2025-05-29 14:04:05 +08:00
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtMultimedia 5.15
2025-09-15 09:46:04 +08:00
import HuskarUI.Basic 1.0
2025-05-29 14:04:05 +08:00
import QmlTool 1.0
import FileTransfer 1.0
import "../MyGlobals" 1.0
import "../Component" 1.0
2025-09-15 09:46:04 +08:00
HusWindow {
2025-05-29 14:04:05 +08:00
id:plugininfo_goods
width: 1110
height: 630
visible: true
title: qsTr("插件详情页")
captionBar.topButtonVisible: true
captionBar.winIconDelegate: Image {
id: name
width: 20
height: 20
source: "qrc:/image/logo.png"
}
//原始数据
property var p_basedata: null
//插件名
property string p_name : "未定名插件"
//作者名
property string p_author : "未定名作者"
//版本号
property string p_version: "0.0.1"
//描述
property string p_description: "暂无描述"
//售价
property int p_price: 0
//插件文件数组
property var p_filelist : []
//是否是凌众插件
property bool p_isrindro : false
//图像
property string p_image:"qrc:/image/logo2.png"
Component.onCompleted: {
}
Shortcut {
sequences: ["Esc"]
onActivated: close()
}
function init(index){
//全局数据插件列表存在
if(!GlobalVars.serverPluginexMap)return;
var Data = GlobalVars.serverPluginexMap[index]
p_basedata = Data;
p_name = Data.ProjectName
p_author = Data.ProjectAuthor
p_version = Data.ProjectVersion
p_description = Data.ProjectDescribe
//如果有插件文件数组
if(Data.ProjectFiles)p_filelist = Data.ProjectFiles
//如果有插件的详细描述
if(Data.ProjectDetails)details.model = Data.ProjectDetails
//如果有售价才设置售价
if(Data.ProjectPrice)p_price = Data.ProjectPrice
else p_price = 0
}
function isLocalIP(ip) {
// 检查是否为空或无效IP
if (!ip || typeof ip !== 'string') return false;
// 常见本地IP模式
const localIPPatterns = [
/^127\./, // 127.0.0.0-127.255.255.255
/^10\./, // 10.0.0.0-10.255.255.255
/^172\.(1[6-9]|2[0-9]|3[0-1])\./, // 172.16.0.0-172.31.255.255
/^192\.168\./ // 192.168.0.0-192.168.255.255
];
// 检查是否匹配任何本地IP模式
return localIPPatterns.some(pattern => pattern.test(ip));
}
function buyPlugin(){
var RealBuyIp = GlobalVars.accServerList[GlobalVars.selectServer].serverIp;
if(isLocalIP(RealBuyIp)){
GlobalVars.msg_control.error("暂不支持单机服务器使用双端插件!");
close()
return;
}
GlobalVars.buyExPlugin(p_name,RealBuyIp)
close()
}
Rectangle{
id:title
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 15
anchors.top: parent.top
anchors.topMargin: 45
height:78 + headerdiv.height + description.height
radius:8
2025-09-15 09:46:04 +08:00
border.color: HusTheme.isDark ? "#23272e" : "#f0f4f7"
2025-05-29 14:04:05 +08:00
border.width: 2
color:"transparent"
Image {
id: logo
source: "qrc:/image/logo.png"
anchors.left: parent.left
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 15
width: 48
height: 48
}
2025-09-15 09:46:04 +08:00
HusDivider {
2025-05-29 14:04:05 +08:00
id:headerdiv
anchors.top: logo.bottom
anchors.left: parent.left
anchors.leftMargin: 1
width: parent.width - 1
height: 30
}
Text {
id:description
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
anchors.top: headerdiv.bottom
text: p_description
wrapMode: Text.WordWrap
font {
pixelSize: 14
2025-09-15 09:46:04 +08:00
family: HusTheme.Primary.fontPrimaryFamily
2025-05-29 14:04:05 +08:00
}
2025-09-15 09:46:04 +08:00
color: HusTheme.Primary.colorTextBase
2025-05-29 14:04:05 +08:00
}
Text {
id:pluginname
anchors.left: logo.right
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 14
text: p_name
font {
pixelSize: 20
2025-09-15 09:46:04 +08:00
family: HusTheme.Primary.fontPrimaryFamily
2025-05-29 14:04:05 +08:00
}
2025-09-15 09:46:04 +08:00
color: HusTheme.Primary.colorTextBase
2025-05-29 14:04:05 +08:00
}
Text {
anchors.left: logo.right
anchors.leftMargin: 10
anchors.top: pluginname.bottom
anchors.topMargin: 2
text: "作者: " + p_author
font {
pixelSize: 14
2025-09-15 09:46:04 +08:00
family: HusTheme.Primary.fontPrimaryFamily
2025-05-29 14:04:05 +08:00
}
2025-09-15 09:46:04 +08:00
color: HusTheme.Primary.colorTextBase
2025-05-29 14:04:05 +08:00
}
2025-09-15 09:46:04 +08:00
HusTag {
2025-05-29 14:04:05 +08:00
id:version_tag
anchors.left: pluginname.right
anchors.leftMargin: 15
anchors.top: pluginname.top
anchors.topMargin: 2
text:"Ver:" + p_version
presetColor:"green"
}
2025-09-15 09:46:04 +08:00
HusTag {
2025-05-29 14:04:05 +08:00
id:price_tag
anchors.top: parent.top
anchors.topMargin: 15
anchors.right: parent.right
anchors.rightMargin: 10
text:"所需贡献点:" + p_price
presetColor:"green"
}
2025-09-15 09:46:04 +08:00
HusButton {
2025-05-29 14:04:05 +08:00
id:buy_button
anchors.right: parent.right
anchors.rightMargin: 10
anchors.top: price_tag.bottom
anchors.topMargin: 2
height: 26
text: "购买"
onClicked: {
//我这里临时先写免费服务端插件的安装
buyPlugin();
}
}
}
Rectangle{
id:content
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 15
anchors.top: title.bottom
anchors.topMargin: 10
anchors.bottom:parent.bottom
anchors.bottomMargin: 10
radius:8
2025-09-15 09:46:04 +08:00
border.color: HusTheme.isDark ? "#23272e" : "#f0f4f7"
2025-05-29 14:04:05 +08:00
border.width: 2
color:"transparent"
clip: true
ScrollView {
anchors.fill: parent
anchors.margins: 10
Column {
id: contentColumn
anchors.fill: parent
spacing: 10
Repeater {
id:details
delegate: Column { // 直接使用 Column 作为根元素
width: parent.width
spacing: 0
Loader {
width: parent.width
sourceComponent: {
switch(modelData.type) {
case "str": return textComponent;
case "img": return imageComponent;
case "mov": return videoComponent;
default: return null;
}
}
// 动态绑定组件属性
property var itemData: modelData
}
}
}
}
}
}
// 定义组件映射
Component {
id: textComponent;
Text {
width: parent.width - 20
text: itemData.content
wrapMode: Text.Wrap
font {
pixelSize: 14
2025-09-15 09:46:04 +08:00
family: HusTheme.Primary.fontPrimaryFamily
2025-05-29 14:04:05 +08:00
}
2025-09-15 09:46:04 +08:00
color: HusTheme.Primary.colorTextBase
2025-05-29 14:04:05 +08:00
}
}
Component {
id: imageComponent;
Image {
source: GlobalVars.server_url + "/rindro/getimg/" + p_name + "/" + itemData.content
fillMode: Image.PreserveAspectFit
asynchronous: true
cache: true
// 动态计算宽度
width: Math.min(implicitWidth, parent.width)
// 让图像靠左边显示
anchors.left: parent.left
// 确保父级有明确宽度传递
property real maxWidth: parent ? parent.width : 0
// 异步加载完成后更新尺寸
onStatusChanged: {
if (status === Image.Ready) {
width = Math.min(implicitWidth, maxWidth)
}
}
}
}
// Component {
// id: videoComponent
// Item {
// id: videoContainer
// width: parent.width
// height: 400
// // 视频播放器
// Video {
// id: videoPlayer
// anchors.fill: parent
// anchors.bottomMargin: 15
// source: itemData.content
// loops: MediaPlayer.Infinite
// autoPlay: false
// // 错误处理
// onErrorChanged: {
// if (error !== MediaPlayer.NoError) {
// GlobalVars.msg_control.error("播放错误:", errorString);
// }
// }
// }
// // 播放控制按钮(可选)
// Row {
// anchors.top: videoPlayer.bottom
// anchors.topMargin: 4
// anchors.horizontalCenter: parent.horizontalCenter
// spacing: 10
// DelButton {
// text: videoPlayer.playbackState === MediaPlayer.PlayingState ? "暂停" : "播放"
// onClicked: videoPlayer.playbackState === MediaPlayer.PlayingState ? videoPlayer.pause() : videoPlayer.play()
// }
// DelButton {
// text: "静音"
// onClicked: videoPlayer.muted = !videoPlayer.muted
// }
// }
// }
// }
Component {
id: videoComponent
Item {
id: videoContainer
width: itemData.width
height: itemData.height + 40
// 视频播放器
Video {
id: videoPlayer
anchors {
left: parent.left
right: parent.right
top: parent.top
}
height: itemData.height
anchors.margins: 2
// fillMode: MediaPlayer.PreserveAspectFit // 保持视频比例,不拉伸
// source: itemData.content
source: itemData.content
loops: MediaPlayer.Infinite
autoPlay: false
focus: false // 确保视频播放器不捕获焦点
// 错误处理
onErrorChanged: {
if (error !== MediaPlayer.NoError) {
GlobalVars.msg_control.error("播放错误:", errorString);
}
}
}
// 外边框
Rectangle {
id: border
anchors {
left: videoPlayer.left
right: videoPlayer.right
top: videoPlayer.top
bottom: videoPlayer.bottom
}
border.color: "#cccccc"
border.width: 2
radius: 4
color: "transparent"
z: 1 // 确保边框在视频上方
}
// 视频加载状态指示器
Rectangle {
id: loadingIndicator
anchors.centerIn: videoPlayer
width: 60
height: 60
radius: 30
color: "#00000048"
z: 2 // 确保加载指示器在最上层
Text {
id: loadingText
anchors.centerIn: parent
text: "加载中..."
color: "white"
font.pixelSize: 12
}
visible: videoPlayer.status === MediaPlayer.LoadingStatus
}
// 错误提示文本
Text {
id: errorText
anchors.centerIn: videoPlayer
text: "视频加载失败,请检查链接或网络"
color: "red"
font.pixelSize: 14
visible: videoPlayer.error !== MediaPlayer.NoError
z: 2 // 确保错误文本在最上层
}
// 进度条容器,移到视频下方
Rectangle {
id: progressBarContainer
anchors {
left: parent.left
right: parent.right
bottom: videoPlayer.bottom
bottomMargin: 2
}
height: 10
color: "#00000048"
radius: 2
z: 2 // 确保进度条在最上层
Rectangle {
id: progressBar
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
}
width: parent.width * (videoPlayer.position / Math.max(1, videoPlayer.duration))
color: "#0078d7"
radius: 2
}
MouseArea {
id: progressBarMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
propagateComposedEvents: true // 允许事件传播
onPressed: {
if (videoPlayer.duration > 0)
videoPlayer.seek((mouse.x / width) * videoPlayer.duration)
}
onPositionChanged: {
if (mouse.pressedButtons & Qt.LeftButton && videoPlayer.duration > 0) {
videoPlayer.seek((mouse.x / width) * videoPlayer.duration)
}
}
}
}
// 播放控制按钮,移到视频下方
Row {
id: controlButtons
anchors {
top: videoPlayer.bottom
topMargin: 5
horizontalCenter: parent.horizontalCenter
}
spacing: 10
visible: true
z: 2 // 确保控制按钮在最上层
2025-09-15 09:46:04 +08:00
HusButton {
2025-05-29 14:04:05 +08:00
id: playPauseButton
text: videoPlayer.playbackState === MediaPlayer.PlayingState ? "暂停" : "播放"
onClicked: {
if (videoPlayer.playbackState === MediaPlayer.PlayingState)
videoPlayer.pause()
else
videoPlayer.play()
}
}
2025-09-15 09:46:04 +08:00
HusButton {
2025-05-29 14:04:05 +08:00
id: muteButton
text: videoPlayer.muted ? "取消静音" : "静音"
onClicked: videoPlayer.muted = !videoPlayer.muted
}
2025-09-15 09:46:04 +08:00
HusButton {
2025-05-29 14:04:05 +08:00
id: replayButton
text: "重播"
onClicked: {
videoPlayer.seek(0)
videoPlayer.play()
}
}
2025-09-15 09:46:04 +08:00
HusButton {
2025-05-29 14:04:05 +08:00
text: "外部浏览器打开"
onClicked: {
Qt.openUrlExternally(GlobalVars.server_url + "/api/videos/" + p_name + "/" + itemData.index)
}
}
}
// 鼠标悬停显示控制按钮
MouseArea {
id: containerMouseArea
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true // 允许事件传播
z: 1 // 确保鼠标区域在适当层级
// onEntered: {
// controlButtons.visible = true
// progressBarContainer.visible = true
// }
// onExited: {
// controlButtons.visible = false
// progressBarContainer.visible = false
// }
}
}
}
/*
DelButton {
text: "Open XLSX File"
anchors.centerIn: parent
onClicked: {
var filePath = "./基础配置.xlsx"; // 请替换为实际的文件路径
QmlTool.openFile(filePath);
}
}
*/
}