Merge branch 'main' of https://git.opencomputing.cn/yumoqing/kboss
This commit is contained in:
commit
f9cc1ed903
@ -4,6 +4,10 @@
|
|||||||
<router-view/>
|
<router-view/>
|
||||||
<FloatingBox
|
<FloatingBox
|
||||||
v-if="!$route.path.includes('kyyForm')&&!$route.path.includes('floatingBox')&&!$route.path.includes('screen')&&!$route.path.includes('wxPage')&&!$route.path.includes('wxDetailPage')"/>
|
v-if="!$route.path.includes('kyyForm')&&!$route.path.includes('floatingBox')&&!$route.path.includes('screen')&&!$route.path.includes('wxPage')&&!$route.path.includes('wxDetailPage')"/>
|
||||||
|
<LoginDialog
|
||||||
|
:visible.sync="loginDialogVisible"
|
||||||
|
@success="handleGlobalLoginSuccess"
|
||||||
|
/>
|
||||||
<div>
|
<div>
|
||||||
<!-- 弹出通话提示-->
|
<!-- 弹出通话提示-->
|
||||||
<div v-if="isShowVideo" class="is-accepted" style="padding: 5px;border-radius: 6px">
|
<div v-if="isShowVideo" class="is-accepted" style="padding: 5px;border-radius: 6px">
|
||||||
@ -38,6 +42,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
import FloatingBox from './components/FloatingBox/FloatingBox.vue'; // 导入悬浮框组件
|
import FloatingBox from './components/FloatingBox/FloatingBox.vue'; // 导入悬浮框组件
|
||||||
|
import LoginDialog from '@/views/LoginDialog/LoginDialog.vue'
|
||||||
import '@/assets/elementStyle.css'
|
import '@/assets/elementStyle.css'
|
||||||
import Hammer from 'hammerjs';
|
import Hammer from 'hammerjs';
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
@ -45,6 +50,7 @@ export default {
|
|||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
FloatingBox, // 注册悬浮框组件
|
FloatingBox, // 注册悬浮框组件
|
||||||
|
LoginDialog,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -52,7 +58,8 @@ export default {
|
|||||||
socket: null,
|
socket: null,
|
||||||
userId: sessionStorage.getItem('userId'),
|
userId: sessionStorage.getItem('userId'),
|
||||||
vedioObj: {},
|
vedioObj: {},
|
||||||
customerName: ''
|
customerName: '',
|
||||||
|
loginDialogVisible: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -66,6 +73,10 @@ export default {
|
|||||||
}
|
}
|
||||||
this.setRemUnit()
|
this.setRemUnit()
|
||||||
this.initHammer();
|
this.initHammer();
|
||||||
|
window.addEventListener('kboss-open-login-dialog', this.openGlobalLoginDialog)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('kboss-open-login-dialog', this.openGlobalLoginDialog)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
@ -75,6 +86,16 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openGlobalLoginDialog() {
|
||||||
|
if (this.$route && this.$route.fullPath && !this.$route.fullPath.includes('/login')) {
|
||||||
|
sessionStorage.setItem('loginRedirectPath', this.$route.fullPath)
|
||||||
|
}
|
||||||
|
this.loginDialogVisible = true
|
||||||
|
},
|
||||||
|
handleGlobalLoginSuccess() {
|
||||||
|
this.loginDialogVisible = false
|
||||||
|
this.userId = sessionStorage.getItem('userId')
|
||||||
|
},
|
||||||
playAudio() {
|
playAudio() {
|
||||||
console.log("开始按钮点击了")
|
console.log("开始按钮点击了")
|
||||||
this.audioElement.play();
|
this.audioElement.play();
|
||||||
|
|||||||
@ -165,16 +165,8 @@ service.interceptors.response.use(
|
|||||||
isRedirectingToLogin = true
|
isRedirectingToLogin = true
|
||||||
saveLoginRedirectPath()
|
saveLoginRedirectPath()
|
||||||
showErrorMessage('登录已过期,请重新登录')
|
showErrorMessage('登录已过期,请重新登录')
|
||||||
const currentPath = (router.currentRoute && router.currentRoute.path) || ''
|
window.dispatchEvent(new Event('kboss-open-login-dialog'))
|
||||||
const isHomePage = currentPath.includes('/homePage') || currentPath.includes('/ncmatchHome')
|
isRedirectingToLogin = false
|
||||||
if (isHomePage) {
|
|
||||||
window.dispatchEvent(new Event('kboss-open-login-dialog'))
|
|
||||||
isRedirectingToLogin = false
|
|
||||||
} else {
|
|
||||||
router.push({path: '/login'}).finally(() => {
|
|
||||||
isRedirectingToLogin = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// window.location.href = 'https://www.opencomputing.cn/'
|
// window.location.href = 'https://www.opencomputing.cn/'
|
||||||
} else if (code == 403) {
|
} else if (code == 403) {
|
||||||
|
|||||||
@ -112,13 +112,20 @@
|
|||||||
v-for="(product, index) in displayedTokenProducts"
|
v-for="(product, index) in displayedTokenProducts"
|
||||||
:key="product.id"
|
:key="product.id"
|
||||||
class="token-market-card"
|
class="token-market-card"
|
||||||
@click="goModelDetail(product)"
|
>
|
||||||
>
|
<!-- @click="goModelDetail(product)" -->
|
||||||
|
|
||||||
<div class="token-card-top">
|
<div class="token-card-top">
|
||||||
<span class="token-provider-avatar">
|
<span class="token-provider-avatar">
|
||||||
<img v-if="product.model_logo" :src="getModelLogoUrl(product.model_logo)" alt="">
|
<img
|
||||||
|
v-if="product.model_logo && !product.logoLoadFailed"
|
||||||
|
:src="getModelLogoUrl(product.model_logo)"
|
||||||
|
alt=""
|
||||||
|
@error="handleModelLogoError(product)"
|
||||||
|
>
|
||||||
<span v-else>{{ getProviderInitial(product.provider || product.display_name || product.model_name) }}</span>
|
<span v-else>{{ getProviderInitial(product.provider || product.display_name || product.model_name) }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="token-title-group">
|
<div class="token-title-group">
|
||||||
<h3>{{ product.display_name || product.model_name }}</h3>
|
<h3>{{ product.display_name || product.model_name }}</h3>
|
||||||
<p>{{ product.provider || product.model_name || '-' }}</p>
|
<p>{{ product.provider || product.model_name || '-' }}</p>
|
||||||
@ -126,25 +133,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="token-price-grid">
|
<div class="token-price-grid">
|
||||||
<div class="token-price-item">
|
<div
|
||||||
<span>输入</span>
|
v-for="(price, priceIndex) in getBillingPreview(product.billing_method)"
|
||||||
<strong>¥{{ formatTokenPrice(product.input_token_price) }}</strong>
|
:key="`${product.id}-billing-${priceIndex}`"
|
||||||
<em>元/百万 tokens</em>
|
class="token-price-item"
|
||||||
|
>
|
||||||
|
<span>{{ price.name }}</span>
|
||||||
|
<strong>{{ price.price }}</strong>
|
||||||
|
<em>{{ price.desc }}</em>
|
||||||
</div>
|
</div>
|
||||||
<div class="token-price-item">
|
<div v-if="getBillingMoreCount(product.billing_method)" class="billing-more-tip">
|
||||||
<span>输出</span>
|
+ {{ getBillingMoreCount(product.billing_method) }} 条计费规则,进入详情查看
|
||||||
<strong>¥{{ formatTokenPrice(product.output_token_price) }}</strong>
|
|
||||||
<em>元/百万 tokens</em>
|
|
||||||
</div>
|
|
||||||
<div class="token-price-item">
|
|
||||||
<span>缓存读</span>
|
|
||||||
<strong>¥{{ formatTokenPrice(product.cache_hit_input_price) }}</strong>
|
|
||||||
<em>元/百万 tokens</em>
|
|
||||||
</div>
|
|
||||||
<div class="token-price-item">
|
|
||||||
<span>缓存创建</span>
|
|
||||||
<strong>¥{{ formatTokenPrice(product.input_token_price) }}</strong>
|
|
||||||
<em>元/百万 tokens</em>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -395,6 +394,36 @@ export default {
|
|||||||
return num.toFixed(4).replace(/\.?0+$/, '');
|
return num.toFixed(4).replace(/\.?0+$/, '');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parseBillingMethod(value) {
|
||||||
|
const text = String(value || '').trim();
|
||||||
|
if (!text) {
|
||||||
|
return [{ name: '计费方式', price: '按量计费', desc: '详情以后端配置为准' }];
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
.split(/\n+/)
|
||||||
|
.map(line => line.replace(/^\s*[-–—]\s*/, '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(line => {
|
||||||
|
const match = line.match(/^([^::]+)[::]\s*([^\[]+)(?:\[(.+)\])?$/);
|
||||||
|
if (!match) {
|
||||||
|
return { name: '计费说明', price: line, desc: '' };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: match[1].trim(),
|
||||||
|
price: match[2].trim(),
|
||||||
|
desc: (match[3] || '').trim()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getBillingPreview(value) {
|
||||||
|
return this.parseBillingMethod(value).slice(0, 3);
|
||||||
|
},
|
||||||
|
|
||||||
|
getBillingMoreCount(value) {
|
||||||
|
return Math.max(this.parseBillingMethod(value).length - 3, 0);
|
||||||
|
},
|
||||||
|
|
||||||
// 供应商头像取首字,避免没有 logo 时卡片显得空。
|
// 供应商头像取首字,避免没有 logo 时卡片显得空。
|
||||||
getProviderInitial(provider) {
|
getProviderInitial(provider) {
|
||||||
return provider ? provider.slice(0, 1) : 'M';
|
return provider ? provider.slice(0, 1) : 'M';
|
||||||
@ -408,6 +437,10 @@ export default {
|
|||||||
return `${this.IMG_URL}${modelLogo}`;
|
return `${this.IMG_URL}${modelLogo}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleModelLogoError(product) {
|
||||||
|
this.$set(product, 'logoLoadFailed', true);
|
||||||
|
},
|
||||||
|
|
||||||
normalizeTokenConfigList(value) {
|
normalizeTokenConfigList(value) {
|
||||||
if (!value) return [];
|
if (!value) return [];
|
||||||
let parsedValue = value;
|
let parsedValue = value;
|
||||||
@ -1471,13 +1504,18 @@ export default {
|
|||||||
.token-price-grid {
|
.token-price-grid {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
flex-direction: column;
|
||||||
gap: 8px 12px;
|
gap: 5px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.token-price-item {
|
.token-price-item {
|
||||||
|
padding: 7px 9px;
|
||||||
|
background: rgba(248, 250, 252, 0.86);
|
||||||
|
border: 1px solid #edf1f7;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
span,
|
span,
|
||||||
em {
|
em {
|
||||||
display: block;
|
display: block;
|
||||||
@ -1488,22 +1526,36 @@ export default {
|
|||||||
span {
|
span {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
display: block;
|
display: block;
|
||||||
color: #111827;
|
color: #0f172a;
|
||||||
font-size: 15px;
|
font-size: 13px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
line-height: 1.1;
|
line-height: 1.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
em {
|
em {
|
||||||
margin-top: 0;
|
margin-top: 2px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
line-height: 1.4;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.billing-more-tip {
|
||||||
|
padding: 5px 9px;
|
||||||
|
color: #2563eb;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #eff6ff;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
.token-description {
|
.token-description {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -1558,8 +1610,8 @@ export default {
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 34px;
|
||||||
height: 100%;
|
height: 34px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user