Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
client
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
381016e6
authored
Sep 08, 2025
by
lijinqi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
api购买、我的api订单 完成
parent
5e6d28fd
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
864 additions
and
119 deletions
+864
-119
src/api/apiorder.js
+62
-0
src/layout/components/AppMain.vue
+20
-0
src/layout/user-layout.vue
+17
-3
src/router/index.js
+25
-1
src/views/console/apiOrder.vue
+351
-0
src/views/console/apiResources.vue
+174
-0
src/views/marketplace/AIMarketplace.vue
+82
-79
src/views/marketplace/AIMarketplaceDetail.vue
+133
-36
No files found.
src/api/apiorder.js
0 → 100644
View file @
381016e6
import
request
from
'@/utils/request.js'
// 查询api订单管理
export
function
getApiOrder
(
query
)
{
return
request
({
url
:
'/apihub/api-order/page'
,
method
:
'get'
,
params
:
query
})
}
// 查询订单管理-需求单管理详细
export
function
getOrder
(
id
)
{
return
request
({
url
:
'/computility/order/'
+
id
,
method
:
'get'
})
}
// 新增订单管理-需求单管理
export
function
addOrder
(
data
)
{
return
request
({
url
:
'/computility/order'
,
method
:
'post'
,
data
:
data
})
}
// 修改订单管理-需求单管理
export
function
updateOrder
(
data
)
{
return
request
({
url
:
'/computility/order'
,
method
:
'put'
,
data
:
data
})
}
// 删除订单管理-需求单管理
export
function
delOrder
(
id
)
{
return
request
({
url
:
'/computility/order/'
+
id
,
method
:
'delete'
})
}
// 取消订单-订单管理
export
function
cancelOrder
(
data
)
{
return
request
({
url
:
'/api/v1/orderCancel'
,
method
:
'post'
,
data
:
data
})
}
// 查看驳回理由-订单管理
export
function
orderReason
(
id
)
{
return
request
({
url
:
`/api/v1/orderReason/
${
id
}
`
,
method
:
'get'
})
}
src/layout/components/AppMain.vue
View file @
381016e6
...
...
@@ -16,6 +16,26 @@ import iframeToggle from "./IframeToggle/index"
import
useTagsViewStore
from
'@/store/modules/tagsView'
const
tagsViewStore
=
useTagsViewStore
()
import
{
watch
,
nextTick
}
from
'vue'
import
{
useRoute
}
from
'vue-router'
const
route
=
useRoute
()
// 路由变化时自动滚动到顶部
watch
(
()
=>
route
.
fullPath
,
()
=>
{
nextTick
(()
=>
{
const
el
=
document
.
querySelector
(
'.app-main'
)
if
(
el
)
{
el
.
scrollTop
=
0
}
else
{
window
.
scrollTo
({
top
:
0
,
behavior
:
'auto'
})
}
})
}
)
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
src/layout/user-layout.vue
View file @
381016e6
...
...
@@ -16,7 +16,7 @@
mode=
"horizontal"
style=
"--el-menu-horizontal-height:48px"
@
select=
"menuSelect"
>
<el-menu-item
index=
"/marketplace/ai"
>
AI应用市场
</el-menu-item>
<el-sub-menu
index=
"computingResource"
>
<template
#
title
>
计算资源
</
template
>
<el-menu-item
...
...
@@ -25,10 +25,15 @@
{{ item.name }}
</el-menu-item>
</el-sub-menu>
<el-menu-item
index=
"/industryApplications/index"
>
解决方案
</el-menu-item>
<el-menu-item
index=
"/componentServices/componentServicesList"
>
行业应用
</el-menu-item>
<el-menu-item
index=
"/partnership/partnershipList"
>
合作伙伴
</el-menu-item>
<!-- 👇 API服务市场放到最后 -->
<el-menu-item
index=
"/marketplace/ai"
>
API服务市场
</el-menu-item>
</el-menu>
</div>
<div
class=
"right-menu flex-align-center"
>
...
...
@@ -183,11 +188,20 @@ function logout() {
.menu
{
width
:
600px
;
flex
:
1
;
flex
:
1
;
//
占据剩余空间
margin-left
:
72px
;
min-width
:
400px
;
//
保底宽度,避免被压缩到太小
overflow
:
visible
;
}
.right-menu
{
display
:
flex
;
align-items
:
center
;
margin-left
:
auto
;
//
把右侧挤到最右
}
:deep
(
.el-menu
)
{
border-bottom
:
none
;
...
...
src/router/index.js
View file @
381016e6
...
...
@@ -218,6 +218,30 @@ export const constantRoutes = [
{
path
:
'/console'
,
component
:
ManageLayout
,
children
:
[
{
path
:
'apiOrder'
,
component
:
()
=>
import
(
'@/views/console/apiOrder.vue'
),
name
:
'ApiOrder'
,
meta
:
{
title
:
'API订单'
,
icon
:
'order'
}
}
]
},
{
path
:
'/console'
,
component
:
ManageLayout
,
children
:
[
{
path
:
'apiResources'
,
component
:
()
=>
import
(
'@/views/console/apiResources.vue'
),
name
:
'ApiResources'
,
meta
:
{
title
:
'API资源'
,
icon
:
'instock'
}
}
]
},
{
path
:
'/console'
,
component
:
ManageLayout
,
hidden
:
true
,
children
:
[
{
...
...
@@ -236,7 +260,7 @@ export const constantRoutes = [
path
:
'ai'
,
component
:
()
=>
import
(
'@/views/marketplace/AIMarketplace.vue'
),
name
:
'AIMarketplace'
,
meta
:
{
title
:
'A
I应用
市场'
}
meta
:
{
title
:
'A
PI服务
市场'
}
},
{
path
:
'ai/detail'
,
...
...
src/views/console/apiOrder.vue
0 → 100644
View file @
381016e6
<
template
>
<div
class=
"app-container"
>
<el-form
:model=
"queryParams"
ref=
"queryRef"
:inline=
"true"
v-show=
"showSearch"
label-width=
"68px"
>
<!--
<el-form-item
label=
"订单编号"
prop=
"orderNo"
>
-->
<!--
<el-input-->
<!-- v-model="queryParams.orderNo"-->
<!-- placeholder="请输入订单编号"-->
<!-- clearable-->
<!-- @keyup.enter="handleQuery"-->
<!-- />-->
<!--
</el-form-item>
-->
<el-form-item
label=
"API类型"
prop=
"category"
>
<el-select
v-model=
"queryParams.category"
placeholder=
"请选择API类型"
clearable
>
<el-option
v-for=
"dict in application_category"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
/>
</el-select>
</el-form-item>
<!--
<el-form-item
label=
"型号"
prop=
"model"
>
-->
<!--
<el-select-->
<!-- v-model="queryParams.model"-->
<!-- placeholder="请选择型号"-->
<!-- clearable-->
<!-- >-->
<!--
<el-option-->
<!-- v-for="dict in model"-->
<!-- :key="dict.value"-->
<!-- :label="dict.label"-->
<!-- :value="dict.value"-->
<!-- />-->
<!--
</el-select>
-->
<!--
</el-form-item>
-->
<!--
<el-form-item
label=
"CPU"
prop=
"cpu"
>
-->
<!--
<el-select
v-model=
"queryParams.cpu"
placeholder=
"请选择CPU"
clearable
>
-->
<!--
<el-option-->
<!-- v-for="dict in cpu_type"-->
<!-- :key="dict.value"-->
<!-- :label="dict.label"-->
<!-- :value="dict.value"-->
<!-- />-->
<!--
</el-select>
-->
<!--
</el-form-item>
-->
<!--
<el-form-item
label=
"GPU"
prop=
"gpu"
>
-->
<!--
<el-select
v-model=
"queryParams.gpu"
placeholder=
"请选择GPU"
clearable
>
-->
<!--
<el-option-->
<!-- v-for="dict in gpu_type"-->
<!-- :key="dict.value"-->
<!-- :label="dict.label"-->
<!-- :value="dict.value"-->
<!-- />-->
<!--
</el-select>
-->
<!--
</el-form-item>
-->
<!--
<el-form-item
label=
"内存"
prop=
"memory"
>
-->
<!--
<el-select-->
<!-- v-model="queryParams.memory"-->
<!-- placeholder="请选择内存"-->
<!-- clearable-->
<!-- >-->
<!--
<el-option-->
<!-- v-for="dict in memory_type"-->
<!-- :key="dict.value"-->
<!-- :label="dict.label"-->
<!-- :value="dict.value"-->
<!-- />-->
<!--
</el-select>
-->
<!--
</el-form-item>
-->
<el-form-item
label=
"高级查询"
prop=
"searchQuery"
>
<el-input
v-model=
"queryParams.searchQuery"
placeholder=
"请输入api名称/订单编号"
clearable
style=
"width: 200px"
@
keyup
.
enter=
"handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
icon=
"Search"
@
click=
"handleQuery"
>
搜索
</el-button
>
<el-button
icon=
"Refresh"
@
click=
"resetQuery"
>
重置
</el-button>
</el-form-item>
</el-form>
<el-table
v-loading=
"loading"
:data=
"orderList"
:max-height=
"620"
>
<!--
<el-table-column
type=
"selection"
width=
"45"
align=
"center"
/>
-->
<!--
<el-table-column
label=
"序号"
align=
"center"
prop=
"id"
/>
-->
<el-table-column
label=
"订单编号"
align=
"center"
prop=
"orderNo"
/>
<el-table-column
label=
"api名称"
align=
"center"
prop=
"apiName"
/>
<el-table-column
label=
"资源包"
align=
"center"
prop=
"packageName"
/>
<el-table-column
label=
"使用次数"
align=
"center"
prop=
"packageTimes"
/>
<el-table-column
label=
有效期
align=
"center"
prop=
"packageValidDays"
/>
<el-table-column
label=
"实付金额"
align=
"center"
prop=
"costPrice"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
costPrice
/
100
}}
</
template
>
</el-table-column>
<!-- <el-table-column label="商品类别" align="center" prop="category">-->
<!-- <template #default="scope">-->
<!-- <dict-tag-->
<!-- :options="application_category"-->
<!-- :value="scope.row.category"-->
<!-- />-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- v-for="(item, index) in orderList[0]?.properties.length!==0?orderList[0]?.properties.slice(0,4):orderList[0]?.properties"-->
<!-- :key="index"-->
<!-- :label="item.propertyName"-->
<!-- >-->
<!-- <template #default="{ row }">-->
<!-- {{ row.properties[index].valueName }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
label=
"订单状态"
align=
"center"
prop=
"statusName"
/>
<el-table-column
label=
"下单时间"
align=
"center"
prop=
"createTime"
width=
"180"
>
<
template
#
default=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
createTime
,
'
{
y
}
-
{
m
}
-
{
d
}
{
h
}
:{
i
}
:{
s
}'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
fixed
=
"right"
class
-
name
=
"small-padding fixed-width"
>
<
template
#
default
=
"scope"
>
<
el
-
button
link
type
=
"primary"
@
click
=
"handleDetails(scope.row)"
>
详情
<
/el-button
>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
pagination
v
-
show
=
"total > 0"
:
total
=
"total"
v
-
model
:
page
=
"queryParams.pageNum"
v
-
model
:
limit
=
"queryParams.pageSize"
@
pagination
=
"getList"
/>
<!--
添加或修改订单管理
-
需求单管理对话框
-->
<
el
-
dialog
:
title
=
"title"
v
-
model
=
"open"
width
=
"500px"
append
-
to
-
body
>
<
div
>
<
div
class
=
"info-block"
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
商品名称
<
/div
>
<
div
class
=
"value"
>
{{
form
.
spuName
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
订单编号
<
/div
>
<
div
class
=
"value"
>
{{
form
.
no
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
费用
<
/div
>
<
div
class
=
"value"
>
{{
form
.
payPrice
?
(
form
.
payPrice
/
100
)
:
'-'
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
商品类别
<
/div
>
<
div
class
=
"value"
>
{{
form
.
categoryName
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"info-block"
>
<
div
class
=
"info-item flex-align-center flex-space-between"
v
-
for
=
"(i,index) in form.properties"
:
key
=
"i.index"
>
<
div
class
=
"label"
>
{{
i
.
propertyName
}}
<
/div
>
<
div
class
=
"value"
>
{{
i
.
valueName
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
订单状态
<
/div
>
<
div
class
=
"value"
>
{{
form
.
statusName
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
下单时间
<
/div
>
<
div
class
=
"value"
>
{{
parseTime
(
form
.
createTime
,
'
{
y
}
-
{
m
}
-
{
d
}
{
h
}
:{
i
}
:{
s
}'
)
}}
<
/div
>
<
/div
>
<
/div
>
<
template
#
footer
>
<
div
class
=
"dialog-footer"
>
<
el
-
button
@
click
=
"cancel"
>
关闭
<
/el-button
>
<
/div
>
<
/template
>
<
/el-dialog
>
<
/div
>
<
/template
>
<
script
setup
name
=
"ApiOrder"
>
import
{
getApiOrder
}
from
'@/api/apiorder.js'
import
{
parseTime
}
from
"../../utils/ruoyi.js"
;
const
{
proxy
}
=
getCurrentInstance
()
const
orderList
=
ref
([])
const
open
=
ref
(
false
)
const
sOpen
=
ref
(
false
)
const
loading
=
ref
(
true
)
const
showSearch
=
ref
(
true
)
const
total
=
ref
(
0
)
const
title
=
ref
(
''
)
const
data
=
reactive
({
form
:
{
}
,
queryParams
:
{
pageNo
:
1
,
pageSize
:
10
,
searchQuery
:
null
,
status
:
null
}
,
rules
:
{
category
:
[
{
required
:
true
,
message
:
'商品类别不能为空'
,
trigger
:
'change'
}
],
model
:
[{
required
:
true
,
message
:
'型号不能为空'
,
trigger
:
'change'
}
],
cpu
:
[{
required
:
true
,
message
:
'CPU不能为空'
,
trigger
:
'change'
}
],
gpu
:
[{
required
:
true
,
message
:
'GPU不能为空'
,
trigger
:
'change'
}
],
memory
:
[{
required
:
true
,
message
:
'内存不能为空'
,
trigger
:
'change'
}
],
storage
:
[
{
required
:
true
,
message
:
'存储硬盘不能为空'
,
trigger
:
'change'
}
],
orderStatus
:
[
{
required
:
true
,
message
:
'状态不能为空'
,
trigger
:
'change'
}
],
networkId
:
[
{
required
:
true
,
message
:
'网络带宽不能为空'
,
trigger
:
'blur'
}
],
submitTime
:
[
{
required
:
true
,
message
:
'申请时间不能为空'
,
trigger
:
'blur'
}
],
applyUser
:
[{
required
:
true
,
message
:
'应用人不能为空'
,
trigger
:
'blur'
}
],
useTime
:
[{
required
:
true
,
message
:
'使用期限不能为空'
,
trigger
:
'blur'
}
],
createTime
:
[
{
required
:
true
,
message
:
'创建时间不能为空'
,
trigger
:
'blur'
}
]
}
}
)
const
{
queryParams
,
form
,
rules
}
=
toRefs
(
data
)
/** 查询订单 */
function
loadList
()
{
loading
.
value
=
true
getApiOrder
(
queryParams
.
value
).
then
((
response
)
=>
{
orderList
.
value
=
response
.
data
.
list
total
.
value
=
response
.
data
.
total
loading
.
value
=
false
}
)
}
// 取消按钮
function
cancel
()
{
open
.
value
=
false
reset
()
}
// 表单重置
function
reset
()
{
form
.
value
=
{
searchQuery
:
null
,
status
:
null
}
proxy
.
resetForm
(
'orderRef'
)
}
/** 搜索按钮操作 */
function
handleQuery
()
{
queryParams
.
value
.
pageNum
=
1
loadList
()
}
/** 重置按钮操作 */
function
resetQuery
()
{
proxy
.
resetForm
(
'queryRef'
)
handleQuery
()
}
function
handleDetails
(
row
)
{
const
_id
=
row
.
id
||
ids
.
value
// getResources(
{
id
:
_id
}
).
then
(
response
=>
{
// form.value = response.data
open
.
value
=
true
title
.
value
=
'查看订单'
//
}
)
}
loadList
()
<
/script
>
<
style
lang
=
"scss"
scoped
>
.
el
-
form
{
padding
:
20
px
20
px
0
20
px
;
border
-
radius
:
4
px
;
background
-
color
:
#
FFFFFF
;
margin
-
bottom
:
20
px
;
}
.
pagination
-
container
{
background
-
color
:
transparent
;
}
.
info
-
block
{
background
-
color
:
#
ffffff
;
padding
:
4
px
0
;
//margin-bottom: 14px;
}
.
info
-
item
{
padding
:
12
px
20
px
;
.
label
{
font
-
weight
:
400
;
font
-
size
:
16
px
;
color
:
#
626566
;
}
.
value
{
font
-
weight
:
bold
;
font
-
size
:
16
px
;
color
:
#
303233
;
}
}
<
/style
>
src/views/console/apiResources.vue
0 → 100644
View file @
381016e6
<
template
>
<div
class=
"app-container"
>
<el-table
v-loading=
"loading"
:data=
"resourcesList"
:max-height=
"620"
>
<el-table-column
label=
"订单编号"
align=
"center"
prop=
"tradeOrderNo"
/>
<el-table-column
label=
"商品类别"
align=
"center"
prop=
"categoryName"
/>
<el-table-column
v-for=
"(item, index) in resourcesList[0]?.properties.length!==0?resourcesList[0]?.properties.slice(0,4):resourcesList[0]?.properties"
:key=
"index"
:label=
"item.propertyName"
>
<template
#
default=
"
{ row }">
{{
row
.
properties
[
index
].
valueName
}}
</
template
>
</el-table-column>
<el-table-column
label=
"申请时间"
align=
"center"
prop=
"createTime"
width=
"180"
>
<
template
#
default=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
createTime
,
'
{
y
}
-
{
m
}
-
{
d
}'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"有效期限"
align
=
"center"
prop
=
"expTime"
width
=
"180"
>
<
template
#
default
=
"scope"
>
<
span
>
{{
parseTime
(
scope
.
row
.
expTime
,
'
{
y
}
-
{
m
}
-
{
d
}'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
class
-
name
=
"small-padding fixed-width"
>
<
template
#
default
=
"scope"
>
<
el
-
button
link
type
=
"primary"
@
click
=
"handleUpdate(scope.row,scope.$index)"
>
详情
<
/el-button
>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
pagination
v
-
show
=
"total>0"
:
total
=
"total"
v
-
model
:
page
=
"queryParams.pageNum"
v
-
model
:
limit
=
"queryParams.pageSize"
@
pagination
=
"getList"
/>
<!--
添加或修改订单管理
-
用户资源管理对话框
-->
<
el
-
dialog
:
title
=
"title"
v
-
model
=
"open"
width
=
"800px"
append
-
to
-
body
>
<
div
>
<
div
class
=
"info-block"
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
订单编号
<
/div
>
<
div
class
=
"value"
>
{{
form
.
tradeOrderNo
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
商品类别
<
/div
>
<
div
class
=
"value"
>
{{
form
.
categoryName
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"info-block"
>
<
div
class
=
"info-item flex-align-center flex-space-between"
v
-
for
=
"(i,index) in form.properties"
:
key
=
"i.index"
>
<
div
class
=
"label"
>
{{
i
.
propertyName
}}
<
/div
>
<
div
class
=
"value"
>
{{
i
.
valueName
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
申请时间
<
/div
>
<
div
class
=
"value"
>
{{
parseTime
(
form
.
createTime
,
'
{
y
}
-
{
m
}
-
{
d
}'
)
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
有效期限
<
/div
>
<
div
class
=
"value"
>
{{
parseTime
(
form
.
expTime
,
'
{
y
}
-
{
m
}
-
{
d
}'
)
}}
<
/div
>
<
/div
>
<
div
class
=
"info-item flex-align-center flex-space-between"
>
<
div
class
=
"label"
>
鉴权信息
<
/div
>
<
div
class
=
"value"
>
{{
form
.
auth
}}
<
/div
>
<
/div
>
<
/div
>
<
template
#
footer
>
<
div
class
=
"dialog-footer"
>
<
el
-
button
@
click
=
"cancel"
>
关闭
<
/el-button
>
<
/div
>
<
/template
>
<
/el-dialog
>
<
/div
>
<
/template
>
<
script
setup
name
=
"NaturalResources"
>
import
{
listResources
,
getResources
}
from
'@/api/computility/resources'
import
{
parseTime
}
from
"../../utils/ruoyi.js"
;
const
resourcesList
=
ref
([])
const
open
=
ref
(
false
)
const
loading
=
ref
(
true
)
const
ids
=
ref
([])
const
total
=
ref
(
0
)
const
title
=
ref
(
''
)
const
data
=
reactive
({
form
:
{
}
,
queryParams
:
{
pageNum
:
1
,
pageSize
:
10
,
}
}
)
const
{
queryParams
,
form
}
=
toRefs
(
data
)
/** 查询订单管理-用户资源管理列表 */
function
getList
()
{
loading
.
value
=
true
listResources
(
queryParams
.
value
).
then
(
response
=>
{
resourcesList
.
value
=
response
.
data
.
list
total
.
value
=
response
.
data
.
total
loading
.
value
=
false
}
)
}
// 取消按钮
function
cancel
()
{
open
.
value
=
false
}
/** 修改按钮操作 */
function
handleUpdate
(
row
)
{
const
_id
=
row
.
id
||
ids
.
value
getResources
({
id
:
_id
}
).
then
(
response
=>
{
form
.
value
=
response
.
data
open
.
value
=
true
title
.
value
=
'查看详情'
}
)
}
getList
()
<
/script
>
<
style
lang
=
"scss"
scoped
>
.
el
-
form
{
padding
:
20
px
20
px
0
20
px
;
border
-
radius
:
4
px
;
background
-
color
:
#
FFFFFF
;
margin
-
bottom
:
20
px
;
}
.
pagination
-
container
{
background
-
color
:
transparent
;
}
.
el
-
select
{
width
:
100
%
!
important
;
}
.
info
-
block
{
background
-
color
:
#
ffffff
;
padding
:
4
px
0
;
//margin-bottom: 14px;
}
.
info
-
item
{
padding
:
12
px
20
px
;
.
label
{
font
-
weight
:
400
;
font
-
size
:
16
px
;
color
:
#
626566
;
}
.
value
{
font
-
weight
:
bold
;
font
-
size
:
16
px
;
color
:
#
303233
;
}
}
<
/style
>
src/views/marketplace/AIMarketplace.vue
View file @
381016e6
...
...
@@ -3,18 +3,18 @@
<!-- 头部搜索区域 -->
<div
class=
"search-section"
>
<div
class=
"custom-main-w"
>
<h1
class=
"page-title"
>
API应用市场
</h1>
<h2
class=
"page-subtitle"
>
一站式API管理、配置、调用、维护
</h2>
<h1
class=
"page-title"
>
一站链接全球API资源
</h1>
<h2
class=
"page-subtitle"
>
找API、找服务商、找资料
</h2>
<div
class=
"search-box"
>
<el-input
v-model=
"searchQuery"
placeholder=
"可输入
关键词搜索
"
placeholder=
"可输入
API名称/分类名称
"
@
keyup
.
enter=
"handleSearch"
clearable
>
<template
#
append
>
<el-button
type=
"primary"
@
click=
"handleSearch"
>
<el-icon
style=
"margin-right:
10
px"
>
<el-icon
style=
"margin-right:
8
px"
>
<Search
/>
</el-icon>
立即搜索
...
...
@@ -24,6 +24,7 @@
</div>
</div>
</div>
<!-- API分类标签 -->
<div
class=
"category-tabs-wrapper"
>
<div
class=
"custom-main-w"
>
...
...
@@ -40,7 +41,6 @@
:name=
"String(category.id)"
/>
</el-tabs>
</div>
</div>
...
...
@@ -50,8 +50,15 @@
<el-skeleton
:rows=
"3"
animated
/>
</div>
<el-row
:gutter=
"50"
v-else-if=
"apiList.length > 0"
>
<el-col
:span=
"8"
v-for=
"api in apiList"
:key=
"api.id"
>
<el-row
:gutter=
"30"
v-else-if=
"apiList.length > 0"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"8"
:lg=
"6"
v-for=
"api in apiList"
:key=
"api.id"
>
<APICard
:id=
"api.id"
:coverImage=
"api.coverImage"
...
...
@@ -73,7 +80,7 @@
<el-pagination
v-model=
"currentPage"
:page-size=
"pageSize"
:page-sizes=
"[
9, 18, 27, 36
]"
:page-sizes=
"[
10, 20, 50, 100
]"
:total=
"total"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"handleSizeChange"
...
...
@@ -82,7 +89,6 @@
</div>
</div>
</template>
<
script
>
import
{
ElMessage
}
from
'element-plus'
;
import
{
Search
}
from
'@element-plus/icons-vue'
;
...
...
@@ -189,42 +195,90 @@ export default {
</
script
>
<
style
scoped
lang=
"scss"
>
/* 搜索区域 */
.search-section
{
text-align
:
center
;
padding
:
170px
0
150px
;
background
:
linear-gradient
(
180deg
,
rgba
(
225
,
237
,
255
,
1
)
0%
,
rgba
(
255
,
255
,
255
,
0
)
100%
);
padding
:
120px
0
100px
;
background
:
linear-gradient
(
180deg
,
#e1edff
0%
,
rgba
(
255
,
255
,
255
,
0
)
100%
);
}
.page-title
{
font-size
:
40px
;
margin-bottom
:
16px
;
font-size
:
36px
;
margin-bottom
:
12px
;
font-weight
:
bold
;
color
:
#333
;
}
.page-subtitle
{
font-size
:
2
6
px
;
color
:
#6
c6c6c
;
margin-bottom
:
2
4
px
;
font-size
:
2
0
px
;
color
:
#6
66
;
margin-bottom
:
2
0
px
;
}
.search-box
{
max-width
:
8
00px
;
margin
:
3
0px
auto
0
;
max-width
:
7
00px
;
margin
:
2
0px
auto
0
;
:deep(.el-input__wrapper)
{
padding
:
15px
11px
;
padding
:
14px
14px
;
border-radius
:
50px
0
0
50px
;
box-shadow
:
0
4px
10px
rgba
(
0
,
0
,
0
,
0.1
);
}
:deep
(
.el-input-group__append
)
{
color
:
#fff
;
border-radius
:
0
50px
50px
0
;
background-color
:
var
(
--el-color-primary
)
!important
;
color
:
#fff
;
font-weight
:
bold
;
padding
:
0
24px
;
}
}
/* 分类 Tabs */
.category-tabs-wrapper
{
margin-bottom
:
50px
;
padding
:
20px
0
;
background-color
:
#fff
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0.05
);
}
:deep
(
.el-tabs__header
)
{
margin
:
0
;
}
:deep
(
.el-tabs__nav-wrap
)
{
max-width
:
1440px
;
min-width
:
1200px
;
margin
:
0
auto
;
}
:deep
(
.el-tabs__nav-wrap
::after
)
{
content
:
none
!important
;
}
:deep
(
.el-tabs__item
)
{
font-size
:
16px
;
padding
:
12px
20px
!important
;
margin-right
:
16px
;
border-radius
:
4px
;
transition
:
all
0.2s
;
}
:deep
(
.el-tabs__item.is-active
)
{
color
:
#fff
;
background-color
:
var
(
--el-color-primary
)
!important
;
font-weight
:
bold
;
box-shadow
:
0
3px
6px
rgba
(
0
,
0
,
0
,
0.1
);
}
:deep
(
.el-tabs__active-bar
)
{
background-color
:
transparent
;
}
/* API 列表 */
.api-list
{
margin-bottom
:
60px
;
background
:
#f9f9fb
;
padding
:
40px
20px
;
border-radius
:
8px
;
margin-bottom
:
50px
;
min-height
:
400px
;
}
...
...
@@ -237,62 +291,11 @@ export default {
text-align
:
center
;
}
/* 分页 */
.pagination-container
{
display
:
flex
;
justify-content
:
center
;
margin-bottom
:
60px
;
padding
:
20px
0
;
}
//
分类标签
//
.category-title
{
//
position
:
absolute
;
//
left
:
-60px
;
//
color
:
#333
;
//
font-size
:
24px
;
//
line-height
:
60px
;
//
top
:
0
;
//
font-weight
:
bold
;
//
}
.category-tabs-wrapper
{
position
:
relative
;
margin-bottom
:
70px
;
padding
:
35px
0
;
background-color
:
#fff
;
.category-tabs
{
//
padding-left
:
100px
;
}
:deep
(
.el-tabs__header
)
{
margin
:
0
;
}
:deep
(
.el-tabs__nav-wrap
)
{
max-width
:
1440px
;
min-width
:
1200px
;
margin
:
0
auto
;
}
:deep
(
.el-tabs__nav-wrap
::after
)
{
content
:
none
!important
;
}
:deep
(
.el-tabs__nav
)
{
width
:
100%
;
}
:deep
(
.el-tabs__item
)
{
color
:
#333
;
font-size
:
20px
;
margin-right
:
20px
;
padding
:
22px
24px
!important
;
font-weight
:
400
;
justify-content
:
flex-start
;
}
:deep
(
.el-tabs__item.is-active
)
{
color
:
#fff
;
font-weight
:
bold
;
position
:
relative
;
border-radius
:
3px
;
background-color
:
var
(
--el-color-primary
)
!important
;
}
:deep
(
.el-tabs__active-bar
)
{
background-color
:
transparent
;
}
margin-top
:
30px
;
margin-bottom
:
50px
;
}
</
style
>
src/views/marketplace/AIMarketplaceDetail.vue
View file @
381016e6
...
...
@@ -5,7 +5,7 @@
<el-breadcrumb
separator=
">"
>
<el-breadcrumb-item
:to=
"
{ path: '/' }">首页
</el-breadcrumb-item>
<el-breadcrumb-item
:to=
"
{ path: '/marketplace/ai' }"
>A
I应用
市场
</el-breadcrumb-item
>A
PI服务
市场
</el-breadcrumb-item
>
<el-breadcrumb-item
v-if=
"categoryName"
>
{{
categoryName
...
...
@@ -160,11 +160,11 @@
</div>
<el-divider
style=
"margin: 0 !important;"
/>
<div
class=
"drawer-footer flex-space-between flex-align-center"
>
<div>
应付
费用
</div>
<div>
费用
</div>
<div
class=
"flex-align-center"
>
<div
class=
"mr20"
>
<div
class=
"price"
>
¥{{ currentPrice
}}
</div>
<div
class=
"price"
>
¥{{ currentPrice}}
</div>
</div>
<el-button
type=
"primary"
@
click=
"create"
:disabled=
"!checkbox"
>
立即购买
...
...
@@ -173,35 +173,36 @@
</div>
</template>
</el-drawer>
<!-- 右侧内容区 -->
<!-- <div class="right-section">-->
<!-- <!– 商家信息 –>-->
<!-- <div class="merchant-info">-->
<!-- <div class="preview-image">-->
<!-- <el-image src="/src/assets/logo/nscc-logo-copy.png" fit="cover" />-->
<!-- </div>-->
<!-- <ul class="info-list">-->
<!-- <li>-->
<!-- <span class="label">商家:</span>-->
<!-- <span>自营</span>-->
<!--<!– <span>{{ merchantInfo.merchant }}</span>–>-->
<!-- </li>-->
<!-- <li>-->
<!-- <span class="label">电话:</span>-->
<!-- <span>13348681789</span>-->
<!--<!– <span>{{ merchantInfo.phone }}</span>–>-->
<!-- </li>-->
<!-- <li>-->
<!-- <span class="label">邮箱:</span>-->
<!--<!– <span>{{ merchantInfo.email }}</span>–>-->
<!-- </li>-->
<!-- </ul>-->
<!-- </div>-->
<!-- <!– 相关API推荐 –>-->
<!-- <RelatedApis :apis="relatedApis" />-->
<!-- </div>-->
<el-dialog
:title=
"qrCode.title"
v-model=
"qrCode.visible"
width=
"385px"
append-to-body
:align-center=
"true"
:close-on-click-modal=
"false"
@
closed=
"clearQueryInterval"
>
<img
:src=
"qrCode.url"
alt=
""
/>
</el-dialog>
<el-dialog
title=
"购买协议"
v-model=
"protocol"
width=
"800px"
append-to-body
:align-center=
"true"
:close-on-click-modal=
"false"
@
closed=
"clearProtocol"
>
<div
class=
"pdf-box"
>
<!-- <div id="pdf-container" style="width: 100%; height: 100%;"></div>-->
<iframe
v-if=
"pdfUrl"
:src=
"pdfUrl"
style=
"width:100%; height:80vh;"
></iframe>
</div>
</el-dialog>
</div>
</div>
</template>
...
...
@@ -213,11 +214,12 @@ import {
//getMerchantInfo,
getAppRecommendList
,
//getAppCategoryList,
getAppInfoDetail
,
createApiOrderSubmit
,
getAppInfoDetail
,
createApiOrderSubmit
,
createPay
}
from
"../../api/marketplace"
;
import
RelatedApis
from
"./components/RelatedApis.vue"
;
import
{
createOrderSubmit
,
createPay
}
from
"@/api/computingResource.js"
;
import
{
ElMessageBox
}
from
"element-plus"
;
import
{
ElMessage
,
ElMessageBox
}
from
"element-plus"
;
import
QRCode
from
"qrcode"
;
import
{
PayOrderStatusEnum
}
from
"@/utils/constants.js"
;
import
request
from
"@/utils/request.js"
;
const
router
=
useRouter
();
const
route
=
useRoute
();
...
...
@@ -234,6 +236,9 @@ const form = ref({
num
:
1
})
const
checkbox
=
ref
(
false
)
const
protocol
=
ref
(
false
)
const
interval
=
ref
(
undefined
)
// 分类
...
...
@@ -254,6 +259,16 @@ const selectSpec = (idx) => {
selectedSpec
.
value
=
idx
;
};
const
pdfUrl_unuse
=
ref
(
'https://luhu-ltx.oss-cn-shenzhen.aliyuncs.com/20250828/文字文稿1_1756349853834.pdf'
)
const
pdfUrl
=
ref
(
'http://localhost:48080/admin-api/infra/file/preview'
)
const
qrCode
=
ref
({
url
:
''
,
title
:
'请使用微信”扫一扫“扫码支付'
,
visible
:
false
})
// 详情数据
const
productData
=
ref
({
createTime
:
""
,
...
...
@@ -391,6 +406,12 @@ const currentHtml = computed(() => {
return
""
;
});
async
function
handleCheckProtocol
()
{
console
.
log
(
'点击'
)
protocol
.
value
=
true
}
// 去订单确认页// 详情页 goOrderConfirm
const
goOrderConfirm
=
()
=>
{
showDrawer
.
value
=
true
...
...
@@ -459,6 +480,82 @@ function create() {
function
getCode
(
value
,
payOrderId
)
{
QRCode
.
toDataURL
(
value
,
{
errorCorrectionLevel
:
'L'
,
margin
:
2
,
width
:
350
},
(
err
,
url
)
=>
{
if
(
err
)
throw
err
qrCode
.
value
=
{
url
:
url
,
title
:
'请使用微信“扫一扫”扫码支付'
,
visible
:
true
}
}
)
createQueryInterval
(
payOrderId
)
}
/** 轮询查询任务 */
const
createQueryInterval
=
(
id
)
=>
{
if
(
interval
.
value
)
{
return
}
interval
.
value
=
setInterval
(
async
()
=>
{
const
res
=
await
getOrder
(
id
)
console
.
log
(
res
,
'res'
)
// 已支付
if
(
res
.
data
.
status
===
PayOrderStatusEnum
.
SUCCESS
.
status
)
{
clearQueryInterval
()
// ElMessage.success('支付成功!')
ElMessageBox
.
confirm
(
'支付成功'
,
'请前往控制台-我的订单查看'
,
{
confirmButtonText
:
'确认'
,
showCancelButton
:
false
,
type
:
'success'
}
).
then
(()
=>
{
})
}
// 已取消
if
(
res
.
data
.
status
===
PayOrderStatusEnum
.
CLOSED
.
status
)
{
clearQueryInterval
()
ElMessage
.
error
(
'支付已关闭!'
)
}
},
1000
*
2
)
}
// 查询详情支付订单
const
getOrder
=
async
(
id
,
sync
)
=>
{
return
await
request
({
url
:
'/pay/order/get'
,
method
:
'get'
,
params
:
{
id
,
sync
}
})
}
/** 清空查询任务 */
const
clearQueryInterval
=
()
=>
{
// 清空各种弹窗
qrCode
.
value
=
{
title
:
''
,
url
:
'请使用微信“扫一扫”扫码支付'
,
visible
:
false
}
showDrawer
.
value
=
false
// 清空任务
clearInterval
(
interval
.
value
)
interval
.
value
=
undefined
}
const
clearProtocol
=
()
=>
{
protocol
.
value
=
true
}
// 暴露 goOrderConfirm 到模板
defineExpose
({
goOrderConfirm
});
</
script
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment