mirror of
https://gitee.com/blackfox/geekai.git
synced 2024-12-02 12:17:42 +08:00
opt: adjust ItemList component styles
This commit is contained in:
parent
7d1d88a32f
commit
a688d3feb5
@ -145,7 +145,10 @@ func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc {
|
||||
c.Request.URL.Path == "/api/mj/notify" ||
|
||||
c.Request.URL.Path == "/api/chat/history" ||
|
||||
c.Request.URL.Path == "/api/chat/detail" ||
|
||||
c.Request.URL.Path == "/api/role/list" ||
|
||||
c.Request.URL.Path == "/api/mj/jobs" ||
|
||||
c.Request.URL.Path == "/api/mj/proxy" ||
|
||||
c.Request.URL.Path == "/api/sd/jobs" ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/captcha/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/static/") ||
|
||||
|
@ -48,13 +48,15 @@ func (h *ChatRoleHandler) List(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := utils.GetLoginUser(c, h.db)
|
||||
if err != nil {
|
||||
userId := h.GetInt(c, "user_id", 0)
|
||||
if userId == 0 {
|
||||
resp.NotAuth(c)
|
||||
return
|
||||
}
|
||||
var user model.User
|
||||
h.db.First(&user, userId)
|
||||
var roleKeys []string
|
||||
err = utils.JsonDecode(user.ChatRoles, &roleKeys)
|
||||
err := utils.JsonDecode(user.ChatRoles, &roleKeys)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "角色解析失败!")
|
||||
return
|
||||
|
@ -14,12 +14,59 @@
|
||||
.inner {
|
||||
display flex
|
||||
color #ffffff
|
||||
padding 20px;
|
||||
|
||||
.left-menu {
|
||||
width 160px
|
||||
}
|
||||
padding 15px;
|
||||
overflow-y visible
|
||||
overflow-x hidden
|
||||
|
||||
.list-box {
|
||||
.app-item {
|
||||
border 1px solid #666666
|
||||
border-radius 6px
|
||||
overflow hidden
|
||||
transition: all 0.3s ease; /* 添加过渡效果 */
|
||||
|
||||
.el-image {
|
||||
padding 6px
|
||||
|
||||
.el-image__inner {
|
||||
border-radius 10px
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display flex
|
||||
padding 10px
|
||||
|
||||
.name {
|
||||
width 100%
|
||||
text-align left
|
||||
font-size 16px
|
||||
font-weight bold
|
||||
color #47fff1
|
||||
}
|
||||
|
||||
.opt {
|
||||
position: relative;
|
||||
top -5px
|
||||
}
|
||||
}
|
||||
|
||||
.hello-msg {
|
||||
overflow: hidden;
|
||||
white-space normal
|
||||
text-overflow: ellipsis;
|
||||
height 60px
|
||||
padding 10px
|
||||
font-size 14px
|
||||
color #999999
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
|
||||
transform: translateY(-10px); /* 向上移动10像素 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,19 @@
|
||||
color: #fff;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.task-list-box .running-job-list .job-item {
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.task-list-box .running-job-list .job-item .job-item-inner {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.task-list-box .running-job-list .job-item .job-item-inner .progress {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
@ -24,24 +27,30 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.task-list-box .running-job-list .job-item .job-item-inner .progress span {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line {
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li a {
|
||||
padding: 3px 0;
|
||||
width: 44px;
|
||||
@ -52,25 +61,31 @@
|
||||
background-color: #4e5058;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li a:hover {
|
||||
background-color: #6d6f78;
|
||||
}
|
||||
|
||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul .show-prompt {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.task-list-box .el-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 240px;
|
||||
}
|
||||
|
||||
.task-list-box .el-image img {
|
||||
height: 240px;
|
||||
}
|
||||
|
||||
.task-list-box .el-image .el-image-viewer__wrapper img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.task-list-box .el-image .image-slot {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
@ -80,16 +95,20 @@
|
||||
min-height: 200px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.task-list-box .el-image .image-slot .iconfont {
|
||||
font-size: 50px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.task-list-box .el-image.upscale {
|
||||
max-height: 304px;
|
||||
max-height: 312px;
|
||||
}
|
||||
|
||||
.task-list-box .el-image.upscale img {
|
||||
height: 304px;
|
||||
height: 312px;
|
||||
}
|
||||
|
||||
.task-list-box .el-image.upscale .el-image-viewer__wrapper img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
@ -40,6 +40,10 @@
|
||||
.job-item {
|
||||
width 100%
|
||||
height 100%
|
||||
border 1px solid #666666
|
||||
padding 6px
|
||||
overflow hidden
|
||||
border-radius 6px
|
||||
|
||||
.opt {
|
||||
.opt-line {
|
||||
@ -54,7 +58,7 @@
|
||||
|
||||
a {
|
||||
padding 3px 0
|
||||
width 44px
|
||||
width 40px
|
||||
text-align center
|
||||
border-radius 5px
|
||||
display block
|
||||
@ -113,10 +117,10 @@
|
||||
}
|
||||
|
||||
.el-image.upscale {
|
||||
max-height 304px
|
||||
max-height 310px
|
||||
|
||||
img {
|
||||
height 304px
|
||||
height 310px
|
||||
}
|
||||
|
||||
.el-image-viewer__wrapper {
|
||||
|
@ -5,11 +5,11 @@
|
||||
class="list-item"
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
:style="{width:itemWidth + 'px', marginBottom: margin*2+'px'}"
|
||||
:style="{width:itemWidth + 'px'}"
|
||||
>
|
||||
<div :style="{marginLeft: margin+'px', marginRight: margin+'px'}">
|
||||
<div class="item-inner" :style="{padding: gap/2+'px'}">
|
||||
<div class="item-wrapper">
|
||||
<slot :item="item" :index="index"></slot>
|
||||
<slot :item="item" :index="index" :width="itemWidth"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -21,6 +21,7 @@
|
||||
// 列表组件
|
||||
import {onMounted, ref} from "vue";
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const props = defineProps({
|
||||
items: {
|
||||
type: Array,
|
||||
@ -28,38 +29,25 @@ const props = defineProps({
|
||||
},
|
||||
gap: {
|
||||
type: Number,
|
||||
default: 10
|
||||
default: 12
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 240
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 240
|
||||
}
|
||||
});
|
||||
|
||||
const container = ref(null)
|
||||
const itemWidth = ref(props.width)
|
||||
const margin = ref(props.gap)
|
||||
|
||||
onMounted(() => {
|
||||
computeSize()
|
||||
})
|
||||
|
||||
const computeSize = () => {
|
||||
const w = container.value.offsetWidth - 10 // 减去滚动条的宽度
|
||||
const w = container.value.offsetWidth - 8 // 减去滚动条的宽度
|
||||
let cols = Math.floor(w / props.width)
|
||||
itemWidth.value = Math.floor(w / cols) - 1
|
||||
while (itemWidth.value < props.width && cols > 1) {
|
||||
cols -= 1
|
||||
itemWidth.value = Math.floor(w / cols) - 1
|
||||
}
|
||||
|
||||
if (props.gap > 0) {
|
||||
margin.value = props.gap / 2
|
||||
}
|
||||
itemWidth.value = Math.floor(w / cols)
|
||||
}
|
||||
|
||||
window.onresize = () => {
|
||||
@ -76,15 +64,14 @@ window.onresize = () => {
|
||||
flex-wrap wrap
|
||||
|
||||
.list-item {
|
||||
|
||||
div {
|
||||
.item-inner {
|
||||
display flex
|
||||
height 100%
|
||||
overflow hidden
|
||||
|
||||
.item-wrapper {
|
||||
height 100%
|
||||
width 100%
|
||||
display flex
|
||||
justify-content center
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,30 @@
|
||||
<template>
|
||||
<div class="page-apps">
|
||||
<div class="page-apps custom-scroll">
|
||||
<div class="title">
|
||||
AI 助手应用中心
|
||||
</div>
|
||||
<div class="inner custom-scroll">
|
||||
<div class="app-list">
|
||||
<div class="list-item" v-for="item in list" :key="item.id">
|
||||
<div v-if="item.key !=='gpt'">
|
||||
<el-image :src="item.icon"/>
|
||||
<div class="inner" :style="{height: listBoxHeight + 'px'}">
|
||||
<ItemList :items="list" v-if="list.length > 0" gap="20" width="250">
|
||||
<template #default="scope">
|
||||
<div class="app-item" :style="{width: scope.width+'px'}">
|
||||
<el-image :src="scope.item.icon" fit="cover" :style="{height: scope.width+'px'}"/>
|
||||
<div class="title">
|
||||
<span class="name">{{ scope.item.name }}</span>
|
||||
<div class="opt">
|
||||
<el-button size="small"
|
||||
style="--el-color-primary:#009999"
|
||||
@click="addRole(scope.item)">
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
<span>添加应用</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hello-msg">{{ scope.item['hello_msg'] }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</ItemList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -19,18 +33,31 @@
|
||||
import {onMounted, ref} from "vue"
|
||||
import {ElMessage} from "element-plus";
|
||||
import {httpGet} from "@/utils/http";
|
||||
import ItemList from "@/components/ItemList.vue";
|
||||
import {Plus} from "@element-plus/icons-vue";
|
||||
|
||||
const listBoxHeight = window.innerHeight - 97
|
||||
const list = ref([])
|
||||
onMounted(() => {
|
||||
httpGet("/api/role/list?all=true").then((res) => {
|
||||
list.value = res.data
|
||||
const data = res.data
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].key === 'gpt') {
|
||||
continue
|
||||
}
|
||||
list.value.push(data[i])
|
||||
}
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取应用失败:" + e.message)
|
||||
})
|
||||
})
|
||||
|
||||
const addRole = (row) => {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
<style lang="stylus">
|
||||
@import "@/assets/css/chat-app.styl"
|
||||
@import "@/assets/css/custom-scroll.styl"
|
||||
</style>
|
||||
|
@ -553,7 +553,7 @@ const connect = function (chat_id, role_id) {
|
||||
content: _role['hello_msg'],
|
||||
orgContent: _role['hello_msg'],
|
||||
})
|
||||
ElMessage.success({message: "对话连接成功!", duration: 500})
|
||||
ElMessage.success({message: "对话连接成功!", duration: 1000})
|
||||
} else { // 加载聊天记录
|
||||
loadChatHistory(chat_id);
|
||||
}
|
||||
|
@ -286,7 +286,7 @@
|
||||
|
||||
<h2>创作记录</h2>
|
||||
<div class="finish-job-list">
|
||||
<ItemList :items="finishedJobs" v-if="finishedJobs.length > 0">
|
||||
<ItemList :items="finishedJobs" v-if="finishedJobs.length > 0" width="240">
|
||||
<template #default="scope">
|
||||
<div class="job-item">
|
||||
<el-image
|
||||
@ -503,7 +503,7 @@ onMounted(() => {
|
||||
|
||||
const clipboard = new Clipboard('.copy-prompt');
|
||||
clipboard.on('success', () => {
|
||||
ElMessage.success({message: "复制成功!", duration: 500});
|
||||
ElMessage.success("复制成功!");
|
||||
})
|
||||
|
||||
clipboard.on('error', () => {
|
||||
|
@ -289,7 +289,7 @@
|
||||
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
|
||||
<h2>任务列表</h2>
|
||||
<div class="running-job-list">
|
||||
<ItemList :items="runningJobs" v-if="runningJobs.length > 0">
|
||||
<ItemList :items="runningJobs" v-if="runningJobs.length > 0" width="240">
|
||||
<template #default="scope">
|
||||
<div class="job-item">
|
||||
<el-popover
|
||||
@ -645,7 +645,7 @@ onMounted(() => {
|
||||
|
||||
const clipboard = new Clipboard('.copy-prompt');
|
||||
clipboard.on('success', () => {
|
||||
ElMessage.success({message: "复制成功!", duration: 500});
|
||||
ElMessage.success("复制成功!");
|
||||
})
|
||||
|
||||
clipboard.on('error', () => {
|
||||
|
@ -281,7 +281,7 @@ getNext()
|
||||
onMounted(() => {
|
||||
const clipboard = new Clipboard('.copy-prompt');
|
||||
clipboard.on('success', () => {
|
||||
ElMessage.success({message: "复制成功!", duration: 500});
|
||||
ElMessage.success("复制成功!");
|
||||
})
|
||||
|
||||
clipboard.on('error', () => {
|
||||
@ -293,6 +293,7 @@ const changeImgType = () => {
|
||||
document.getElementById('waterfall-box').scrollTo(0, 0)
|
||||
page.value = 0
|
||||
list.value = []
|
||||
loading.value = true
|
||||
isOver.value = false
|
||||
nextTick(() => getNext())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user