Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ai_web_page_prod
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
haojie
ai_web_page_prod
Commits
b1b30785
Commit
b1b30785
authored
Apr 20, 2023
by
haojie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
c5f8a27f
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1221 additions
and
404 deletions
+1221
-404
src/components/custom/ImgSizeRadioGroup.vue
+15
-2
src/components/custom/Select.vue
+1
-1
src/components/custom/TTable.vue
+5
-4
src/components/custom/input/index.vue
+1
-1
src/components/custom/loading2.vue
+24
-1
src/components/modulecard.vue
+4
-10
src/layout/content.vue
+2
-2
src/pages/CopywritingGeneration/index.vue
+127
-76
src/pages/CreationRecord/components/CopywritingRecord.vue
+177
-0
src/pages/CreationRecord/components/MappingRecord.vue
+170
-26
src/pages/CreationRecord/index.vue
+25
-27
src/pages/Detail/index.vue
+52
-18
src/pages/Home/components/HomeSwiper/swiper.vue
+3
-0
src/pages/Home/index.less
+2
-0
src/pages/Home/index.tsx
+30
-9
src/pages/ImageGeneration/components/GenerateResult/index.less
+11
-8
src/pages/ImageGeneration/components/GenerateResult/index.tsx
+10
-5
src/pages/ImageGeneration/components/upload/index.less
+5
-0
src/pages/ImageGeneration/components/upload/index.tsx
+13
-48
src/pages/ImageGeneration/index.vue
+213
-163
src/style/ui.less
+5
-0
src/style/variables.less
+0
-1
src/utils/api/Task.ts
+236
-0
src/utils/api/scenes.ts
+60
-2
src/utils/tool.ts
+30
-0
No files found.
src/components/custom/ImgSizeRadioGroup.vue
View file @
b1b30785
...
...
@@ -31,7 +31,7 @@
<
script
lang=
"ts"
setup
>
import
CustomInput
from
'@/components/custom/input/index.vue'
;
import
{
ref
}
from
'vue'
;
import
{
ref
,
watch
}
from
'vue'
;
const
props
=
withDefaults
(
defineProps
<
{
list
:
any
[];
...
...
@@ -43,8 +43,21 @@ const emit = defineEmits(['update:modelValue']);
// 当前选择的下标
const
Current_btn
=
ref
(
props
.
modelValue
);
const
onBtnChange
=
(
item
:
any
)
=>
{
Current_btn
.
value
=
item
.
value
;
emit
(
'update:modelValue'
,
item
.
value
)
;
};
watch
(
()
=>
props
.
modelValue
,
(
v
)
=>
{
Current_btn
.
value
=
v
;
}
);
watch
(
()
=>
Current_btn
.
value
,
(
v
)
=>
{
emit
(
'update:modelValue'
,
v
);
}
);
</
script
>
<
style
lang=
"less"
>
...
...
src/components/custom/Select.vue
View file @
b1b30785
...
...
@@ -33,7 +33,7 @@ const props = withDefaults(
}
);
const
emit
=
defineEmits
([
'update:modelValue'
]);
const
SelectValue
=
ref
(
''
);
const
SelectValue
=
ref
(
props
.
modelValue
);
watch
(
()
=>
SelectValue
.
value
,
(
v
)
=>
{
...
...
src/components/custom/TTable.vue
View file @
b1b30785
...
...
@@ -7,13 +7,14 @@
:columns=
"columns"
hover
:loading=
"loading"
></TTable>
>
</TTable>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
Table
as
TTable
}
from
"tdesign-vue-next"
;
import
{
ref
}
from
"vue"
;
import
{
Table
as
TTable
}
from
'tdesign-vue-next'
;
import
{
ref
}
from
'vue'
;
const
props
=
defineProps
<
{
columns
:
any
[];
list
:
any
[];
...
...
@@ -22,7 +23,7 @@ const loading = ref(false);
</
script
>
<
style
lang=
"less"
>
@import
"@/style/variables.less"
;
@import
'@/style/variables.less'
;
.reset-t-table
{
background-color
:
transparent
;
.t-table__content
{
...
...
src/components/custom/input/index.vue
View file @
b1b30785
...
...
@@ -102,7 +102,7 @@ const Cur_pwd_type = ref<string>('private');
const
numberInput
=
(
e
:
string
)
=>
{
const
{
type
}
=
props
;
if
(
type
==
'number'
)
{
input_value
.
value
=
e
.
replace
(
/
[^\d
.
]
/g
,
''
);
input_value
.
value
=
e
.
replace
(
/
[^\d]
/g
,
''
);
}
// 提交输入事件
emit
(
'inputChange'
,
input_value
.
value
);
...
...
src/components/custom/loading2.vue
View file @
b1b30785
<
template
>
<div
class=
"custom-loading-two"
:style=
"
{
position: position,
}"
>
<div
class=
"loading"
>
<div></div>
<div></div>
...
...
@@ -9,9 +15,26 @@
<div></div>
<div></div>
</div>
</div>
</
template
>
<
style
>
<
script
lang=
"ts"
setup
>
const
props
=
withDefaults
(
defineProps
<
{
position
?:
string
;
}
>
(),
{
position
:
'absolute'
,
}
);
</
script
>
<
style
lang=
"less"
>
.custom-loading-two
{
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
.loading
,
.loading
>
div
{
position
:
relative
;
...
...
src/components/modulecard.vue
View file @
b1b30785
...
...
@@ -4,9 +4,9 @@
<div
class=
"recommend-content"
>
<template
v-for=
"(item, index) in list"
:key=
"index"
>
<CustomCard
:img=
"item.im
g
"
:img=
"item.im
age
"
:title=
"item.title"
:content=
"item.
content
"
:content=
"item.
description
"
@
click=
"toGenerate(item)"
></CustomCard>
</
template
>
...
...
@@ -17,20 +17,14 @@
<
script
lang=
"ts"
setup
>
import
{
reactive
}
from
'vue'
;
import
CustomCard
from
'@/components/card.vue'
;
import
{
useRouter
}
from
'vue-router'
;
const
props
=
defineProps
<
{
list
:
any
[];
label
:
string
;
}
>
();
const
router
=
useRouter
(
);
const
emit
=
defineEmits
([
'change'
]
);
const
toGenerate
=
(
item
:
any
)
=>
{
// 判断类型跳转页面
console
.
log
(
item
);
const
url
=
router
.
resolve
({
// path: '/CopywritingGeneration',
path
:
'/ImageGeneration'
,
});
window
.
open
(
url
.
href
);
emit
(
'change'
,
item
);
};
</
script
>
...
...
src/layout/content.vue
View file @
b1b30785
...
...
@@ -27,13 +27,13 @@ const route = useRoute();
background
:
#181818
;
.custom-content
{
flex
:
1
;
max-height
:
calc
(
100vh
-
6
0
px
);
max-height
:
calc
(
100vh
-
6
7
px
);
overflow
:
auto
;
.center-box
{
margin
:
0
auto
;
//
min-width
:
90vw
;
max-width
:
1597px
;
box-sizing
:
border-box
;
min-width
:
90vw
;
padding
:
0
30px
;
height
:
100%
;
}
...
...
src/pages/CopywritingGeneration/index.vue
View file @
b1b30785
<
template
>
<div
class=
"custom-copywriting-generation"
>
<img
class=
"tip-box"
:src=
"imgs.tips"
alt=
""
/>
<div
class=
"custom-copywriting-generation-page"
>
<div
class=
"custom-copywriting-generation"
v-show=
"!loading"
>
<img
class=
"tip-box"
:src=
"res_img ?? imgs.tips"
alt=
""
/>
<div
class=
"interaction-form"
>
<div
class=
"basic-info"
v-for=
"item in AdminData.list"
:key=
"item.name"
>
<div
class=
"label"
>
*
{{
item
.
name
}}
</div>
...
...
@@ -34,15 +35,19 @@
</div>
<div
class=
"confirm-box"
>
<div>
字符余额:0/50000
</div>
<CustomResetButton
@
click=
"onReset"
width=
"20%"
>
重置
</CustomResetButton>
<CustomResetButton
@
click=
"onReset"
width=
"50%"
bold
>
生成图片
</CustomResetButton
<CustomResetButton
@
click=
"onReset"
width=
"20%"
>
重置
</CustomResetButton
>
<CustomResetButton
@
click=
"beforeSubmit"
width=
"50%"
bold
>
生成文案
</CustomResetButton
>
</div>
<div
class=
"cust-line"
></div>
<CustomGptMessage
computed
:list=
"MessageList.list"
></CustomGptMessage>
</div>
</div>
<CustomLoading
v-show=
"loading"
></CustomLoading>
</div>
</template>
<
script
lang=
"ts"
setup
>
...
...
@@ -51,87 +56,56 @@ import CustomTextArea from '@/components/custom/textarea.vue';
import
CustomInput
from
'@/components/custom/input/index.vue'
;
import
CustomResetButton
from
'@/components/custom/resetbutton.vue'
;
import
CustomGptMessage
from
'@/components/custom/gptmessage.vue'
;
import
{
onBeforeMount
,
reactive
}
from
'vue'
;
import
{
onBeforeMount
,
reactive
,
ref
}
from
'vue'
;
import
{
getScenesList
,
useSubmitConversation
}
from
'@/utils/api/scenes'
;
import
{
useRoute
}
from
'vue-router'
;
import
{
show_message
}
from
'@/utils/tdesign_tool'
;
import
{
FormExample
,
ConversationKey
}
from
'@/utils/api/Task'
;
import
CustomLoading
from
'@/components/custom/loading2.vue'
;
import
{
Validationrules
}
from
'@/utils/tool'
;
const
route
=
useRoute
();
const
id
=
route
.
query
.
id
;
const
imgs
=
{
tips
:
new
URL
(
'../../assets/img/tips.png'
,
import
.
meta
.
url
).
href
,
};
// 场景id
const
scenario_id
=
ref
();
// 场景示例图
const
res_img
=
ref
(
''
);
const
loading
=
ref
(
false
);
// 后台配置的输入类型--input-select-textarea
// type-1是input,2是select,3是长文本输入
const
AdminData
=
reactive
({
list
:
[],
});
// 获取本地存储的对话记录--先返回空数组
const
getLocalList
=
()
=>
{
return
[];
let
list
=
localStorage
.
getItem
(
ConversationKey
);
if
(
list
)
{
return
JSON
.
parse
(
list
);
}
return
[];
};
// gpt-消息列表
const
MessageList
=
reactive
({
list
:
[
{
user
:
'user'
,
message
:
'早上好,早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好,早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好'
,
},
{
user
:
'user'
,
message
:
''
,
},
],
// 显示在页面的list
list
:
[],
// 存本地的完整对话列表
localList
:
getLocalList
(),
});
// 获取后台配置的组件
const
getAdminComponent
=
async
()
=>
{
try
{
// let res:any = await ddd();
// if(res.data){
// }
let
list
=
[
{
name
:
'基础填写'
,
value
:
'name'
,
lists
:
[
{
type
:
'text'
,
name
:
'url'
,
label
:
'链接'
,
value
:
null
,
span
:
24
,
placeholder
:
'输入链接'
,
// component_type: 'input',
},
// 下拉选择
{
type
:
'select'
,
options
:
[
{
label
:
'第一个'
,
value
:
1
,
},
{
label
:
'第二个'
,
value
:
2
,
},
],
// 可设置默认值
value
:
1
,
},
],
},
{
name
:
'详细描述'
,
value
:
'2'
,
lists
:
[
{
// 长文本输入框
type
:
'textarea'
,
name
:
'url'
,
label
:
'链接'
,
value
:
null
,
span
:
24
,
maxRows
:
'5'
,
minRows
:
'5'
,
placeholder
:
'详细描述产品细节,生成的文案更加完美。'
,
maxlength
:
100
,
// component_type: 'input',
},
],
},
];
loading
.
value
=
true
;
console
.
log
(
JSON
.
stringify
(
FormExample
));
let
res
:
any
=
await
getScenesList
(
id
,
'id'
);
if
(
res
.
code
==
0
)
{
// 取id
scenario_id
.
value
=
res
.
data
.
id
;
// 取图片
res_img
.
value
=
res
.
data
.
example_image
;
let
list
=
res
.
data
.
form
;
// 修改数据
list
.
forEach
((
item
:
any
)
=>
{
item
.
lists
.
forEach
((
it
:
any
)
=>
{
...
...
@@ -150,16 +124,89 @@ const getAdminComponent = async () => {
});
});
AdminData
.
list
=
list
;
console
.
log
(
AdminData
.
list
);
}
loading
.
value
=
false
;
}
catch
(
e
)
{
console
.
log
(
e
);
loading
.
value
=
false
;
}
};
// 重置
const
onReset
=
()
=>
{
console
.
log
(
'111'
);
// 遍历整个列表,清空value
AdminData
.
list
.
forEach
((
item
:
any
)
=>
{
item
.
lists
.
forEach
((
it
:
any
)
=>
{
if
(
it
.
value
)
{
it
.
value
=
''
;
}
});
});
};
// 提交
const
onSubmit
=
async
(
params
:
any
)
=>
{
try
{
// 提交前先创建一个消息
MessageList
.
list
.
push
({
message
:
''
,
});
let
res
:
any
=
await
useSubmitConversation
({
scenario_id
:
scenario_id
.
value
,
// messages: MessageList.localList,
messages
:
[],
parameters
:
params
,
});
if
(
res
.
code
==
0
)
{
// 完整对话记录
MessageList
.
localList
=
res
.
data
;
localStorage
.
setItem
(
ConversationKey
,
JSON
.
stringify
(
MessageList
.
localList
)
);
// 要显示的内容--找到最后一条属于机器人的消息
let
RobotList
=
MessageList
.
localList
.
filter
(
(
item
:
any
)
=>
item
.
role
==
'assistant'
);
if
(
RobotList
&&
RobotList
.
length
)
{
MessageList
.
list
[
MessageList
.
list
.
length
-
1
].
message
=
RobotList
[
RobotList
.
length
-
1
].
content
;
}
}
console
.
log
(
res
);
// message列表存到本地
}
catch
(
e
)
{
// 删除最后一个
MessageList
.
list
.
pop
();
console
.
log
(
e
);
}
};
// 提交前的校验
const
beforeSubmit
=
()
=>
{
let
params
:
any
=
{};
// 遍历整个列表
for
(
let
i
=
0
;
i
<
AdminData
.
list
.
length
;
i
++
)
{
let
item
=
AdminData
.
list
[
i
];
for
(
let
j
=
0
;
j
<
item
.
lists
.
length
;
j
++
)
{
let
it
=
item
.
lists
[
j
];
// 校验规则
let
message
=
Validationrules
(
it
.
rules
,
it
.
value
);
if
(
message
)
{
// 提示错误信息
show_message
(
message
);
return
;
}
else
{
// 添加params
params
[
it
.
name
]
=
it
.
value
;
}
}
}
onSubmit
(
params
);
};
onBeforeMount
(
async
()
=>
{
if
(
!
id
)
{
show_message
(
'禁止访问'
);
return
;
}
// 获取组件列表
await
getAdminComponent
();
});
...
...
@@ -167,9 +214,12 @@ onBeforeMount(async () => {
<
style
lang=
"less"
>
@import
'@/style/variables.less'
;
.custom-copywriting-generation
{
margin-top
:
@
page-margin-top
;
.custom-copywriting-generation-page
{
position
:
relative
;
height
:
100%
;
.custom-copywriting-generation
{
display
:
flex
;
padding-top
:
@
page-margin-top
;
.tip-box
{
width
:
50%
;
object-fit
:
contain
;
...
...
@@ -220,5 +270,6 @@ onBeforeMount(async () => {
margin-top
:
20px
;
}
}
}
}
</
style
>
src/pages/CreationRecord/components/CopywritingRecord.vue
0 → 100644
View file @
b1b30785
<
template
>
<div>
<TTable
class=
"reset-t-table"
row-key=
"index"
:data=
"RecordList.list"
:columns=
"columns"
:loading=
"loading"
>
<template
#
detail=
"
{ row }">
<div
class=
"detail-box"
v-for=
"item in row.detail"
:key=
"item.name"
>
<span>
{{
item
.
label
}}
:
</span>
<span>
{{
item
.
value
}}
</span>
</div>
</
template
>
<
template
#
download=
"{ row }"
>
<span
class=
"download-text"
>
查看
</span>
</
template
>
</TTable>
<div
class=
"custom-pagination"
>
<t-pagination
v-model=
"pageNum"
v-model:page-size=
"pageSize"
:total=
"total"
:pageSizeOptions=
"[]"
@
current-change=
"pageChange"
/>
</div>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
Table
as
TTable
}
from
'tdesign-vue-next'
;
import
CustomTTable
from
'@/components/custom/TTable.vue'
;
import
{
onBeforeMount
,
reactive
,
ref
}
from
'vue'
;
import
{
getGenerateRecords
}
from
'@/utils/api/scenes'
;
import
{
Pagination
as
TPagination
}
from
'tdesign-vue-next'
;
import
{
TASKTYPE
}
from
'@/utils/api/Task'
;
const
RecordList
=
reactive
({
// 绘图列表
list
:
[],
});
const
loading
=
ref
(
false
);
const
pageNum
=
ref
<
number
>
(
1
);
const
pageSize
=
ref
<
number
>
(
10
);
const
total
=
ref
<
number
>
(
0
);
// 文案记录
const
columns
=
[
{
title
:
'产品'
,
colKey
:
'title'
,
},
{
title
:
'详细'
,
colKey
:
'detail'
,
align
:
'center'
,
},
{
title
:
'消耗字符数'
,
colKey
:
'consumes_characters'
,
align
:
'center'
,
},
{
title
:
'操作'
,
colKey
:
'download'
,
align
:
'right'
,
},
];
const
pageChange
=
(
value
:
number
)
=>
{
pageNum
.
value
=
value
;
getLog
();
};
const
getLog
=
async
()
=>
{
try
{
loading
.
value
=
true
;
let
res
:
any
=
await
getGenerateRecords
({
page
:
pageNum
.
value
,
limit
:
pageSize
.
value
,
type
:
TASKTYPE
.
CHAT
,
});
if
(
res
.
code
==
0
)
{
RecordList
.
list
=
res
.
data
.
data
;
total
.
value
=
res
.
data
.
total
;
}
console
.
log
(
res
);
loading
.
value
=
false
;
}
catch
(
e
)
{
loading
.
value
=
false
;
console
.
log
(
e
);
}
};
onBeforeMount
(()
=>
{
getLog
();
});
</
script
>
<
style
lang=
"less"
>
@import
'@/style/variables.less'
;
.reset-t-table
{
background-color
:
transparent
;
min-height
:
500px
;
.t-table__content
{
background-color
:
transparent
;
}
thead
{
tr
{
background-color
:
transparent
;
th
{
border
:
none
;
background
:
#000000
;
color
:
white
;
font-size
:
@
font-size-16
;
font-weight
:
400
;
}
&
>
:first-child
{
border-top-left-radius
:
8px
;
border-bottom-left-radius
:
8px
;
}
&
>
:last-child
{
border-top-right-radius
:
8px
;
border-bottom-right-radius
:
8px
;
}
}
}
tbody
{
.t-table__empty-row
{
background-color
:
transparent
;
&:hover
{
background-color
:
transparent
;
}
.t-table__empty
{
color
:
white
;
}
}
tr
{
background
:
transparent
;
td
{
color
:
#ffffff
;
border-bottom
:
1px
solid
#464646
;
font-weight
:
400
;
font-size
:
@
font-size-14
;
.detail-box
{
text-align
:
start
;
}
.img
{
width
:
85px
;
height
:
85px
;
border-radius
:
8px
;
}
.download-text
{
font-weight
:
400
;
font-size
:
@
font-size-14
;
color
:
#00f9f9
;
cursor
:
pointer
;
}
}
}
}
}
.custom-pagination
{
padding
:
12px
0
;
.t-pagination__total
{
color
:
white
;
}
.t-is-current
{
background
:
#00f9f9
;
border-radius
:
2px
;
border
:
none
;
color
:
#000000
;
}
.t-pagination__btn
{
&
>
:nth-child(1)
{
color
:
#c9cdd4
;
}
}
}
</
style
>
src/pages/CreationRecord/components/MappingRecord.vue
View file @
b1b30785
<
template
>
<CustomTTable
class=
"mapping-record-table"
<div>
<TTable
class=
"reset-t-table"
row-key=
"index"
:data=
"RecordList.list"
:columns=
"columns"
:list=
"RecordList.list"
></CustomTTable>
:loading=
"loading"
>
<template
#
detail=
"
{ row }">
<div
class=
"detail-box"
v-for=
"item in row.detail"
:key=
"item.name"
>
<span>
{{
item
.
label
}}
:
</span>
<span>
{{
item
.
value
}}
</span>
</div>
</
template
>
<
template
#
size=
"{ row }"
>
<div
v-for=
"(item, index) in row.size"
:key=
"item"
>
<span
>
{{
item
}}
<template
v-if=
"index != 0"
>
,
</
template
>
</span>
</div>
</template>
<
template
#
url=
"{ row }"
>
<img
class=
"img"
:src=
"row.url"
alt=
""
/>
</
template
>
<
template
#
download=
"{ row }"
>
<span
class=
"download-text"
>
下载
</span>
</
template
>
</TTable>
<div
class=
"custom-pagination"
>
<t-pagination
v-model=
"pageNum"
v-model:page-size=
"pageSize"
:total=
"total"
:pageSizeOptions=
"[]"
@
current-change=
"pageChange"
/>
</div>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
CustomTTable
from
"@/components/custom/TTable.vue"
;
import
{
reactive
}
from
"vue"
;
import
{
Table
as
TTable
}
from
'tdesign-vue-next'
;
import
CustomTTable
from
'@/components/custom/TTable.vue'
;
import
{
onBeforeMount
,
reactive
,
ref
}
from
'vue'
;
import
{
getGenerateRecords
}
from
'@/utils/api/scenes'
;
import
{
Pagination
as
TPagination
}
from
'tdesign-vue-next'
;
import
{
TASKTYPE
}
from
'@/utils/api/Task'
;
const
RecordList
=
reactive
({
// 绘图列表
list
:
[],
});
const
loading
=
ref
(
false
);
const
pageNum
=
ref
<
number
>
(
1
);
const
pageSize
=
ref
<
number
>
(
10
);
const
total
=
ref
<
number
>
(
0
);
// 绘图记录
const
columns
=
[
{
title
:
"产品"
,
colKey
:
"name"
,
title
:
'产品'
,
colKey
:
'title'
,
},
{
title
:
"详细"
,
colKey
:
"packages"
,
align
:
"center"
,
className
:
"n_quantity"
,
title
:
'详细'
,
colKey
:
'detail'
,
align
:
'center'
,
width
:
'40%'
,
},
{
title
:
"尺寸"
,
colKey
:
"n_funds"
,
align
:
"center"
,
className
:
"n_funds"
,
title
:
'尺寸'
,
colKey
:
'size'
,
align
:
'center'
,
},
{
title
:
"数量"
,
colKey
:
"operation"
,
align
:
"right"
,
title
:
'数量'
,
colKey
:
'number'
,
align
:
'center'
,
},
{
title
:
"图片"
,
colKey
:
"img"
,
align
:
"center"
,
title
:
'图片'
,
colKey
:
'url'
,
align
:
'center'
,
},
{
title
:
"下载"
,
colKey
:
"download"
,
align
:
"right"
,
title
:
'下载'
,
colKey
:
'download'
,
align
:
'right'
,
},
];
const
pageChange
=
(
value
:
number
)
=>
{
pageNum
.
value
=
value
;
getLog
();
};
const
getLog
=
async
()
=>
{
try
{
loading
.
value
=
true
;
let
res
:
any
=
await
getGenerateRecords
({
page
:
pageNum
.
value
,
limit
:
pageSize
.
value
,
type
:
TASKTYPE
.
PAINTING
,
});
if
(
res
.
code
==
0
)
{
RecordList
.
list
=
res
.
data
.
data
;
total
.
value
=
res
.
data
.
total
;
}
console
.
log
(
res
);
loading
.
value
=
false
;
}
catch
(
e
)
{
loading
.
value
=
false
;
console
.
log
(
e
);
}
};
onBeforeMount
(()
=>
{
getLog
();
});
</
script
>
<
style
lang=
"less"
>
.mapping-record-table
{
@import
'@/style/variables.less'
;
.reset-t-table
{
background-color
:
transparent
;
min-height
:
500px
;
.t-table__content
{
background-color
:
transparent
;
}
thead
{
tr
{
background-color
:
transparent
;
th
{
border
:
none
;
background
:
#000000
;
color
:
white
;
font-size
:
@
font-size-16
;
font-weight
:
400
;
}
&
>
:first-child
{
border-top-left-radius
:
8px
;
border-bottom-left-radius
:
8px
;
}
&
>
:last-child
{
border-top-right-radius
:
8px
;
border-bottom-right-radius
:
8px
;
}
}
}
tbody
{
.t-table__empty-row
{
background-color
:
transparent
;
&:hover
{
background-color
:
transparent
;
}
.t-table__empty
{
color
:
white
;
}
}
tr
{
background
:
transparent
;
td
{
color
:
#ffffff
;
border-bottom
:
1px
solid
#464646
;
font-weight
:
400
;
font-size
:
@
font-size-14
;
.detail-box
{
text-align
:
start
;
}
.img
{
width
:
85px
;
height
:
85px
;
border-radius
:
8px
;
}
.download-text
{
font-weight
:
400
;
font-size
:
@
font-size-14
;
color
:
#00f9f9
;
cursor
:
pointer
;
}
}
}
}
}
.custom-pagination
{
padding
:
12px
0
;
.t-pagination__total
{
color
:
white
;
}
.t-is-current
{
background
:
#00f9f9
;
border-radius
:
2px
;
border
:
none
;
color
:
#000000
;
}
.t-pagination__btn
{
&
>
:nth-child(1)
{
color
:
#c9cdd4
;
}
}
}
</
style
>
src/pages/CreationRecord/index.vue
View file @
b1b30785
...
...
@@ -17,10 +17,7 @@
</div>
<template
v-if=
"is_first"
>
<div
v-show=
"DefaultTable == 'text'"
>
<CustomTTable
:columns=
"columns2"
:list=
"RecordList.textlist"
></CustomTTable>
<CopywritingRecord></CopywritingRecord>
</div>
</
template
>
</div>
...
...
@@ -28,11 +25,12 @@
</template>
<
script
lang=
"ts"
setup
>
import
CustomTTable
from
"@/components/custom/TTable.vue"
;
import
MappingRecord
from
"./components/MappingRecord.vue"
;
import
{
reactive
,
ref
}
from
"vue"
;
import
CustomTTable
from
'@/components/custom/TTable.vue'
;
import
MappingRecord
from
'./components/MappingRecord.vue'
;
import
CopywritingRecord
from
'./components/CopywritingRecord.vue'
;
import
{
reactive
,
ref
}
from
'vue'
;
// 默认展示绘图记录
const
DefaultTable
=
ref
<
"img"
|
"text"
>
(
"img"
);
const
DefaultTable
=
ref
<
'img'
|
'text'
>
(
'img'
);
const
is_first
=
ref
(
false
);
const
RecordList
=
reactive
({
...
...
@@ -43,37 +41,37 @@ const RecordList = reactive({
});
const
label_list
=
[
{
label
:
"绘图记录"
,
value
:
"img"
,
label
:
'绘图记录'
,
value
:
'img'
,
},
{
label
:
"文案记录"
,
value
:
"text"
,
label
:
'文案记录'
,
value
:
'text'
,
},
];
// 文案记录
const
columns2
=
[
{
title
:
"账号"
,
colKey
:
"name"
,
title
:
'账号'
,
colKey
:
'name'
,
},
{
title
:
"套餐"
,
colKey
:
"packages"
,
align
:
"center"
,
className
:
"n_quantity"
,
title
:
'套餐'
,
colKey
:
'packages'
,
align
:
'center'
,
className
:
'n_quantity'
,
},
{
title
:
"状况"
,
colKey
:
"n_funds"
,
align
:
"center"
,
className
:
"n_funds"
,
title
:
'状况'
,
colKey
:
'n_funds'
,
align
:
'center'
,
className
:
'n_funds'
,
},
{
title
:
"到期时间"
,
colKey
:
"operation"
,
align
:
"right"
,
title
:
'到期时间'
,
colKey
:
'operation'
,
align
:
'right'
,
},
];
const
changeTable
=
(
item
:
any
)
=>
{
...
...
@@ -83,9 +81,9 @@ const changeTable = (item: any) => {
</
script
>
<
style
lang=
"less"
>
@import
"@/style/variables.less"
;
@import
'@/style/variables.less'
;
.custom-creation-record
{
margin
-top
:
@
page-margin-top
;
padding
-top
:
@
page-margin-top
;
.label-box
{
font-weight
:
600
;
font-size
:
@
font-size-18
;
...
...
src/pages/Detail/index.vue
View file @
b1b30785
<
template
>
<div
class=
"custom-product-detail"
>
<ModuleCard
label=
"亚马逊工具"
:list=
"ProductList.list"
></ModuleCard>
<Animation
v-show=
"loading"
></Animation>
<ModuleCard
:label=
"parent_title"
:list=
"ProductList.list"
@
change=
"onChange"
></ModuleCard>
<CustomLoading
v-show=
"loading"
></CustomLoading>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
useRoute
}
from
'vue-router'
;
import
{
useRoute
,
useRouter
}
from
'vue-router'
;
import
{
onMounted
,
reactive
,
ref
}
from
'vue'
;
import
{
show_message
}
from
'@/utils/tdesign_tool'
;
import
ModuleCard
from
'@/components/modulecard.vue'
;
import
Animation
from
'@/components/Animation.vue'
;
import
{
getScenesList
}
from
'@/utils/api/scenes'
;
import
CustomLoading
from
'@/components/custom/loading2.vue'
;
import
{
TASKTYPE
}
from
'@/utils/api/Task'
;
// 会带一个id
const
route
=
useRoute
();
const
params_id
=
route
.
params
.
id
;
const
router
=
useRouter
();
const
params_id
=
route
.
query
.
id
;
const
loading
=
ref
(
false
);
// 产品大标题
const
parent_title
=
ref
(
''
);
// 产品列表
const
ProductList
=
reactive
({
list
:
[],
});
// 这里跳转传id
const
onChange
=
(
item
:
any
)
=>
{
console
.
log
(
item
);
let
path
=
''
;
if
(
item
.
type
==
TASKTYPE
.
CHAT
)
{
// 文案
path
=
'/CopywritingGeneration'
;
}
else
if
(
item
.
type
==
TASKTYPE
.
PAINTING
)
{
// 绘图
path
=
'/ImageGeneration'
;
}
if
(
path
)
{
const
url
=
router
.
resolve
({
path
:
path
,
query
:
{
id
:
item
.
id
,
},
});
window
.
open
(
url
.
href
);
}
};
// 获取当前分类所有产品
const
getallproduct
=
()
=>
{
const
getallproduct
=
async
()
=>
{
try
{
if
(
!
params_id
)
{
if
(
typeof
params_id
==
'undefined'
)
{
show_message
(
'没有类目id'
);
return
;
}
// let res: any = await ddd();
// console.log(res);
loading
.
value
=
true
;
let
res
:
any
=
await
getScenesList
(
params_id
,
'parent'
);
if
(
res
.
code
==
0
)
{
parent_title
.
value
=
res
.
data
[
0
].
parent_title
;
ProductList
.
list
=
res
.
data
;
}
console
.
log
(
res
);
loading
.
value
=
false
;
}
catch
(
e
)
{
console
.
log
(
e
);
loading
.
value
=
false
;
}
};
onMounted
(()
=>
{
// 获取数据
getallproduct
();
// 假数据生成
for
(
let
i
=
0
;
i
<
20
;
i
++
)
{
ProductList
.
list
.
push
({
img
:
new
URL
(
'../../assets/img/clothes.jpeg'
,
import
.
meta
.
url
).
href
,
title
:
'亚马逊工具'
,
content
:
'你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好'
,
});
}
});
</
script
>
<
style
lang=
"less"
>
.custom-product-detail
{
padding-bottom
:
40px
;
box-sizing
:
border-box
;
height
:
100%
;
position
:
relative
;
.custom-recommend
{
margin-top
:
0
;
padding-top
:
30px
;
}
}
</
style
>
src/pages/Home/components/HomeSwiper/swiper.vue
View file @
b1b30785
...
...
@@ -94,6 +94,9 @@ const goDetail = (item: any) => {
console
.
log
(
item
);
const
url
=
router
.
resolve
({
path
:
'Detail'
,
query
:
{
id
:
item
.
id
,
},
});
window
.
open
(
url
.
href
);
};
...
...
src/pages/Home/index.less
View file @
b1b30785
@import '@/style/variables.less';
.swiper-box {
margin: @page-margin-top 0 30px 0;
margin-top: 0;
padding-top: @page-margin-top;
}
src/pages/Home/index.tsx
View file @
b1b30785
...
...
@@ -2,27 +2,48 @@ import { defineComponent, onMounted, reactive } from 'vue';
import
HomeSwiper
from
'./components/HomeSwiper/swiper.vue'
;
import
'./index.less'
;
import
ModuleCard
from
'@/components/modulecard.vue'
;
import
{
getScenariosRecommend
}
from
'@/utils/api/scenes'
;
import
{
useRouter
}
from
'vue-router'
;
export
default
defineComponent
({
setup
()
{
const
router
=
useRouter
();
const
CardList
=
reactive
({
list
:
[]
as
any
,
});
onMounted
(()
=>
{
// 创建测试列表
for
(
let
i
=
0
;
i
<
21
;
i
++
)
{
CardList
.
list
.
push
({
img
:
new
URL
(
'../../assets/img/clothes.jpeg'
,
import
.
meta
.
url
).
href
,
title
:
'亚马逊产品文案生成'
,
content
:
'1111121111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'
,
const
getRecommend
=
async
()
=>
{
try
{
let
res
:
any
=
await
getScenariosRecommend
();
if
(
res
.
code
==
0
)
{
CardList
.
list
=
res
.
data
;
}
console
.
log
(
res
.
data
);
}
catch
(
e
)
{
console
.
log
(
e
);
}
};
const
onChange
=
(
item
:
any
)
=>
{
if
(
item
.
type
==
0
)
{
// 文案生成
const
url
=
router
.
resolve
({
path
:
'/CopywritingGeneration'
,
// path: '/ImageGeneration',
});
window
.
open
(
url
.
href
);
}
};
onMounted
(()
=>
{
// 获取推荐数据
getRecommend
();
});
return
()
=>
(
<
div
>
<
div
class=
"swiper-box"
>
<
HomeSwiper
></
HomeSwiper
>
<
ModuleCard
label=
"推荐工具"
list=
{
CardList
.
list
}
></
ModuleCard
>
<
ModuleCard
label=
"推荐工具"
list=
{
CardList
.
list
}
onChange=
{
onChange
}
></
ModuleCard
>
</
div
>
</
div
>
);
...
...
src/pages/ImageGeneration/components/GenerateResult/index.less
View file @
b1b30785
@import '@/style/variables.less';
.empty-box,
.loading-box {
.img-res-status {
display: flex;
justify-content: center;
align-items: center;
.empty-box,
.loading-box {
display: flex;
flex-direction: column;
align-items: center;
...
...
@@ -9,19 +13,17 @@
font-size: @font-size-16;
color: #888fa1;
}
}
.loading-box {
}
.load-success-box {
}
.load-success-box {
padding: 0 20px;
height: 100%;
display: flex;
flex-direction: column;
width: 100%;
.result-img-box {
padding-top: 100px
;
padding: 100px 0 20px 0
;
display: flex;
justify-content: space-between
;
justify-content: center
;
align-items: center;
flex-wrap: wrap;
row-gap: 20px;
...
...
@@ -49,4 +51,5 @@
}
}
}
}
}
src/pages/ImageGeneration/components/GenerateResult/index.tsx
View file @
b1b30785
...
...
@@ -36,7 +36,7 @@ export default defineComponent({
{
props
.
list
?
props
.
list
.
map
((
item
:
any
)
=>
(
<
div
class=
"result-img"
>
<
img
class=
"img"
src=
{
item
.
img
}
alt=
""
/>
<
img
class=
"img"
src=
{
item
}
alt=
""
/>
</
div
>
))
:
''
}
...
...
@@ -50,13 +50,18 @@ export default defineComponent({
// 判断当前展示的模块
const
CurrentModule
=
()
=>
{
if
(
true
)
{
// return EmptyHTML();
// return LoadingHTML();
// return LoadSuccessHTML();
const
{
status
}
=
props
;
if
(
status
==
''
)
{
// 未开始
return
EmptyHTML
();
}
else
if
(
status
==
'loading'
)
{
return
LoadingHTML
();
}
else
{
return
LoadSuccessHTML
();
}
};
return
()
=>
<
div
>
{
CurrentModule
()
}
</
div
>;
return
()
=>
<
div
class=
"img-res-status"
>
{
CurrentModule
()
}
</
div
>;
},
});
src/pages/ImageGeneration/components/upload/index.less
View file @
b1b30785
...
...
@@ -73,6 +73,11 @@
font-size: @font-size-15;
color: #8b8b8b;
}
.custom-t-progress {
.t-progress__info {
color: #00f9f9;
}
}
}
.custom-UploadSuccess-stauts {
display: flex;
...
...
src/pages/ImageGeneration/components/upload/index.tsx
View file @
b1b30785
import
{
computed
,
defineComponent
,
reactive
,
ref
}
from
'vue'
;
import
{
defineComponent
,
reactive
,
ref
,
watch
}
from
'vue'
;
import
'./index.less'
;
import
UploadTip
from
'@/assets/svg/upload/uploadTip2.svg'
;
import
{
...
...
@@ -17,16 +17,12 @@ import { v4 } from 'uuid';
export
default
defineComponent
({
props
:
{
modelValue
:
String
,
config
:
Object
as
any
,
num
:
Number
,
},
emits
:
[
'update:modelValue'
],
setup
(
props
,
{
emit
})
{
const
store
=
useStore
();
// 后台配置的地址
const
adminConfigUrl
=
computed
(()
=>
store
.
getters
[
'user/getadminConfig'
]);
// 上传策略
const
uploadStrategy
=
computed
(
()
=>
store
.
getters
[
'user/getuploadStrategy'
]
);
const
files
=
ref
([]);
// 文件地址
const
Curfile
=
reactive
({
...
...
@@ -53,7 +49,7 @@ export default defineComponent({
};
const
beforeUpload
=
(
file
:
File
)
=>
{
try
{
let
config
=
uploadStrategy
.
value
.
config
;
const
{
config
}
=
props
;
let
config_len
=
Object
.
keys
(
config
).
length
;
if
(
!
config_len
)
{
show_message
(
'无法上传,请尝试刷新页面'
);
...
...
@@ -89,45 +85,6 @@ export default defineComponent({
emit
(
'update:modelValue'
,
Curfile
.
url
);
MessagePlugin
.
warning
(
'上传失败'
);
};
// 内网上传-Intranet
const
IntranetUpload
=
(
file
:
any
)
=>
{
openpercentage
();
return
new
Promise
((
resolve
)
=>
{
let
uuid
=
v4
();
// 上传中状态
Curfile
.
status
=
1
;
let
url
=
''
;
if
(
import
.
meta
.
env
.
MODE
==
'production'
)
{
// 线上地址使用完整url
url
=
adminConfigUrl
.
value
+
'video/'
+
uuid
+
'.png'
;
// url = `http://192.168.1.19:5000/video/` + uuid + '.png';
}
else
if
(
import
.
meta
.
env
.
MODE
==
'app'
)
{
// app
url
=
'/video/'
+
uuid
+
'.png'
;
}
else
{
// 本地
url
=
'/video/'
+
uuid
+
'.png'
;
}
setTimeout
(()
=>
{
request
.
put
(
url
,
file
[
0
].
raw
).
then
((
res
:
any
)
=>
{
// resolve 参数为关键代码
if
(
res
==
200
)
{
let
url
=
adminConfigUrl
.
value
+
'video/'
+
uuid
+
'.png'
;
UploadSuccessCallback
(
uuid
,
url
);
//
Curfile
.
uploadStatus
=
true
;
resolve
({
status
:
'success'
,
response
:
{
url
:
Curfile
.
url
},
});
}
else
{
UploadErrorCallback
();
Curfile
.
uploadStatus
=
false
;
}
});
},
1000
);
});
};
// 外网上传-func
const
ExtranetUpload
=
(
file
:
any
)
=>
{
openpercentage
();
...
...
@@ -136,7 +93,7 @@ export default defineComponent({
// 上传中状态
Curfile
.
status
=
1
;
let
url
=
''
;
const
{
config
}
=
uploadStrategy
.
value
;
const
{
config
}
=
props
;
url
=
'https://'
+
config
.
host
;
setTimeout
(()
=>
{
let
formData
=
new
FormData
();
...
...
@@ -216,9 +173,11 @@ export default defineComponent({
return
(
<
div
class=
"custom-uploading-stauts"
>
<
TProgress
class=
"custom-t-progress"
theme=
"circle"
percentage=
{
percentage
.
value
}
size=
{
'small'
}
color=
{
'#00f9f9'
}
/>
<
div
class=
"uploading-title"
>
正在上传
</
div
>
</
div
>
...
...
@@ -243,6 +202,12 @@ export default defineComponent({
return
UploadSuccess
();
}
};
watch
(
()
=>
props
.
num
,
(
v
)
=>
{
Curfile
.
status
=
0
;
}
);
return
()
=>
(
<
div
class=
"custom-real-upload custom-upload-line"
>
<
div
class=
"real-upload-content"
>
...
...
src/pages/ImageGeneration/index.vue
View file @
b1b30785
<
template
>
<div
class=
"custom-copywriting-generation"
>
<div
class=
"generation-box"
v-show=
"!loading"
>
<div
class=
"interaction-form"
>
<div
class=
"basic-info"
v-for=
"item in AdminData.list"
:key=
"item.name"
>
<div
class=
"label"
>
*
{{
item
.
name
}}
</div>
...
...
@@ -27,14 +28,18 @@
:maxlength=
"it.maxlength"
></CustomTextArea>
</
template
>
<
template
v-else-if=
"it.component_type == 'radio
group_size'"
>
<
template
v-else-if=
"it.component_type == 'radio_
group_size'"
>
<ImgSizeRadioGroupVue
:list=
"it.options"
v-model=
"it.value"
></ImgSizeRadioGroupVue>
</
template
>
<
template
v-else-if=
"it.component_type == 'upload'"
>
<CustomUpload
v-model=
"it.value"
></CustomUpload>
<CustomUpload
v-model=
"it.value"
:config=
"StrategyConfig"
:num=
"AdminData.reset_num"
></CustomUpload>
</
template
>
<
template
v-else-if=
"it.component_type == 'custom-number'"
>
<CustomInput
...
...
@@ -49,38 +54,31 @@
</div>
<div
class=
"confirm-box"
>
<div
class=
"pay-num"
>
<div>
余额:0/5000
</div>
<div>
实付:100
</div>
<!--
<div>余额:0/5000</div>
<div>实付:100</div>
-->
</div>
<CustomResetButton
@
click=
"onReset"
width=
"20%"
>
重置
</CustomResetButton>
<CustomResetButton
@
click=
"onReset"
width=
"50%"
bold
<CustomResetButton
@
click=
"onReset"
width=
"20%"
>
重置
</CustomResetButton
>
<CustomResetButton
@
click=
"beforeSubmit"
width=
"50%"
bold
>
生成图片
</CustomResetButton
>
</div>
</div>
<div
class=
"generate-result"
>
<CustomGenerateResult
status=
"success"
:list=
"[
{
img: 'data:image/jpeg;base64,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',
},
{
img: 'data:image/jpeg;base64,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',
},
{
img: 'data:image/jpeg;base64,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',
},
{
img: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPEBAQEBAPDw8QEA4NDQ8PDRANDw8OFRIWFhURFRUYHSogGBolGxUTITEhJSorLi4wFx8zODUsNygtLjcBCgoKDg0OGxAQGC0lHh0rKy0tKy0rLTIrLSstLS0tLSstLy03NS03Ky0tLS0tLjArKy0rLSsrLS0tNystLS0tLf/AABEIAKgBLAMBIgACEQEDEQH/xAAbAAEAAwADAQAAAAAAAAAAAAAAAQIDBAUHBv/EADIQAAIBAwQBAwIEBgIDAAAAAAABAgMEEQUSITFRBhNBYXEUIjKRByNCgaHRgrFUY3L/xAAaAQEBAQEBAQEAAAAAAAAAAAAAAQMCBAUG/8QAIxEBAAICAgEEAwEAAAAAAAAAAAECAxESIQQTMVFhMkGBFP/aAAwDAQACEQMRAD8A8bAB084AAJSNSlNF2ATyUmi6WCJrgCKZcpTJm/8AsBJfJYhMkClP5Jn0RT+SZ9AIdFisOic8gU28/wCTQgZ5AifRSK5Lz6IpoCzCYaCQGc1yQXqIoBqjOfZojOfYE0y0+itMtPoBBcETZMHwROOQIhIuysYlmwK0y5SmTNgGucliEyQMSCSAAAAAADSLREpeCgAspMvuRkANIMibKAC8JFtyMgBeDJm+DMAaRksESlyigA13IrGXZQAaTfBKaMgBeUvAjIoANW0ZkADVSRSb5KgC8GTKSwZgCYvBopoyAGrkikpZKgC8GTNmYAvCRbcjIASQAAAAAAAAAAAAAAAAAABOCcAVBfAwE2oC2CMBUAlo09r8u7K7xjK3ft4+pUmdMgWUCMEXaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALJEIsEkJwSkWSK5mVMDBqojaE5MsEGjiVaCxKjRGS7RRkdQ5VC42xlHEWpbctxTksPPD+C8bKcoSqqL9uLUZTx+VSecJv+zOHE5dGpLG1N4eMrPDZYZXiY7q4solTsdQ06pR2qpFwcoqpHPGYvpnAkhMad0vFo3EqAAjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWRZIhFkVzKyRrGJSCOVRgVle2kRpCVI+p9N6C7qTSaikt0m/hFPUGiu2m4PD4TTXTTNPTnjt87/fj9X0t9vlJQM5I51WmcacTOYe+l9uO0ZyN3EymiNqyojkUuzGETkUo8hLy5tWnUqQ3tSlFYjueWl4WTrakTvI31VUHQy/alJTcccOWMZOmqrk6swwTbuJ/jjsgtIqcPWAAAAAAAAAAAAAAAAAAAAAAAAAAAAALouZxNEVzLWmcugcODOVRZYefJD6v05fVKUl7bw3x1nP0wdp6jsq7/AJtZfq4zxx9OOj5nTLpwkmu0019z7Kd/Vv4qnGMePzPHGX5eXx2eqkxNdPznl1tizxkiI1+5fB16XJwqtM+j1XT5UpOMlhrs6erSMbVfWwZotETEutcSHA5UqRT2jPT2RdxVA5FCmXjROy0+Mac4SqQ3QTTlHrK8FiHGXLqOmlbUl+GVD2oJqe/3cfnfH6c+D52s+TvfUN1SqVZSow9uDxiGeuDoahbz258SsceWtb719sJFS0ipm+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlM0iZFosqTDZG9ORx0y8WGVo27KhUPo9B1uVvLMcPKw0+mj5GnM5VKsaVtMdvB5Hj1yVmto6ff2du9RqTlKSjxl4WfokkdJqGlOFWVOP5mm48c5OustTnT5jJxflPDO00bXPZqqpJbu8pvyvJtyrb3fK9DNhmZp3ER1Dqq1lKLw1h9YwZysmmso7u/1qNW495xWMp7e1heR6j12FxKMowUNqx3ls5mte+29M2eZrE0947+nEvNEqW8IVJxxGfMeU/r/AGGt6vSq0aUIUo05U44lJYzPrn/H+ThX+tVasIwnNyjDiKb6R01Wsc2tEfi9GHxr31bL7xM+yleocWTLzkYzZjL61K6VZABGoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEkAC8ZGkZGJKkVzMOQpGkahxlIupBnNXMjWLqucFSJ3F2znHDnOuZyrnF3kOQ2RihrOqZSkVcjOUiNa0TKRQZII0iAABQAAAAAAAAAAAAAAAAAAAAAAAAAAel0NFprT7advptreW1WwnXv9Qq3St61ve5lvgqrl/L2YjiO17s/c5EtFsVoSru3ozrrTPxMvbpSV578q7hC59zel7Ucfmjhvo8t+nw2m18Nrpjc/L6x38ePsTTvl9PUvVvpKFR6Xb2ttCirqVlCdenZSpvM6G6o3ce41PjfJx2LG3t4OB/EDT7S1q2l/Y0bGrayncWlShCrG8tXWpSlslU2S/VOlOE9ueHH5+fPd78vjrl8EZ4x8d4+MjRyema5p1o9R1q3jaWtKlY6XeTtlSpuL95RoyjVk88zW+STWODja1pllDTJ6rCjRSvLSztbWiuI0NRUpxu5wj/TtjRyn5mzzzc/L5757Gf28fBdHN6J/FDR6VrRtHQtadGnONu5VYWUqW+crdSa/Ee41Uy9z27FjHbwZXPpyhjQKtSk6Njc0LSGo3UU4QdadWWVOf8ATJxSWfhc/B8C5N9tv7tshyeMZePGeP2Gk5R8PTfVXpzdRUZWFtp15PU4WOmQt5Nfi7aeVvnHdLdh7H7nGcnM9UemLGNzpUrWNvK3Wo2+k38aVaFdVH7kMTq7W9spRVVNPno8m3Ph5eUkk89JdJeApPy/Pfz5GjcfD1zUfT9srmxVext7OrU1t2dO3p5jG80vLxWnScnjnas8Z3fYt6c9N6dcQs6dWnThcVNUv/blJfy69C3rx32k/vTlJx+tPHzz5Dl5zl5855/cZfl8PK56fkml5R8PXfSfpu0qwTha2tzvvNQo39SvGdX8FTp1EqFKKjOLpKUHKXu8424+UfE+lNEo3Oq+xKcJWVCtcV69VzSpOyoSlLc5Sf6JJRWX8TyfMefqsP6rw/IT/wBP7eC6TlD1dentPp6lWrVKFKpptXR6+pQp0Kka1OlUp7I1oUakXhyjKM2mn/WjHVPTFlQnKnCNGvCPpq8vqVeK4rV41Je1df8A3t2nl25+X8rvz2Mvy+sd/Hgml5fT2nSPRmm1ZaVcThSUIWdjHULf/wAm4uoU429Rx+cznWbf/qR1PpH0lZ1YXv4lW8J3l5d2Gme7Wp0p0VSVTFahGTzN+7KjDC8Hlm5+X8fL+Ohl8cvjrnoujk+00726ej30qtjZyurW5o2Sq1KMnWXvOrvcnu5nFrEX8bV2d5aaBaur/KtaFxdx0PTbu0sqnFK5uqkV71WUcr3JJc7c8nl+X5fPL57Yz08vKxh55WOsDRyetUtC0yNzdfi7anSUdGo3V/b0JOasLydVRqOly9slFqW3Lxn6nyP8SdGo2NxaUKPtNLTbOdWpS/RXrN1FKv8A8tqZ8nnvvnvnv7jP+l9vA0k26QAA5AAAAAAAADSn0ZmlPoCwYlHJSUcAWh0SRDoSjkCWVp9FZRwWp9AWBEo5KSjgC0OixWn0TKOQJfRnGOSZRwWh0BKQaKzZVTAmUcF0UcygG2AEZz7Aso5bLFKbLtAGjOSwWafwyjYEAAAAAAAAAAAAAAAAAACWXp9AATLPwVeQALQ6E5YAAo5ZLU+iQAm8FHLJAAvT6Jln4AAq8loPgABOOSFDyAAlFIzAA2RnPsABGOS3K+oAFkUqAAUAAAAAAAAAAAAAAAAAAH//2Q==',
},
]"
:status=
"AdminData.status"
:list=
"AdminData.callback_list"
></CustomGenerateResult>
</div>
</div>
<CustomLoading
v-show=
"loading"
></CustomLoading>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
CustomLoading
from
'@/components/custom/loading2.vue'
;
import
CustomSelect
from
'@/components/custom/Select.vue'
;
import
CustomTextArea
from
'@/components/custom/textarea.vue'
;
import
CustomInput
from
'@/components/custom/input/index.vue'
;
...
...
@@ -88,152 +86,60 @@ import CustomResetButton from '@/components/custom/resetbutton.vue';
import
CustomGptMessage
from
'@/components/custom/gptmessage.vue'
;
import
CustomGenerateResult
from
'./components/GenerateResult'
;
import
CustomUpload
from
'./components/upload'
;
import
{
onBeforeMount
,
reactive
}
from
'vue'
;
import
{
onBeforeMount
,
onBeforeUnmount
,
reactive
,
ref
,
watch
}
from
'vue'
;
import
ImgSizeRadioGroupVue
from
'@/components/custom/ImgSizeRadioGroup.vue'
;
import
CustomRadioGroup
from
'@/components/custom/RadioGroup.vue'
;
import
{
getScenesList
,
useUploadStrategy
,
useSubmitConversationImage
,
useImageCallback
,
}
from
'@/utils/api/scenes'
;
import
{
FormExample2
,
CustomNum
}
from
'@/utils/api/Task'
;
import
{
Validationrules
}
from
'@/utils/tool'
;
import
{
useRoute
}
from
'vue-router'
;
import
{
show_message
}
from
'@/utils/tdesign_tool'
;
const
imgs
=
{
tips
:
new
URL
(
'../../assets/img/tips.png'
,
import
.
meta
.
url
).
href
,
};
// 后台配置的输入类型--input-select-textarea
// type-1是input,2是select,3是长文本输入
//
const
loading
=
ref
(
false
);
const
route
=
useRoute
();
const
id
=
route
.
query
.
id
;
// 定时器
let
IntervalImg
:
any
=
null
;
// 上传策略状态
const
StrategyStatus
=
ref
(
false
);
// 上传策略
const
StrategyConfig
=
ref
({});
const
AdminData
=
reactive
({
list
:
[],
});
// gpt-消息列表
const
MessageList
=
reactive
({
list
:
[
{
user
:
'user'
,
message
:
'早上好,早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好,早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好早上好'
,
},
{
user
:
'user'
,
message
:
''
,
},
// 回调图片列表
callback_list
:
[
'http://ai-gpt.test/admin/images/155bf4db0b486817071b3fe4733efb94.jpg'
,
'http://ai-gpt.test/admin/images/155bf4db0b486817071b3fe4733efb94.jpg'
,
'http://ai-gpt.test/admin/images/155bf4db0b486817071b3fe4733efb94.jpg'
,
'http://ai-gpt.test/admin/images/155bf4db0b486817071b3fe4733efb94.jpg'
,
],
/**
* loading-生成中
* success-结束
*/
status
:
''
,
reset_num
:
1
,
});
const
scenario_id
=
ref
();
// 获取后台配置的组件
const
getAdminComponent
=
async
()
=>
{
try
{
// let res:any = await ddd();
// if(res.data){
// }
let
list
=
[
{
name
:
'基础填写'
,
value
:
'name'
,
lists
:
[
{
type
:
'text'
,
name
:
'url'
,
label
:
'链接'
,
value
:
null
,
span
:
24
,
placeholder
:
'输入链接'
,
// component_type: 'input',
},
// 下拉选择
{
type
:
'select'
,
options
:
[
{
label
:
'第一个'
,
value
:
1
,
},
{
label
:
'第二个'
,
value
:
2
,
},
],
// 可设置默认值
value
:
1
,
},
],
},
{
name
:
'详细描述'
,
value
:
'2'
,
lists
:
[
{
// 长文本输入框
type
:
'textarea'
,
name
:
'url'
,
label
:
'链接'
,
value
:
null
,
span
:
24
,
maxRows
:
'5'
,
minRows
:
'5'
,
placeholder
:
'详细描述产品细节,生成的文案更加完美。'
,
maxlength
:
100
,
// component_type: 'input',
},
],
},
// 图片尺寸
{
name
:
'图片尺寸'
,
value
:
'3'
,
lists
:
[
{
// 单选按钮组
type
:
'radiogroup_size'
,
name
:
'img_size'
,
value
:
'1600x1600'
,
span
:
24
,
placeholder
:
'详细描述产品细节,生成的文案更加完美。'
,
// component_type: 'input',
options
:
[
{
size
:
'1600x1600'
,
label
:
'亚马逊产品图尺寸'
,
value
:
'1600x1600'
,
},
{
size
:
'600x180'
,
label
:
'亚马逊a+主图'
,
value
:
'600x180'
,
},
{
type
:
'custom'
,
label
:
'自定义'
,
value
:
''
,
value1
:
''
,
value2
:
''
,
},
],
},
],
},
// 上传图片
{
name
:
'上传图片'
,
value
:
'4'
,
lists
:
[
{
// 单选按钮组
type
:
'upload'
,
name
:
'upload'
,
value
:
null
,
span
:
24
,
},
],
},
// 生成数量
{
name
:
'生成数量'
,
value
:
'5'
,
lists
:
[
{
type
:
'custom-number'
,
name
:
'num'
,
value
:
null
,
span
:
24
,
placeholder
:
'自定义'
,
},
],
},
];
loading
.
value
=
true
;
console
.
log
(
JSON
.
stringify
(
FormExample2
));
let
res
:
any
=
await
getScenesList
(
id
,
'id'
);
if
(
res
.
code
==
0
)
{
// 取id
scenario_id
.
value
=
res
.
data
.
id
;
let
list
=
res
.
data
.
form
;
list
.
push
(
CustomNum
);
// 修改数据
list
.
forEach
((
item
:
any
)
=>
{
item
.
lists
.
forEach
((
it
:
any
)
=>
{
...
...
@@ -244,12 +150,14 @@ const getAdminComponent = async () => {
}
else
if
(
it
.
type
==
'textarea'
)
{
// 多行文本输入框
it
.
component_type
=
'textarea'
;
}
else
if
(
it
.
type
==
'radio
group_size'
)
{
}
else
if
(
it
.
type
==
'radio_
group_size'
)
{
// 单选按钮
it
.
component_type
=
'radio
group_size'
;
it
.
component_type
=
'radio_
group_size'
;
}
else
if
(
it
.
type
==
'radiogroup'
)
{
it
.
component_type
=
'radiogroup'
;
}
else
if
(
it
.
type
==
'upload'
)
{
// 获取上传策略
StrategyStatus
.
value
=
true
;
// 上传
it
.
component_type
=
'upload'
;
}
else
if
(
it
.
type
==
'custom-number'
)
{
...
...
@@ -259,32 +167,172 @@ const getAdminComponent = async () => {
if
(
!
it
.
value
)
{
it
.
value
=
''
;
}
// 记得要push一个生成数量
});
});
AdminData
.
list
=
list
;
console
.
log
(
AdminData
.
list
);
}
loading
.
value
=
false
;
}
catch
(
e
)
{
console
.
log
(
e
);
loading
.
value
=
false
;
}
};
const
getStrategy
=
async
()
=>
{
try
{
let
res
:
any
=
await
useUploadStrategy
();
if
(
res
.
code
==
0
)
{
StrategyConfig
.
value
=
res
.
data
;
}
}
catch
(
e
)
{
console
.
log
(
e
);
}
};
watch
(
()
=>
StrategyStatus
.
value
,
(
v
)
=>
{
if
(
v
)
{
// 获取上传策略
getStrategy
();
}
}
);
// 获取图片回调
const
ImageCallback
=
async
(
uuid
:
string
)
=>
{
try
{
let
res
:
any
=
await
useImageCallback
({
// key: uuid,
key
:
'generate_image:beacfaacc2fb819c17bb92e2495deee7'
,
});
if
(
res
.
code
==
0
)
{
if
(
res
.
data
.
image
)
{
AdminData
.
status
=
'success'
;
if
(
res
.
data
.
image
.
length
>
AdminData
.
callback_list
.
length
)
{
AdminData
.
callback_list
=
res
.
data
.
image
;
}
if
(
res
.
data
.
image
.
length
==
4
)
{
// 关闭定时器
closeInterval
();
}
}
}
console
.
log
(
res
);
}
catch
(
e
)
{
console
.
log
(
e
);
}
};
// 开启定时器
const
openInterval
=
(
uuid
:
string
)
=>
{
IntervalImg
=
window
.
setInterval
(()
=>
{
// 请求接口
ImageCallback
(
uuid
);
},
2000
);
};
// 关闭定时器
const
closeInterval
=
()
=>
{
if
(
IntervalImg
)
{
window
.
clearInterval
(
IntervalImg
);
clearInterval
(
IntervalImg
);
IntervalImg
=
null
;
}
};
// 重置
const
onReset
=
()
=>
{
console
.
log
(
'111'
);
// 遍历整个列表,清空value
AdminData
.
list
.
forEach
((
item
:
any
)
=>
{
item
.
lists
.
forEach
((
it
:
any
)
=>
{
if
(
it
.
value
)
{
it
.
value
=
''
;
}
});
});
// 恢复默认状态
AdminData
.
status
=
''
;
AdminData
.
callback_list
=
[];
// 初始化图片状态
AdminData
.
reset_num
+=
1
;
};
// 提交--ai图片任务
const
onSubmit
=
async
(
params
:
any
)
=>
{
try
{
let
res
:
any
=
await
useSubmitConversationImage
({
scenario_id
:
scenario_id
.
value
,
parameters
:
params
,
});
if
(
res
.
code
==
0
)
{
// 开启定时器
openInterval
(
res
.
data
.
uuid
);
AdminData
.
status
=
'loading'
;
}
console
.
log
(
res
);
}
catch
(
e
)
{
console
.
log
(
e
);
}
};
// 提交前的校验
const
beforeSubmit
=
()
=>
{
let
params
:
any
=
{};
// 遍历整个列表
for
(
let
i
=
0
;
i
<
AdminData
.
list
.
length
;
i
++
)
{
let
item
=
AdminData
.
list
[
i
];
for
(
let
j
=
0
;
j
<
item
.
lists
.
length
;
j
++
)
{
let
it
=
item
.
lists
[
j
];
// 校验规则
let
message
=
Validationrules
(
it
.
rules
,
it
.
value
,
it
.
name
);
if
(
message
)
{
// 提示错误信息
show_message
(
message
);
return
;
}
else
{
// 类型为图片尺寸且当前选择的是自定义
if
(
it
.
type
==
'radio_group_size'
&&
it
.
value
==
''
)
{
// 找到options列表里的自定义模块
let
customObj
=
it
.
options
.
find
((
opt
:
any
)
=>
opt
.
type
==
'custom'
);
if
(
customObj
)
{
if
(
customObj
.
value1
&&
customObj
.
value2
)
{
params
[
it
.
name
]
=
customObj
.
value1
+
'x'
+
customObj
.
value2
;
}
else
{
show_message
(
'自定义图片尺寸未填写完整'
);
return
;
}
}
}
else
if
(
it
.
name
==
'number'
)
{
// 转换为number类型
params
[
it
.
name
]
=
parseFloat
(
it
.
value
+
''
);
}
else
{
// 添加params
params
[
it
.
name
]
=
it
.
value
;
}
}
}
}
console
.
log
(
params
);
onSubmit
(
params
);
};
onBeforeMount
(
async
()
=>
{
if
(
!
id
)
{
show_message
(
'禁止访问'
);
return
;
}
// 获取组件列表
await
getAdminComponent
();
});
onBeforeUnmount
(()
=>
{
closeInterval
();
});
</
script
>
<
style
lang=
"less"
>
@import
'@/style/variables.less'
;
.custom-copywriting-generation
{
margin-top
:
@
page-margin-top
;
padding-top
:
@
page-margin-top
;
box-sizing
:
border-box
;
position
:
relative
;
width
:
100%
;
height
:
100%
;
.generation-box
{
display
:
flex
;
padding-bottom
:
30px
;
box-sizing
:
border-box
;
.generate-result
{
width
:
50%
;
border
:
2px
dashed
#565656
;
...
...
@@ -348,7 +396,8 @@ onBeforeMount(async () => {
font-size
:
@
font-size-20
;
}
}
&
>
:last-child
{
&
>
:last-child
,
&
>
:nth-child
(
2
)
{
&::before
{
width
:
calc
(
200%
-
2px
);
}
...
...
@@ -358,5 +407,6 @@ onBeforeMount(async () => {
margin-top
:
20px
;
}
}
}
}
</
style
>
src/style/ui.less
View file @
b1b30785
...
...
@@ -16,4 +16,9 @@
&::-webkit-scrollbar-thumb {
background: #ddd;
}
&:hover {
&::-webkit-scrollbar-thumb {
background: #ddd !important;
}
}
}
src/style/variables.less
View file @
b1b30785
// 每个页面的content模块的margin-top
@page-margin-top: 30px;
// border
@main-border-radius: 15px;
...
...
src/utils/api/Task.ts
View file @
b1b30785
...
...
@@ -2,3 +2,239 @@ export const Tasks = {
img_to_img
:
1
,
text_to_img
:
2
,
};
// 任务类型
export
const
TASKTYPE
=
{
CHAT
:
1
,
PAINTING
:
2
,
VIDEO
:
3
,
};
// 文案生成对话记录 本地的key
export
const
ConversationKey
=
'custom_conversation'
;
// 图片生成页面要push一个生成数量
export
const
CustomNum
=
{
name
:
'生成数量'
,
lists
:
[
{
type
:
'custom-number'
,
label
:
'生成数量'
,
name
:
'number'
,
value
:
null
,
span
:
24
,
placeholder
:
'自定义'
,
rules
:
[
{
type
:
'required'
,
message
:
'产品数量必填'
,
},
],
},
],
};
// form表单示例--文案
export
const
FormExample
=
[
{
name
:
'基础填写'
,
lists
:
[
{
type
:
'text'
,
name
:
'category_1'
,
label
:
'产品类目'
,
value
:
null
,
span
:
24
,
placeholder
:
'产品类目'
,
rules
:
[
{
type
:
'required'
,
message
:
'必填'
,
},
],
},
{
type
:
'text'
,
name
:
'category_2'
,
value
:
null
,
label
:
'产品关键词'
,
span
:
24
,
placeholder
:
'产品关键词'
,
rules
:
[
{
type
:
'required'
,
message
:
'必填'
,
},
],
},
// 下拉选择
{
type
:
'select'
,
placeholder
:
'选择产品名称'
,
label
:
'产品名称'
,
name
:
'category_3'
,
options
:
[
{
label
:
'充电器'
,
value
:
'充电器'
,
},
{
label
:
'衣服'
,
value
:
'衣服'
,
},
],
// 可设置默认值
value
:
'衣服'
,
rules
:
[
{
type
:
'required'
,
message
:
'必填'
,
},
],
},
],
},
{
name
:
'详细描述'
,
lists
:
[
{
// 长文本输入框
type
:
'textarea'
,
name
:
'category_4'
,
label
:
'产品描述'
,
value
:
null
,
span
:
24
,
maxRows
:
'5'
,
minRows
:
'5'
,
placeholder
:
'详细描述产品细节,生成的文案更加完美。'
,
maxlength
:
1000
,
rules
:
[
{
type
:
'required'
,
message
:
'必填'
,
},
],
},
],
},
];
// form表单示例2-图片生成
export
const
FormExample2
=
[
{
name
:
'基础填写'
,
lists
:
[
{
type
:
'text'
,
name
:
'category_1'
,
label
:
'产品类目'
,
value
:
null
,
span
:
24
,
placeholder
:
'产品类目'
,
rules
:
[
{
type
:
'required'
,
message
:
'产品类目必填'
,
},
],
},
{
type
:
'text'
,
name
:
'category_2'
,
label
:
'产品类型'
,
value
:
null
,
span
:
24
,
placeholder
:
'产品类型'
,
rules
:
[
{
type
:
'required'
,
message
:
'产品类型必填'
,
},
],
},
],
},
{
name
:
'画面描述'
,
lists
:
[
{
// 长文本输入框
type
:
'textarea'
,
name
:
'category_3'
,
label
:
'画面描述'
,
value
:
null
,
span
:
24
,
maxRows
:
'5'
,
minRows
:
'5'
,
placeholder
:
'画面描述以短句、短语为佳,高级设置内的参数会对图像生成有艺术修饰作用;支持中英文等语言输入'
,
maxlength
:
1000
,
rules
:
[
{
type
:
'required'
,
message
:
'画面描述必填'
,
},
],
},
],
},
// 图片尺寸
{
name
:
'图片尺寸'
,
lists
:
[
{
// 单选按钮组
type
:
'radio_group_size'
,
name
:
'size_1'
,
value
:
'1600x1600'
,
span
:
24
,
label
:
'图片尺寸'
,
placeholder
:
'详细描述产品细节,生成的文案更加完美。'
,
options
:
[
{
size
:
'1600x1600'
,
label
:
'亚马逊产品图尺寸'
,
value
:
'1600x1600'
,
},
{
size
:
'600x180'
,
label
:
'亚马逊a+主图'
,
value
:
'600x180'
,
},
{
type
:
'custom'
,
label
:
'自定义'
,
value
:
''
,
value1
:
''
,
value2
:
''
,
},
],
rules
:
[
{
type
:
'required'
,
message
:
'图片尺寸必选'
,
},
],
},
],
},
// 上传图片
{
name
:
'上传图片'
,
lists
:
[
{
// 单选按钮组
type
:
'upload'
,
name
:
'image_1'
,
label
:
'上传图片'
,
value
:
null
,
span
:
24
,
// rules: [
// {
// type: 'required',
// message: '必填',
// },
// ],
},
],
},
];
src/utils/api/scenes.ts
View file @
b1b30785
...
...
@@ -3,8 +3,19 @@ import request from '../request';
// 场景模块
// 获取场景列表
export
const
getScenesList
=
()
=>
{
return
request
.
get
(
'/api/scenarios'
,
{
export
const
getScenesList
=
(
id
:
number
,
type
:
string
)
=>
{
if
(
type
==
'parent'
)
{
return
request
.
get
(
`/api/scenarios`
,
{
params
:
{
parent_id
:
id
,
},
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
}
let
url
=
id
?
`/api/scenarios/
${
id
}
`
:
`/api/scenarios`
;
return
request
.
get
(
url
,
{
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
...
...
@@ -19,3 +30,50 @@ export const getScenariosRecommend = () => {
},
});
};
// 文案提交
export
const
useSubmitConversation
=
(
data
:
any
)
=>
{
return
request
.
post
(
'/api/users/conversation'
,
data
,
{
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
};
// 图片任务提交
export
const
useSubmitConversationImage
=
(
data
:
any
)
=>
{
return
request
.
post
(
'/api/users/conversation/image'
,
data
,
{
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
};
// 图片任务回调
export
const
useImageCallback
=
(
data
:
any
)
=>
{
return
request
.
get
(
'/api/users/conversation/image'
,
{
params
:
data
,
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
};
// 获取上传策略
export
const
useUploadStrategy
=
()
=>
{
return
request
.
get
(
'/api/users/upload/policy'
,
{
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
};
// 获取生成记录
export
const
getGenerateRecords
=
(
data
:
any
)
=>
{
return
request
.
get
(
'/api/users/scenarios/logs'
,
{
params
:
data
,
headers
:
{
authorization
:
`Bearer
${
getUserCookie
()}
`
,
},
});
};
src/utils/tool.ts
View file @
b1b30785
...
...
@@ -411,3 +411,33 @@ export const filterRepeatTimestamp = (list: any, newList: any) => {
}
return
list
;
};
/**
*
* @param rules
* @param value
* @returns
*/
export
const
Validationrules
=
(
rules
:
any
[],
value
:
string
|
number
,
name
:
string
=
''
)
=>
{
if
(
rules
&&
rules
.
length
)
{
for
(
let
i
=
0
;
i
<
rules
.
length
;
i
++
)
{
let
item
=
rules
[
i
];
if
(
item
.
type
==
'required'
&&
!
value
&&
name
.
indexOf
(
'size_'
)
==
-
1
)
{
// 必填项
return
item
.
message
;
}
else
if
(
item
.
type
==
'regex'
&&
value
)
{
// 正则
let
status
=
item
.
value
.
test
(
value
);
if
(
!
status
)
{
return
item
.
message
;
}
}
}
}
else
{
return
''
;
}
};
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