fixed: 新闻素材来源修改多选为单选;修改视频时长统计(视频时长单位为毫秒);

update: 更新导航栏文字(AI视频->视频生成)
This commit is contained in:
LittleBoy 2024-12-17 11:39:19 +08:00
parent 1acdc2a99d
commit e1a4005e27
7 changed files with 54 additions and 40 deletions

25
README.md Normal file
View File

@ -0,0 +1,25 @@
## 数值人直播间
### Start
```shell
git clone git@e.coding.net:starbite/aixiaodui/fengmang-backend.git
npm install
npm run dev
```
打开 [http://localhost:10021/](http://localhost:10021/) 查看效果
### Deploy
**直接部署**
> 需要配置 /mgmt 及 /api 反向代理
```shell
; 如果需要指定前缀(CDN)或者需要运行在相对路径中,不需要则跳过此命令
export PUBLIC_PATH=xxxxxxxx(相应路径)
npm run build
```
生成的资源在dist目录中将此目录中所有文件放置在待部署web目录即可。
**使用docker**
[x] TODO
```shell
dockercompose up -d
```

View File

@ -177,7 +177,7 @@ export default function LiveIndex() {
const totalDuration = useMemo(() => {
if (!videoData || videoData.length == 0) return 0;
// 计算总时长
return videoData.reduce((sum, v) => sum + v.video_duration, 0);
return videoData.reduce((sum, v) => sum + Math.ceil(v.video_duration / 1000), 0);
}, [videoData])
return (<div className="container py-10 page-live">

View File

@ -11,6 +11,11 @@ type SearchPanelProps = {
const pagination = {
limit: 10, page: 1
}
const DEFAULT_STATE = {
tag_level_1_id: -1,
tag_level_2_id: -1,
subOptions: []
}
export default function SearchPanel({onSearch}: SearchPanelProps) {
const tags = useArticleTags();
const [params, setParams] = useSetState<ApiArticleSearchParams>({
@ -18,36 +23,26 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
});
const [state, setState] = useSetState<{
source: string | number;
tag_level_1_id: number;
tag_level_2_id: number;
subOptions: (string | number)[]
}>({
source: -1,
subOptions: []
})
}>({...DEFAULT_STATE})
// 二级分类
const [subOptions, setSubOptions] = useState<OptionItem[]>([])
const onFinish = () => {
if(state.source != -1){
params.tags = [];
state.subOptions.forEach(level2 => {
params.tags!.push({
level1: state.source,
level2
})
})
}else{
params.tags = undefined;
}
onSearch?.({
...params
...params,
tag_level_1_id: state.tag_level_1_id > 0?state.tag_level_1_id:undefined,
tag_level_2_id: state.tag_level_2_id > 0?state.tag_level_2_id:undefined,
pagination
})
}
// 重置
const onReset = () => {
setParams({pagination, title: ''})
setState({source: -1,subOptions: []})
setState({...DEFAULT_STATE})
setSubOptions([])
onSearch?.({pagination})
}
@ -84,37 +79,31 @@ export default function SearchPanel({onSearch}: SearchPanelProps) {
<div className="list-container flex-1">
<div className="news-source-lv-1 flex flex-wrap">
<div
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.source == -1 ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == -1 ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
onClick={() => {
setState({source: -1, subOptions: []})
setState({...DEFAULT_STATE})
setSubOptions([])
}}></div>
{
tags.filter(s=>s.value !== 999999).map(it => (
<div
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.source == it.value ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_1_id == it.value ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
key={it.value}
onClick={() => {
setState({source: it.value, subOptions: []})
setState({tag_level_1_id: Number(it.value),tag_level_2_id:-1})
setSubOptions(it.children || [])
}}>{it.label}</div>)
)
}
</div>
{state.source != -1 && subOptions.length > 0 && <div className="news-source-lv-2 bg-gray-100 p-2 rounded mt-2 flex flex-wrap">
{state.tag_level_1_id != -1 && subOptions.length > 0 && <div className="news-source-lv-2 bg-gray-100 p-2 rounded mt-2 flex flex-wrap">
{
subOptions.map(it => (
<div
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.subOptions.includes(it.value) ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
className={`filter-item whitespace-nowrap px-2 py-1 mt-1 text-sm mr-1 cursor-pointer rounded ${state.tag_level_2_id == it.value ? 'bg-blue-500 text-white' : 'hover:bg-gray-100'}`}
key={it.value}
onClick={() => {
const options = [...state.subOptions]
if (options.includes(it.value)) {
options.splice(options.indexOf(it.value), 1)
} else {
options.push(it.value)
}
setState({subOptions: options})
setState({tag_level_2_id: Number(it.value)})
}}>{it.label}</div>)
)
}

View File

@ -77,7 +77,7 @@ export default function VideoIndex() {
const totalDuration = useMemo(() => {
if (!videoData || videoData.length == 0) return 0;
// 计算总时长
return videoData.reduce((sum, v) => sum + v.duration, 0);
return videoData.reduce((sum, v) => sum + Math.ceil(v.duration / 1000), 0);
}, [videoData])
return (<div className="container py-10 page-live">

View File

@ -17,7 +17,7 @@ const NavItems = [
},
{
key: 'create',
name: 'AI视频',
name: '视频生成',
icon: 'ai',
path:'/create'
},

8
src/types/api.d.ts vendored
View File

@ -6,10 +6,10 @@ declare interface ApiRequestPageParams {
}
declare interface ApiArticleSearchParams extends ApiRequestPageParams{
// // 1级标签id
// tag_level_1_id?: number;
// // 2级标签id 没有则为0
// tag_level_2_id?: number;
// 1级标签id
tag_level_1_id?: number;
// 2级标签id 没有则为0
tag_level_2_id?: number;
tags?: {
level1: Id;
level2: Id;

View File

@ -32,12 +32,12 @@ export default defineConfig(({mode}) => {
port: 10021,
proxy: {
'/mgmt': {
target: 'http://192.168.0.231:9999',
target: 'http://124.220.14.192', // http://124.220.14.192/ 192.168.0.231:9999
changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '')
},
'/api': {
target: 'http://192.168.0.231:9999',
target: 'http://124.220.14.192',
changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '')
}