更新
This commit is contained in:
parent
c513814c0a
commit
64af489397
@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useLoginStore } from './store/LoginStore';
|
||||
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
const loginStore = useLoginStore();
|
||||
|
||||
onMounted(() => {
|
||||
@ -11,10 +12,12 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<div>
|
||||
<router-view>
|
||||
</router-view>
|
||||
</div>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import {get, post} from '../utlis/request'
|
||||
import { get, post } from '../utlis/request'
|
||||
|
||||
// 获取视频列表
|
||||
export const getVideos = <T,D>(data:D):Promise<T> =>get('http://180.76.111.84:9028/v1/feed/list',data)
|
||||
export const getVideos = <T, D>(data: D): Promise<T> => get('https://vidu.opencomputing.cn/v1/feed/list', data)
|
||||
|
||||
// 充值
|
||||
export const recharge = <T,D>(data:D):Promise<T> =>post('/api/unipay/user_recharge.dspy',data)
|
||||
export const recharge = <T, D>(data: D): Promise<T> => post('/api/unipay/user_recharge.dspy', data)
|
||||
|
||||
// 开户
|
||||
export const openAccount = <T>():Promise<T> =>post('/api/accounting/open_customer_accounts.dspy')
|
||||
export const openAccount = <T>(): Promise<T> => post('/api/accounting/open_customer_accounts.dspy')
|
||||
|
||||
// 余额
|
||||
export const balance = <T>():Promise<T> =>get('/api/accounting/mybalance.dspy')
|
||||
export const balance = <T>(): Promise<T> => get('/api/accounting/mybalance.dspy')
|
||||
|
||||
// 充值记录
|
||||
export const consumptionRecord = <T,D>(data:D):Promise<T> => get('/api/platformbiz/query_orders.dspy',data)
|
||||
@ -54,6 +54,12 @@
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">消费记录</div>
|
||||
<div class="code-name">&#xe654;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">余额</div>
|
||||
@ -174,9 +180,9 @@
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1774432601927') format('woff2'),
|
||||
url('iconfont.woff?t=1774432601927') format('woff'),
|
||||
url('iconfont.ttf?t=1774432601927') format('truetype');
|
||||
src: url('iconfont.woff2?t=1775638325739') format('woff2'),
|
||||
url('iconfont.woff?t=1775638325739') format('woff'),
|
||||
url('iconfont.ttf?t=1775638325739') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
@ -202,6 +208,15 @@
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiaofeijilu"></span>
|
||||
<div class="name">
|
||||
消费记录
|
||||
</div>
|
||||
<div class="code-name">.icon-xiaofeijilu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-yue"></span>
|
||||
<div class="name">
|
||||
@ -382,6 +397,14 @@
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiaofeijilu"></use>
|
||||
</svg>
|
||||
<div class="name">消费记录</div>
|
||||
<div class="code-name">#icon-xiaofeijilu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-yue"></use>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 5136943 */
|
||||
src: url('iconfont.woff2?t=1774432601927') format('woff2'),
|
||||
url('iconfont.woff?t=1774432601927') format('woff'),
|
||||
url('iconfont.ttf?t=1774432601927') format('truetype');
|
||||
src: url('iconfont.woff2?t=1775638325739') format('woff2'),
|
||||
url('iconfont.woff?t=1775638325739') format('woff'),
|
||||
url('iconfont.ttf?t=1775638325739') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-xiaofeijilu:before {
|
||||
content: "\e654";
|
||||
}
|
||||
|
||||
.icon-yue:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -5,6 +5,13 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "1020316",
|
||||
"name": "消费记录",
|
||||
"font_class": "xiaofeijilu",
|
||||
"unicode": "e654",
|
||||
"unicode_decimal": 58964
|
||||
},
|
||||
{
|
||||
"icon_id": "2681721",
|
||||
"name": "余额",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -18,7 +18,13 @@
|
||||
<span class="menu-text">首页</span>
|
||||
</div>
|
||||
</el-menu-item>
|
||||
|
||||
<el-menu-item index="bill">
|
||||
<div class="menu-item-content">
|
||||
<i class="iconfont icon-xiaofeijilu"></i>
|
||||
<span class="menu-text">消费记录</span>
|
||||
</div>
|
||||
</el-menu-item>
|
||||
|
||||
</el-menu>
|
||||
</div>
|
||||
|
||||
@ -90,12 +96,15 @@ const activeIndex = ref('index')
|
||||
// 菜单项点击事件
|
||||
const handleSelect = (index: string) => {
|
||||
activeIndex.value = index
|
||||
|
||||
|
||||
// 处理路由跳转
|
||||
switch (index) {
|
||||
case 'index':
|
||||
router.push('/index');
|
||||
break;
|
||||
case 'bill':
|
||||
router.push('/bill');
|
||||
break;
|
||||
case 'discover':
|
||||
router.push('/discover');
|
||||
break;
|
||||
@ -127,6 +136,8 @@ const updateActiveIndex = () => {
|
||||
const path = route.path
|
||||
if (path.includes('/index')) {
|
||||
activeIndex.value = 'index';
|
||||
} else if (path.includes('/bill')) {
|
||||
activeIndex.value = 'bill';
|
||||
} else if (path.includes('/discover')) {
|
||||
activeIndex.value = 'discover';
|
||||
} else if (path.includes('/profile')) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -7,20 +7,37 @@
|
||||
<div class="upload-section">
|
||||
<!-- 上传视频 -->
|
||||
<div class="upload-item">
|
||||
<div class="upload-icon">
|
||||
<svg width="1em" height="1em" fill="none" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.28 5.96875L12.2617 19.9688" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"></path>
|
||||
<path d="M5.25 12.9688H19.25" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"></path>
|
||||
</svg>
|
||||
<!-- 已上传时显示预览 -->
|
||||
<div v-if="videoBase64" class="uploaded-preview">
|
||||
<img :src="videoBase64" alt="视频预览" class="uploaded-image" />
|
||||
<div class="uploaded-actions">
|
||||
<span class="uploaded-action" @click="handlePreview('video')">
|
||||
<el-icon><ZoomIn /></el-icon>
|
||||
</span>
|
||||
<span class="uploaded-action" @click="handleRemoveVideo">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
<span class="upload-title">上传视频 / 主体</span>
|
||||
<span class="upload-desc">最多可上传1个5-8s或2个5s内视频 / 主体</span>
|
||||
<!-- 未上传时显示上传框 -->
|
||||
<div v-else class="upload-placeholder">
|
||||
<div class="upload-icon">
|
||||
<svg width="1em" height="1em" fill="none" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.28 5.96875L12.2617 19.9688" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"></path>
|
||||
<path d="M5.25 12.9688H19.25" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
<span class="upload-title">上传视频 / 主体</span>
|
||||
<span class="upload-desc">最多可上传1个视频</span>
|
||||
</div>
|
||||
<el-upload action="#" :auto-upload="false" :show-file-list="false" accept="video/*"
|
||||
:on-change="handleVideoChange" class="upload-button">
|
||||
<el-button type="primary" size="small">选择文件</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<img src="https://image01.vidu.zone/vidu/media-asset/video-a09ab611.webp" alt="视频示例"
|
||||
class="upload-preview" />
|
||||
</div>
|
||||
|
||||
<!-- 分割线 -->
|
||||
@ -28,19 +45,37 @@
|
||||
|
||||
<!-- 上传图片 -->
|
||||
<div class="upload-item">
|
||||
<div class="upload-icon">
|
||||
<svg width="1em" height="1em" fill="none" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.28 5.96875L12.2617 19.9688" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"></path>
|
||||
<path d="M5.25 12.9688H19.25" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"></path>
|
||||
</svg>
|
||||
<!-- 已上传时显示预览 -->
|
||||
<div v-if="imageBase64" class="uploaded-preview">
|
||||
<img :src="imageBase64" alt="图片预览" class="uploaded-image" />
|
||||
<div class="uploaded-actions">
|
||||
<span class="uploaded-action" @click="handlePreview('image')">
|
||||
<el-icon><ZoomIn /></el-icon>
|
||||
</span>
|
||||
<span class="uploaded-action" @click="handleRemoveImage">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
<span class="upload-title">上传图片 / 主体</span>
|
||||
<span class="upload-desc">最多可上传1-4张图片</span>
|
||||
<!-- 未上传时显示上传框 -->
|
||||
<div v-else class="upload-placeholder">
|
||||
<div class="upload-icon">
|
||||
<svg width="1em" height="1em" fill="none" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.28 5.96875L12.2617 19.9688" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"></path>
|
||||
<path d="M5.25 12.9688H19.25" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="upload-text">
|
||||
<span class="upload-title">上传图片 / 主体</span>
|
||||
<span class="upload-desc">最多可上传1张图片</span>
|
||||
</div>
|
||||
<el-upload action="#" :auto-upload="false" :show-file-list="false" accept="image/*"
|
||||
:on-change="handleImageChange" class="upload-button">
|
||||
<el-button type="primary" size="small">选择文件</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<img src="https://image01.vidu.zone/vidu/media-asset/img-052445cb.webp" alt="图片示例" class="upload-preview" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -144,13 +179,20 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<!-- 图片预览对话框 -->
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, defineEmits } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Delete, ZoomIn } from '@element-plus/icons-vue'
|
||||
import type { UploadFile } from 'element-plus'
|
||||
|
||||
// 定义 emit 事件
|
||||
const emit = defineEmits(['price-update', 'prompt-change'])
|
||||
const emit = defineEmits(['price-update', 'prompt-change', 'task-created'])
|
||||
|
||||
// 下拉选中项
|
||||
const selectModel = ref('lucy')
|
||||
@ -167,6 +209,14 @@ const durations = [2, 3, 4, 5, 6, 7, 8]
|
||||
// 提示词文本
|
||||
const promptText = ref('')
|
||||
|
||||
// 上传文件的base64
|
||||
const videoBase64 = ref('')
|
||||
const imageBase64 = ref('')
|
||||
|
||||
// 预览对话框
|
||||
const dialogVisible = ref(false)
|
||||
const dialogImageUrl = ref('')
|
||||
|
||||
// 价格计算
|
||||
const price = computed(() => {
|
||||
// 基础价格:5秒及以下每个 1 单位,超过5秒每个 2 单位
|
||||
@ -198,6 +248,125 @@ const handleChange = (value: string) => {
|
||||
const handlePromptInput = (value: string) => {
|
||||
promptText.value = value
|
||||
}
|
||||
|
||||
// 处理视频上传
|
||||
const handleVideoChange = (file: UploadFile) => {
|
||||
if (videoBase64.value) {
|
||||
ElMessage.warning('只能上传一个视频,请先删除已有视频')
|
||||
return
|
||||
}
|
||||
|
||||
const rawFile = file.raw as File
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
const base64 = e.target?.result as string
|
||||
videoBase64.value = base64
|
||||
console.log('视频上传成功,Base64长度:', base64.length)
|
||||
ElMessage.success('视频上传成功')
|
||||
}
|
||||
reader.readAsDataURL(rawFile)
|
||||
}
|
||||
|
||||
// 处理图片上传
|
||||
const handleImageChange = (file: UploadFile) => {
|
||||
if (imageBase64.value) {
|
||||
ElMessage.warning('只能上传一张图片,请先删除已有图片')
|
||||
return
|
||||
}
|
||||
|
||||
const rawFile = file.raw as File
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
const base64 = e.target?.result as string
|
||||
imageBase64.value = base64
|
||||
console.log('图片上传成功,Base64长度:', base64.length)
|
||||
ElMessage.success('图片上传成功')
|
||||
}
|
||||
reader.readAsDataURL(rawFile)
|
||||
}
|
||||
|
||||
// 删除视频
|
||||
const handleRemoveVideo = () => {
|
||||
videoBase64.value = ''
|
||||
ElMessage.info('已删除视频')
|
||||
}
|
||||
|
||||
// 删除图片
|
||||
const handleRemoveImage = () => {
|
||||
imageBase64.value = ''
|
||||
ElMessage.info('已删除图片')
|
||||
}
|
||||
|
||||
// 预览
|
||||
const handlePreview = (type: 'video' | 'image') => {
|
||||
dialogImageUrl.value = type === 'video' ? videoBase64.value : imageBase64.value
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 构建提交参数
|
||||
const buildSubmitParams = () => {
|
||||
const params: Record<string, any> = {
|
||||
llmid: selectModel.value,
|
||||
prompt: promptText.value,
|
||||
duration: selectedDuration.value,
|
||||
voice: selectVoice.value,
|
||||
quality: selectQuality.value,
|
||||
codec: selectCodec.value,
|
||||
ratio: selectRatio.value,
|
||||
count: selectedCount.value,
|
||||
}
|
||||
|
||||
// 添加视频base64
|
||||
if (videoBase64.value) {
|
||||
params.video = videoBase64.value
|
||||
console.log('添加视频参数,Base64长度:', videoBase64.value.length)
|
||||
}
|
||||
|
||||
// 添加图片base64
|
||||
if (imageBase64.value) {
|
||||
params.image = imageBase64.value
|
||||
console.log('添加图片参数,Base64长度:', imageBase64.value.length)
|
||||
}
|
||||
|
||||
console.log('提交参数:', JSON.stringify(params, null, 2))
|
||||
return params
|
||||
}
|
||||
|
||||
// 生成视频
|
||||
const generate = async () => {
|
||||
if (!videoBase64.value && !imageBase64.value) {
|
||||
ElMessage.warning('请至少上传一个视频或图片')
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
const params = buildSubmitParams()
|
||||
// TODO: 调用实际的生成接口
|
||||
console.log('生成参数:', params)
|
||||
ElMessage.success('生成任务已提交')
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('生成失败:', error)
|
||||
ElMessage.error('生成失败,请重试')
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
promptText.value = ''
|
||||
videoBase64.value = ''
|
||||
imageBase64.value = ''
|
||||
selectedDuration.value = 5
|
||||
selectedCount.value = 1
|
||||
emit('prompt-change', true)
|
||||
}
|
||||
|
||||
// 暴露给父组件
|
||||
defineExpose({
|
||||
generate,
|
||||
resetForm,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@ -463,6 +632,82 @@ const handlePromptInput = (value: string) => {
|
||||
background-image: linear-gradient(to bottom, #7280FF, #DADFFF);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// 上传预览相关样式
|
||||
.uploaded-preview {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 185/75;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background-color: #1a1c20;
|
||||
|
||||
.uploaded-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.uploaded-actions {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uploaded-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-placeholder {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 16px 24px;
|
||||
height: 88px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.upload-button {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import ElementPlus from 'element-plus'
|
||||
// element-ui css
|
||||
import 'element-plus/dist/index.css'
|
||||
import 'element-plus/theme-chalk/index.css'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
// pinia持久化
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
// pinia
|
||||
@ -15,11 +16,13 @@ import { createPinia } from 'pinia'
|
||||
// icon
|
||||
import './assets/css/iconfont/iconfont.css'
|
||||
|
||||
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
app.use(ElementPlus)
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
})
|
||||
app.use(pinia)
|
||||
app.mount('#app')
|
||||
app.mount('#app')
|
||||
@ -29,6 +29,12 @@ const router = createRouter({
|
||||
name: 'index',
|
||||
component: () => import('@/views/index/index.vue')
|
||||
},
|
||||
// 消费记录
|
||||
{
|
||||
path: '/bill',
|
||||
name: 'bill',
|
||||
component: () => import('@/views/Bill/Bill.vue')
|
||||
},
|
||||
// ImgGenerate
|
||||
{
|
||||
path: '/ImgGenerate',
|
||||
@ -70,15 +76,15 @@ const router = createRouter({
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// 素材广场
|
||||
{
|
||||
path: '/material-square',
|
||||
name: 'material-square',
|
||||
component: () => import('@/views/videoGenerate/videoGenerate.vue')
|
||||
}
|
||||
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
783
src/views/Bill/Bill.vue
Normal file
783
src/views/Bill/Bill.vue
Normal file
@ -0,0 +1,783 @@
|
||||
<template>
|
||||
<div class="bill-container">
|
||||
<el-card class="bill-card">
|
||||
<!-- 头部筛选区 -->
|
||||
<div class="bill-header">
|
||||
<div class="header-title">
|
||||
<i class="iconfont icon-xiaofeijilu"></i>
|
||||
<span>消费记录</span>
|
||||
</div>
|
||||
<div class="header-filters">
|
||||
<el-select
|
||||
v-model="statusFilter"
|
||||
placeholder="订单状态"
|
||||
size="default"
|
||||
@change="handleFilterChange"
|
||||
popper-class="custom-select-popper"
|
||||
class="status-select"
|
||||
>
|
||||
<el-option label="全部状态" value="" />
|
||||
<el-option label="成功" value="SUCCEEDED" />
|
||||
<el-option label="失败" value="FAILED" />
|
||||
<el-option label="运行中" value="RUNNING" />
|
||||
<el-option label="处理中" value="PROCESSING" />
|
||||
<el-option label="已创建" value="CREATED" />
|
||||
<el-option label="排队中" value="QUEUING" />
|
||||
<el-option label="未知错误" value="UNKNOWN" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区 -->
|
||||
<div class="bill-content">
|
||||
<!-- 加载中 -->
|
||||
<div v-if="isLoading" class="loading-container">
|
||||
<div class="loading-spinner">
|
||||
<div class="spinner-circle"></div>
|
||||
</div>
|
||||
<div class="loading-text">加载中...</div>
|
||||
</div>
|
||||
|
||||
<!-- 空数据 -->
|
||||
<div v-else-if="!orderList.length" class="empty-container">
|
||||
<img src="../../assets/images/preparation.png" alt="">
|
||||
<div class="empty-text">暂无消费记录</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<div v-else class="order-list">
|
||||
<div class="order-item" v-for="order in orderList" :key="order.row_num_">
|
||||
<!-- 订单头部 -->
|
||||
<div class="order-header">
|
||||
<div class="order-model">
|
||||
<span class="label">模型:</span>
|
||||
<span class="value">{{ order.name || order.model }}</span>
|
||||
</div>
|
||||
<div class="order-status">
|
||||
<span :class="['status-badge', getStatusClass(order.status)]">
|
||||
{{ getStatusText(order.status) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单内容 -->
|
||||
<div class="order-body">
|
||||
<div class="order-info">
|
||||
<div class="info-row">
|
||||
<span class="info-label">使用时间:</span>
|
||||
<span class="info-value">{{ order.use_time }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">模型ID:</span>
|
||||
<span class="info-value">{{ order.llmid }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">模型代码:</span>
|
||||
<span class="info-value">{{ order.model }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 金额信息 -->
|
||||
<div class="order-amount">
|
||||
<div class="amount-label">消费金额</div>
|
||||
<div class="amount-value">
|
||||
<span class="currency">¥</span>
|
||||
<span class="number">{{ order.amount !== null && order.amount !== undefined ? order.amount.toFixed(2) : '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单底部 -->
|
||||
<div class="order-footer">
|
||||
<div class="footer-info">
|
||||
<span class="info-item">使用日期:{{ order.use_date }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div v-if="orderList.length" class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:page-sizes="[5, 10, 20, 30,50]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { consumptionRecord } from '@/apis/home';
|
||||
import { useLoginStore } from '@/store/LoginStore';
|
||||
|
||||
// ==================== 实例和状态 ====================
|
||||
const loginStore = useLoginStore();
|
||||
|
||||
// ==================== 响应式数据 ====================
|
||||
/** 全部订单列表(原始数据) */
|
||||
const allOrderList = ref<any[]>([]);
|
||||
|
||||
/** 当前页显示的订单列表(分页后) */
|
||||
const orderList = ref<any[]>([]);
|
||||
|
||||
/** 加载状态 */
|
||||
const isLoading = ref(false);
|
||||
|
||||
/** 当前页码 */
|
||||
const currentPage = ref(1);
|
||||
|
||||
/** 每页条数 */
|
||||
const pageSize = ref(5);
|
||||
|
||||
/** 总条数 */
|
||||
const total = ref(0);
|
||||
|
||||
/** 状态筛选 */
|
||||
const statusFilter = ref('');
|
||||
|
||||
|
||||
// ==================== 计算属性 ====================
|
||||
/** 登录状态 */
|
||||
const isLoggedIn = computed(() => loginStore.isLoggedIn);
|
||||
|
||||
/**
|
||||
* 更新当前页显示的数据(前端分页)
|
||||
*/
|
||||
const updatePaginatedList = () => {
|
||||
// 先根据状态筛选
|
||||
let filteredList = allOrderList.value;
|
||||
|
||||
if (statusFilter.value) {
|
||||
filteredList = allOrderList.value.filter(order => {
|
||||
const status = (order.status || '').toUpperCase();
|
||||
return status === statusFilter.value.toUpperCase();
|
||||
});
|
||||
console.log('状态筛选 - 筛选条件:', statusFilter.value, '筛选后数量:', filteredList.length);
|
||||
}
|
||||
|
||||
// 更新总数为筛选后的数量
|
||||
total.value = filteredList.length;
|
||||
|
||||
// 如果当前页码超出总页数,重置为第一页
|
||||
const maxPage = Math.ceil(total.value / pageSize.value) || 1;
|
||||
if (currentPage.value > maxPage) {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
// 分页
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
const endIndex = startIndex + pageSize.value;
|
||||
orderList.value = filteredList.slice(startIndex, endIndex);
|
||||
|
||||
console.log('前端分页 - 从索引', startIndex, '到', endIndex, '显示', orderList.value.length, '条数据', '总数:', total.value);
|
||||
};
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
/**
|
||||
* 获取状态显示文本
|
||||
*/
|
||||
const getStatusText = (status: string): string => {
|
||||
const statusMap: Record<string, string> = {
|
||||
'SUCCEEDED': '成功',
|
||||
'SUCCESS': '成功',
|
||||
'succeeded': '成功',
|
||||
'success': '成功',
|
||||
'FAILED': '失败',
|
||||
'failed': '失败',
|
||||
'ERROR': '失败',
|
||||
'error': '失败',
|
||||
'RUNNING': '运行中',
|
||||
'running': '运行中',
|
||||
'PROCESSING': '处理中',
|
||||
'processing': '处理中',
|
||||
'CREATED': '已创建',
|
||||
'created': '已创建',
|
||||
'PENDING': '排队中',
|
||||
'pending': '排队中',
|
||||
'QUEUING': '排队中',
|
||||
'queueing': '排队中',
|
||||
'UNKNOWN': '未知错误',
|
||||
'unknown': '未知错误'
|
||||
};
|
||||
return statusMap[status] || '未知错误';
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取状态样式类名
|
||||
*/
|
||||
const getStatusClass = (status: string): string => {
|
||||
const classMap: Record<string, string> = {
|
||||
'SUCCEEDED': 'status-succeeded',
|
||||
'SUCCESS': 'status-succeeded',
|
||||
'succeeded': 'status-succeeded',
|
||||
'success': 'status-succeeded',
|
||||
'FAILED': 'status-failed',
|
||||
'failed': 'status-failed',
|
||||
'ERROR': 'status-failed',
|
||||
'error': 'status-failed',
|
||||
'RUNNING': 'status-running',
|
||||
'running': 'status-running',
|
||||
'PROCESSING': 'status-processing',
|
||||
'processing': 'status-processing',
|
||||
'CREATED': 'status-created',
|
||||
'created': 'status-created',
|
||||
'PENDING': 'status-queueing',
|
||||
'pending': 'status-queueing',
|
||||
'QUEUING': 'status-queueing',
|
||||
'queueing': 'status-queueing',
|
||||
'UNKNOWN': 'status-unknown',
|
||||
'unknown': 'status-unknown'
|
||||
};
|
||||
return classMap[status] || 'status-unknown';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 每页条数变化
|
||||
*/
|
||||
const handleSizeChange = (size: number) => {
|
||||
console.log('分页大小变化:', size);
|
||||
pageSize.value = size;
|
||||
currentPage.value = 1; // 切换每页条数通常重置为第一页
|
||||
updatePaginatedList(); // 前端分页,更新显示数据
|
||||
};
|
||||
|
||||
/**
|
||||
* 当前页码变化
|
||||
*/
|
||||
const handleCurrentChange = (page: number) => {
|
||||
console.log('页码变化:', page);
|
||||
currentPage.value = page;
|
||||
updatePaginatedList(); // 前端分页,更新显示数据
|
||||
};
|
||||
|
||||
/**
|
||||
* 筛选条件变化
|
||||
*/
|
||||
const handleFilterChange = () => {
|
||||
currentPage.value = 1; // 筛选变化时重置为第一页
|
||||
updatePaginatedList(); // 重新筛选和分页
|
||||
};
|
||||
|
||||
// ==================== 数据加载 ====================
|
||||
/**
|
||||
* 加载订单列表
|
||||
*/
|
||||
const loadOrderList = async () => {
|
||||
if (!isLoggedIn.value) {
|
||||
ElMessage.warning('请先登录');
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
console.log('=== 开始加载订单列表 ===');
|
||||
|
||||
// 不传递分页参数,获取所有数据
|
||||
const res = await consumptionRecord<any, any>({});
|
||||
|
||||
console.log('=== API响应 ===');
|
||||
console.log('完整响应:', res);
|
||||
console.log('响应状态:', res.status);
|
||||
console.log('响应数据:', res.data);
|
||||
|
||||
if (res.status === 'ok' && res.data) {
|
||||
const rawData = res.data.rows || [];
|
||||
allOrderList.value = rawData; // 存储所有数据
|
||||
total.value = rawData.length || 0; // 使用实际数据长度作为总数
|
||||
|
||||
console.log('=== 处理结果 ===');
|
||||
console.log('原始数据长度:', rawData.length);
|
||||
console.log('总数:', total.value);
|
||||
|
||||
// 更新当前页显示的数据
|
||||
updatePaginatedList();
|
||||
} else {
|
||||
allOrderList.value = [];
|
||||
orderList.value = [];
|
||||
total.value = 0;
|
||||
console.log('API返回非ok状态或无数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('=== 获取消费记录失败 ===');
|
||||
console.error('错误详情:', error);
|
||||
ElMessage.error('获取消费记录失败');
|
||||
allOrderList.value = [];
|
||||
orderList.value = [];
|
||||
total.value = 0;
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
onMounted(() => {
|
||||
if (isLoggedIn.value) {
|
||||
loadOrderList();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
:deep(.el-select__wrapper){
|
||||
background-color: #1e2024!important;
|
||||
border: none!important;
|
||||
}
|
||||
|
||||
|
||||
.bill-container {
|
||||
height: 100%;
|
||||
padding-bottom: 40px;
|
||||
box-sizing: border-box;
|
||||
// background-color: #1a1c20; // 主背景色
|
||||
}
|
||||
|
||||
.bill-card {
|
||||
height: 100%;
|
||||
background: #1e2024; // 卡片背景稍亮
|
||||
border: 1px solid #2a2d32;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 28px 32px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// 头部
|
||||
.bill-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 28px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
letter-spacing: 1px;
|
||||
|
||||
.iconfont {
|
||||
font-size: 26px;
|
||||
color: #00c4b3; // 主色调整为深青
|
||||
filter: drop-shadow(0 0 8px rgba(0, 196, 179, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
.header-filters {
|
||||
.status-select {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
background-color: #25282e;
|
||||
border: 1px solid #3a3e45;
|
||||
border-radius: 8px;
|
||||
box-shadow: none;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: #00c4b3;
|
||||
box-shadow: 0 0 8px rgba(0, 196, 179, 0.15);
|
||||
}
|
||||
|
||||
&.is-focus {
|
||||
border-color: #00c4b3;
|
||||
box-shadow: 0 0 12px rgba(0, 196, 179, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
color: #e0e0e0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-input__suffix) {
|
||||
color: #00c4b3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 内容区
|
||||
.bill-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 加载中
|
||||
.loading-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.spinner-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 4px solid rgba(0, 196, 179, 0.1);
|
||||
border-top-color: #00c4b3;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
box-shadow: 0 0 12px rgba(0, 196, 179, 0.3);
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
// 空数据
|
||||
.empty-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
|
||||
img {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
object-fit: contain;
|
||||
opacity: 0.5;
|
||||
filter: grayscale(30%);
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 17px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
}
|
||||
|
||||
// 订单列表
|
||||
.order-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-right: 12px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #14161a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #3a3e45;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: #00c4b3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background: #1e2024;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #2a2d32;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 订单头部
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #2a2d32;
|
||||
|
||||
.order-model {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
|
||||
.label {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 6px 14px;
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
&.status-succeeded {
|
||||
background-color: rgba(0, 196, 179, 0.12);
|
||||
color: #7fddd3;
|
||||
border: 1px solid rgba(0, 196, 179, 0.3);
|
||||
}
|
||||
|
||||
&.status-processing {
|
||||
background-color: rgba(33, 150, 243, 0.12);
|
||||
color: #90caf9;
|
||||
border: 1px solid rgba(33, 150, 243, 0.3);
|
||||
}
|
||||
|
||||
&.status-running {
|
||||
background-color: rgba(156, 39, 176, 0.12);
|
||||
color: #ce93d8;
|
||||
border: 1px solid rgba(156, 39, 176, 0.3);
|
||||
}
|
||||
|
||||
&.status-created {
|
||||
background-color: rgba(158, 158, 158, 0.12);
|
||||
color: #e0e0e0;
|
||||
border: 1px solid rgba(158, 158, 158, 0.3);
|
||||
}
|
||||
|
||||
&.status-failed {
|
||||
background-color: rgba(244, 67, 54, 0.12);
|
||||
color: #ef9a9a;
|
||||
border: 1px solid rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
&.status-queueing {
|
||||
background-color: rgba(255, 193, 7, 0.12);
|
||||
color: #ffe082;
|
||||
border: 1px solid rgba(255, 193, 7, 0.3);
|
||||
}
|
||||
|
||||
&.status-unknown {
|
||||
background-color: rgba(255, 87, 34, 0.12);
|
||||
color: #ffab91;
|
||||
border: 1px solid rgba(255, 87, 34, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单内容
|
||||
.order-body {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.order-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
width: 80px;
|
||||
flex-shrink: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.order-amount {
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
min-width: 140px;
|
||||
|
||||
.amount-label {
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-bottom: 6px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #00c4b3;
|
||||
text-shadow: 0 0 12px rgba(0, 196, 179, 0.4);
|
||||
|
||||
.currency {
|
||||
font-size: 18px;
|
||||
margin-right: 4px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.number {
|
||||
font-family: 'DIN Alternate', 'Courier New', monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 订单底部
|
||||
.order-footer {
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #2a2d32;
|
||||
|
||||
.footer-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
|
||||
.info-item {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 0 12px;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
.pagination-container {
|
||||
margin-top: 28px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #2a2d32;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
:deep(.el-tooltip__trigger){
|
||||
background-color: #14161a!important;
|
||||
border: none!important;
|
||||
}
|
||||
:deep(.el-pagination) {
|
||||
.el-pager li {
|
||||
background-color: #1e2024;
|
||||
border: 1px solid #2a2d32;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 6px;
|
||||
// transition: all 0.3s;
|
||||
margin:0 4px;
|
||||
|
||||
&.is-active {
|
||||
background-color: #00c4b3;
|
||||
border-color: #00c4b3;
|
||||
color: #1a1c20;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&:hover:not(.is-active) {
|
||||
border-color: #00c4b3;
|
||||
color: #00c4b3;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-prev,
|
||||
.btn-next {
|
||||
background-color: #1e2024;
|
||||
border: 1px solid #2a2d32;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
border-color: #00c4b3;
|
||||
color: #00c4b3;
|
||||
}
|
||||
}
|
||||
|
||||
.el-pagination__sizes,
|
||||
.el-pagination__jump {
|
||||
.el-input__wrapper {
|
||||
background-color: #25282e;
|
||||
border: 1px solid #3a3e45;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
border-color: #00c4b3;
|
||||
}
|
||||
|
||||
.el-input__inner {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-pagination__total {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.dark-popper .el-select-dropdown__list {
|
||||
background-color: #1e2024 !important;
|
||||
}
|
||||
|
||||
.dark-popper .el-select-dropdown__item {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.dark-popper .el-select-dropdown__item:hover {
|
||||
background-color: #3a3d44 !important;
|
||||
}
|
||||
|
||||
.dark-popper .el-select-dropdown__item.is-selected {
|
||||
background-color: #2c2f36 !important;
|
||||
color: #409eff !important;
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user