add user lock for chat api, Prevent insufficient deduction of user power caused by submitting multiple requests at one time
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 933 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 982 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 7.4 KiB |
@@ -178,10 +178,13 @@ const props = defineProps({
|
||||
const selectedModel = ref(props.items[0])
|
||||
const requiredKeys = ref(props.requiredKeys)
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const emit = defineEmits(['update:modelValue', 'update:requiredKeys'])
|
||||
|
||||
// 初始化 modelValue 默认值
|
||||
const initModelValue = (model) => {
|
||||
if (props.items.length === 0) {
|
||||
return {}
|
||||
}
|
||||
const defaultValues = {}
|
||||
requiredKeys.value = {}
|
||||
if (model && model.params) {
|
||||
@@ -250,6 +253,7 @@ watch(
|
||||
() => props.items,
|
||||
(newValue) => {
|
||||
selectedModel.value = newValue[0]
|
||||
modelValue.value = initModelValue(selectedModel.value)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
@@ -102,76 +102,7 @@ export const JimengParams = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '图片 2.1 文生图',
|
||||
version: '2.1',
|
||||
label: '平面绘感强,可生成文字海报',
|
||||
key: 'jimeng_high_aes_general_v21_L',
|
||||
params: [
|
||||
{
|
||||
name: 'prompt',
|
||||
label: '提示词',
|
||||
type: 'textarea',
|
||||
showWordLimit: true,
|
||||
maxlength: 800,
|
||||
autosize: { minRows: 3, maxRows: 5 },
|
||||
required: true,
|
||||
placeholder: '请输入提示词',
|
||||
info: '用于生成图像的提示词 ,中英文均可输入',
|
||||
},
|
||||
|
||||
{
|
||||
name: 'size',
|
||||
type: 'select',
|
||||
required: true,
|
||||
placeholder: '请选择尺寸',
|
||||
label: '图片尺寸',
|
||||
prefix: 'icon-resize',
|
||||
options: [
|
||||
{
|
||||
label: '21:9 (1195 * 512)',
|
||||
value: '1195x512',
|
||||
},
|
||||
{
|
||||
label: '16:9 (1024 * 576)',
|
||||
value: '1024x576',
|
||||
},
|
||||
{
|
||||
label: '3:2 (1024 * 682)',
|
||||
value: '1024x682',
|
||||
},
|
||||
{
|
||||
label: '4:3 (1024 * 768)',
|
||||
value: '1024x768',
|
||||
},
|
||||
{
|
||||
label: '1:1 (1024 * 1024)',
|
||||
value: '1024x1024',
|
||||
},
|
||||
{
|
||||
label: '3:4 (768 * 1024)',
|
||||
value: '768x1024',
|
||||
},
|
||||
{
|
||||
label: '2:3 (682 * 1024)',
|
||||
value: '682x1024',
|
||||
},
|
||||
{
|
||||
label: '9:16 (576 * 1024)',
|
||||
value: '576x1024',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'use_pre_llm',
|
||||
type: 'switch',
|
||||
required: false,
|
||||
label: '开启文本扩写',
|
||||
info: '开启后,系统会自动扩写提示词,提高生成质量',
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '图片 3.0 文生图',
|
||||
version: '3.0',
|
||||
@@ -354,6 +285,17 @@ export const JimengParams = {
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
info: '长边与短边比例在3以内,超出此比例或比例相对极端,会导致报错。',
|
||||
},
|
||||
{
|
||||
name: 'scale',
|
||||
label: '文本描述影响的程度',
|
||||
type: 'slider',
|
||||
required: true,
|
||||
info: '该值越大代表文本描述影响程度越大,且输入图片影响程度越小',
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
value: 0.5,
|
||||
},
|
||||
{
|
||||
name: 'size',
|
||||
type: 'select',
|
||||
@@ -405,17 +347,6 @@ export const JimengParams = {
|
||||
label: '将输入的单人写真图片,进行有创意的特效化处理。',
|
||||
key: 'i2i_multi_style_zx2x',
|
||||
params: [
|
||||
{
|
||||
name: 'prompt',
|
||||
label: '提示词',
|
||||
type: 'textarea',
|
||||
required: true,
|
||||
showWordLimit: true,
|
||||
maxlength: 800,
|
||||
autosize: { minRows: 3, maxRows: 5 },
|
||||
placeholder: '请输入用于编辑图像的提示词,如:把xxx改成xxx,删除xxx,添加xxx等',
|
||||
info: '建议长度<=120字符,最长不超过800字符',
|
||||
},
|
||||
{
|
||||
name: 'image_urls',
|
||||
label: '参考图片',
|
||||
@@ -610,6 +541,77 @@ export const JimengParams = {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: '图片 2.1 文生图',
|
||||
version: '2.1',
|
||||
label: '平面绘感强,可生成文字海报',
|
||||
key: 'jimeng_high_aes_general_v21_L',
|
||||
params: [
|
||||
{
|
||||
name: 'prompt',
|
||||
label: '提示词',
|
||||
type: 'textarea',
|
||||
showWordLimit: true,
|
||||
maxlength: 800,
|
||||
autosize: { minRows: 3, maxRows: 5 },
|
||||
required: true,
|
||||
placeholder: '请输入提示词',
|
||||
info: '用于生成图像的提示词 ,中英文均可输入',
|
||||
},
|
||||
|
||||
{
|
||||
name: 'size',
|
||||
type: 'select',
|
||||
required: true,
|
||||
placeholder: '请选择尺寸',
|
||||
label: '图片尺寸',
|
||||
prefix: 'icon-resize',
|
||||
options: [
|
||||
{
|
||||
label: '21:9 (1195 * 512)',
|
||||
value: '1195x512',
|
||||
},
|
||||
{
|
||||
label: '16:9 (1024 * 576)',
|
||||
value: '1024x576',
|
||||
},
|
||||
{
|
||||
label: '3:2 (1024 * 682)',
|
||||
value: '1024x682',
|
||||
},
|
||||
{
|
||||
label: '4:3 (1024 * 768)',
|
||||
value: '1024x768',
|
||||
},
|
||||
{
|
||||
label: '1:1 (1024 * 1024)',
|
||||
value: '1024x1024',
|
||||
},
|
||||
{
|
||||
label: '3:4 (768 * 1024)',
|
||||
value: '768x1024',
|
||||
},
|
||||
{
|
||||
label: '2:3 (682 * 1024)',
|
||||
value: '682x1024',
|
||||
},
|
||||
{
|
||||
label: '9:16 (576 * 1024)',
|
||||
value: '576x1024',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'use_pre_llm',
|
||||
type: 'switch',
|
||||
required: false,
|
||||
label: '开启文本扩写',
|
||||
info: '开启后,系统会自动扩写提示词,提高生成质量',
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
video: [
|
||||
// 视频 3.0 720P-文生视频
|
||||
|
||||
@@ -28,8 +28,6 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
|
||||
// 用户信息
|
||||
const isLogin = ref(false)
|
||||
const userPower = ref(100)
|
||||
|
||||
// 视频预览
|
||||
const showDialog = ref(false)
|
||||
const currentVideoUrl = ref('')
|
||||
@@ -37,16 +35,9 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
// 登录弹窗
|
||||
const shareStore = useSharedStore()
|
||||
|
||||
// 新增:动态获取算力消耗配置
|
||||
// 积分消耗配置
|
||||
const powerConfig = reactive({})
|
||||
// 动态设置算力消耗
|
||||
const setFunctionPowers = (config) => {
|
||||
functions.forEach((f) => {
|
||||
if (config[f.key] !== undefined) {
|
||||
f.power = config[f.key]
|
||||
}
|
||||
})
|
||||
}
|
||||
const currentPowerCost = ref('0积分')
|
||||
|
||||
// 功能配置
|
||||
const functions = JimengFunctions
|
||||
@@ -69,11 +60,7 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
const switchFunction = (f) => {
|
||||
activeFunction.value = f.key
|
||||
formData.value = {}
|
||||
}
|
||||
|
||||
// 获取当前算力消耗
|
||||
const getCurrentPowerCost = () => {
|
||||
return activeFunction.value.power
|
||||
setFunctionPowers()
|
||||
}
|
||||
|
||||
// 获取功能名称
|
||||
@@ -198,12 +185,9 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
shareStore.setShowLoginDialog(true)
|
||||
return
|
||||
}
|
||||
// if (userPower.value < currentPowerCost.value) {
|
||||
// showMessageError('算力不足')
|
||||
// return
|
||||
// }
|
||||
console.log(formData.value)
|
||||
for (const key in requiredKeys.value) {
|
||||
if (!formData.value[key].required) {
|
||||
if (!formData.value[key]) {
|
||||
showMessageError('缺少参数:' + requiredKeys.value[key].label)
|
||||
return
|
||||
}
|
||||
@@ -296,18 +280,25 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const setFunctionPowers = () => {
|
||||
if (activeFunction.value === 'image') {
|
||||
currentPowerCost.value = `${powerConfig.image}积分/张`
|
||||
} else {
|
||||
currentPowerCost.value = `${powerConfig.video}积分/秒`
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化方法
|
||||
const init = async () => {
|
||||
try {
|
||||
// 获取算力消耗配置
|
||||
// 获取积分消耗配置
|
||||
const powerRes = await httpGet('/api/jimeng/power-config')
|
||||
if (powerRes.data) {
|
||||
Object.assign(powerConfig, powerRes.data)
|
||||
setFunctionPowers(powerRes.data)
|
||||
setFunctionPowers()
|
||||
}
|
||||
const user = await checkSession()
|
||||
isLogin.value = true
|
||||
userPower.value = user.power
|
||||
// 获取任务列表
|
||||
await fetchData(1)
|
||||
// 开始轮询
|
||||
@@ -335,7 +326,6 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
currentList,
|
||||
isOver,
|
||||
isLogin,
|
||||
userPower,
|
||||
showDialog,
|
||||
currentVideoUrl,
|
||||
|
||||
@@ -346,11 +336,11 @@ export const useJimengStore = defineStore('jimeng', () => {
|
||||
formData,
|
||||
requiredKeys,
|
||||
progress,
|
||||
currentPowerCost,
|
||||
|
||||
// 方法
|
||||
init,
|
||||
switchFunction,
|
||||
getCurrentPowerCost,
|
||||
getFunctionName,
|
||||
getTaskStatusText,
|
||||
getTaskType,
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
<!-- 功能开关 -->
|
||||
<div class="function-params">
|
||||
<div class="mb-3">
|
||||
<div class="mb-2">
|
||||
<div class="mb-2" v-if="store.functionParams[store.activeFunction].length > 0">
|
||||
<label class="label text-left font-bold">模型选择</label>
|
||||
</div>
|
||||
<param-builder
|
||||
@@ -152,7 +152,10 @@
|
||||
</div>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<div class="submit-btn flex justify-center pt-4">
|
||||
<div
|
||||
class="submit-btn flex justify-center pt-4"
|
||||
v-if="store.functionParams[store.activeFunction].length > 0"
|
||||
>
|
||||
<button
|
||||
@click="store.submitTask"
|
||||
:disabled="store.submitting"
|
||||
@@ -161,7 +164,7 @@
|
||||
>
|
||||
<i v-if="store.submitting" class="iconfont icon-loading animate-spin"></i>
|
||||
<i v-else class="iconfont icon-chuangzuo"></i>
|
||||
<span>立即生成 ({{ store.currentPowerCost }}算力)</span>
|
||||
<span>立即生成 ({{ store.currentPowerCost }})</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -342,7 +345,7 @@
|
||||
</div>
|
||||
<div class="task-meta">
|
||||
<span>{{ dateFormat(item.created_at) }}</span>
|
||||
<span v-if="item.power">{{ item.power }}算力</span>
|
||||
<span v-if="item.power">{{ item.power }}积分</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,9 +57,8 @@
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="text-gray-500 text-sm">
|
||||
生成图片消耗的积分,包括:文生图、图生图、图片编辑、图片特效,<span
|
||||
class="text-red-500"
|
||||
>单位:积分/张</span
|
||||
生成图片消耗的积分,包括:文生图、图生图、图片编辑、图片特效,<el-tag type="primary"
|
||||
>单位:积分/张</el-tag
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
@@ -72,8 +71,8 @@
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="text-gray-500 text-sm">
|
||||
生成视频消耗的积分,包括:文生视频、图生视频,<span class="text-red-500"
|
||||
>单位:积分/秒</span
|
||||
生成视频消耗的积分,包括:文生视频、图生视频,<el-tag type="primary"
|
||||
>单位:积分/秒</el-tag
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
@@ -86,7 +85,7 @@
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="text-gray-500 text-sm">
|
||||
生成数字人视频消耗的积分,<span class="text-red-500">单位:积分/秒</span>
|
||||
生成数字人视频消耗的积分,<el-tag type="primary">单位:积分/秒</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<el-input-number
|
||||
@@ -98,7 +97,7 @@
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="text-gray-500 text-sm">
|
||||
生成视频动作迁移消耗的积分,<span class="text-red-500">单位:积分/秒</span>
|
||||
生成视频动作迁移消耗的积分,<el-tag type="primary">单位:积分/秒</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<el-input-number
|
||||
|
||||