Files
lingji-work-fe/src/views/property-marketing/assignment-management/components/draw-popup.vue

454 lines
12 KiB
Vue
Raw Normal View History

2025-09-15 20:26:31 +08:00
<template>
<a-drawer
title="创建任务"
cancel-text="取消"
ok-text="创建任务"
placement="right"
v-model:visible="showDriwer"
@after-visible-change="showDriwerChange"
width="480px"
2025-09-18 14:40:47 +08:00
class="task-drawer"
style="z-index: 999"
2025-09-15 20:26:31 +08:00
>
2025-09-18 14:40:47 +08:00
<div class="drawer-content" :style="isActive == 'ai' ? 'height: 376px;' : 'height:216px;'">
<div class="flex flex-col justify-center items-start">
<CommonSelect
v-model="localQuery.accounts"
:options="accountList || []"
:multiple="true"
@change="(val) => handleChange('accounts', val)"
class="!w-432px select-with-tags"
placeholder="请选择账号名称"
:allowSearch="true"
:maxTagCount="999"
popup-container=".filter-popup-content"
/>
<div class="ai-content-generator">
<div class="flex mt-16px">
<Button
class="w-194px h-38px mr-8px"
:class="isActive == 'ai' ? 'active-chose' : ''"
@click="handleSelect('ai')"
>
<template #icon>
<img :src="aiIcon" class="w-16 h-16 mr-8px" />
</template>
AI生成
</Button>
<Button
class="w-194px h-38px"
:class="isActive == 'chose' ? 'active-chose' : ''"
@click="handleSelect('chose')"
>
从成品库选择</Button
>
</div>
<div v-show="isActive == 'ai'">
<!-- 任务描述区域 -->
<div class="form-section">
<div class="flex items-center w-400px mt-16px mb-8px">
<div class="section-title">任务描述</div>
<div class="font-size-12px text-[#999999]">非必填</div>
</div>
<div class="w-400px h-126px border-rounded-8px mb-8px" style="background: #fff">
<a-textarea
placeholder="描述你想让AI帮你生成的内容。未填写时AI 会参考账号历史内容的题材与行业方向,结合当下话题,自动生成文案和图片后发布"
class="task-description font-size-12px"
:rows="5"
/>
</div>
</div>
<!-- 素材添加区域 -->
<div class="form-section material-section">
<Button class="add-material-btn" @click="handleAddMaterial">
<template #icon>
<icon-plus size="16" class="mr-8px" />
</template>
从原料库添加
</Button>
<p class="material-hint">AI会参考添加的文本图片视频等素材完成符合需求的创作</p>
</div>
</div>
<div v-show="isActive == 'chose'">
<!-- 任务描述区域 -->
<div class="form-section">
<div class="flex items-center w-400px mt-16px mb-8px">
<div class="section-title">发布内容</div>
<div class="font-size-12px text-[#999999]">必填</div>
</div>
<div class="form-section material-section">
<Button @click="handleAddMaterial" class="add-material-btn">
<template #icon>
<icon-plus size="16" class="mr-8px" />
</template>
添加内容
</Button>
<p class="material-hint">前往成品库选择要发布的内容</p>
</div>
</div>
</div>
</div>
</div>
<!-- 发布计划区域 -->
<div class="publish-section">
<div class="flex items-center justify-between w-384px">
<div class="section-title">发布计划</div>
<CommonSelect
2025-09-19 18:07:33 +08:00
v-model="publishType"
:options="publishOptions"
@change="handlePublishTypeChange"
class="w-180px background-#fff publish-type-select"
:allowSearch="false"
:multiple="false"
2025-09-18 14:40:47 +08:00
popup-container=".filter-popup-content"
/>
</div>
2025-09-19 18:07:33 +08:00
<div v-if="publishType === 'timing'">
2025-09-18 14:40:47 +08:00
<div class="line"></div>
<div class="flex items-center justify-between mt-16px w-384px">
<div class="section-title">日期</div>
<a-date-picker
class="w-180px h-40px background-#fff"
@change="handleDateChange"
v-model="currentDate"
format="YYYY年MM月DD日周dd"
value-format="YYYY-MM-DD"
/>
</div>
<div class="line"></div>
<div class="flex items-center justify-between mt-16px w-384px">
<div class="section-title">时间</div>
2025-09-19 18:07:33 +08:00
<a-time-picker v-model="strValue" format="HH:mm" class="w-180px h-40px background-#fff" />
2025-09-18 14:40:47 +08:00
</div>
</div>
</div>
</div>
<a-drawer
title="成品库"
cancel-text="取消"
ok-text="确定"
placement="right"
v-model:visible="showDrawer2"
@after-visible-change="showDriwerChange"
width="904px"
class="task-drawer"
style="right: 481px"
>
2025-09-19 14:57:14 +08:00
<a-table :data="materialData" bordered :columns="columns">
<template #create_at="{ record }">
<div class="flex items-center">
{{ record.created_at ? dayjs(record.created_at).format('YYYY-MM-DD HH:mm:ss') : '-' }}
</div>
</template>
</a-table>
2025-09-18 14:40:47 +08:00
</a-drawer>
2025-09-15 20:26:31 +08:00
</a-drawer>
</template>
<script lang="ts" setup>
2025-09-19 18:07:33 +08:00
import { ref, reactive, onMounted, watch } from 'vue';
2025-09-18 14:40:47 +08:00
import aiIcon from '@/assets/img/media-account/icon-AI.png';
2025-09-19 14:57:14 +08:00
import { Checkbox, Button, Space, Pagination, notification, DatePicker, TimePicker } from 'ant-design-vue';
import { TABS_LIST, ORIGIN_LIST, RawMaterialType } from '@/views/material-center/components/raw-material/constants';
2025-09-18 14:40:47 +08:00
import dayjs from 'dayjs';
2025-09-19 14:57:14 +08:00
import { getRawMaterialsPage } from '@/api/all/generationWorkshop';
// 工具引入
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
const columns = ref([
{
title: '名称',
dataIndex: 'name',
width: 200,
solts: { customRender: 'name' },
},
{
title: '类型',
dataIndex: 'type',
width: 100,
render: (text) => {
return RawMaterialType[text];
},
},
{
title: '创建时间',
dataIndex: 'created_at',
width: 200,
slots: { customRender: 'create_at' },
},
]);
2025-09-15 20:26:31 +08:00
2025-09-19 14:57:14 +08:00
// 表格分页逻辑
const { pageInfo, onPageChange, onPageSizeChange } = useTableSelectionWithPagination({
onPageChange: () => handleSearch(),
onPageSizeChange: () => handleSearch(),
});
2025-09-18 14:40:47 +08:00
const selectedTab = ref('ai-generate');
// 定义props和emit
const props = defineProps({
operators: Array,
platformOptions: Array,
accountList: Array,
query: Object,
});
2025-09-19 14:57:14 +08:00
// 查询参数
const query = reactive({
page: pageInfo.value.page,
page_size: pageInfo.value.page_size,
platforms: undefined,
operator_ids: undefined,
ids: [],
top_execution_time: undefined,
});
const materialData = ref([]);
const handleSearch = async () => {
const res = await getRawMaterialsPage(query);
console.log(res.data.data);
materialData.value = [...materialData.value, ...res.data.data];
};
2025-09-18 14:40:47 +08:00
const isActive = ref('ai');
2025-09-19 18:07:33 +08:00
// 发布类型选项
const publishOptions = ref([
{ value: 'immediate', label: '立即发布' },
{ value: 'timing', label: '定时发布' },
]);
// 发布类型,默认为立即发布
const publishType = ref('immediate');
// 处理发布类型变化
const handlePublishTypeChange = (value) => {
publishType.value = value;
};
2025-09-19 14:57:14 +08:00
const publishQuery = ref([
{
2025-09-19 10:34:26 +08:00
id: 1,
2025-09-19 14:57:14 +08:00
name: '立即发布',
},
{ id: 2, name: '定时发布' },
]);
2025-09-18 14:40:47 +08:00
// 本地筛选状态(保持上次选择)
const localQuery = ref({
accounts: props.query?.ids || [],
});
2025-09-15 20:26:31 +08:00
const showDriwer = ref(false);
2025-09-18 14:40:47 +08:00
const showDrawer2 = ref(false);
const emit = defineEmits(['filter-change']);
const isTiming = ref(true);
const currentDate = ref(new Date());
2025-09-19 18:07:33 +08:00
// 将时间选择器默认值设置为当前时间
const strValue = ref(dayjs().format('HH:mm'));
// 监听抽屉显示状态,每次打开时更新时间为当前时间
watch(showDriwer, (newVal) => {
if (newVal) {
strValue.value = dayjs().format('HH:mm');
}
});
2025-09-19 14:57:14 +08:00
onMounted(() => {
handleSearch();
});
2025-09-18 14:40:47 +08:00
const handleSelect = (value) => {
console.log('++++++++++', value);
isActive.value = value;
};
const handleAddMaterial = () => {
showDrawer2.value = true;
};
const handleDateChange = (date) => {};
2025-09-15 20:26:31 +08:00
// 暴露方法给父组件
const showDrawer = () => {
showDriwer.value = true;
};
const showDriwerChange = (visible: boolean) => {
console.log('Drawer visible: ', visible);
};
2025-09-18 14:40:47 +08:00
// 处理筛选条件变化(不关闭弹窗,直接触发筛选)
const handleChange = (field, value) => {
localQuery.value[field] = value;
// 直接触发筛选变更,不需要确认按钮
emit('filter-change', {
accounts: localQuery.value.accounts,
});
};
2025-09-15 20:26:31 +08:00
// 使用defineExpose暴露方法
defineExpose({
2025-09-18 14:40:47 +08:00
showDrawer,
2025-09-15 20:26:31 +08:00
});
2025-09-18 14:40:47 +08:00
</script>
<style scoped>
.drawer-content {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
/* 抽屉左侧圆角样式 */
.arco-drawer {
border-top-left-radius: 8px !important;
border-bottom-left-radius: 8px !important;
}
.ai-content-generator {
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
margin-top: 24px;
width: 432px;
background: linear-gradient(to right, #f0f5ff, #fff6f5) !important;
border-radius: 8px;
}
.active-chose {
border: #722ed1 1px solid !important;
}
.main-container {
width: 100%;
max-width: 600px;
background-color: #fff;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.tab-group {
margin-bottom: 24px;
width: 100%;
}
.tab-button {
flex: 1;
height: 48px;
font-size: 16px;
}
.ai-tab .ai-icon {
display: inline-block;
width: 16px;
height: 16px;
background-color: #722ed1;
color: white;
border-radius: 50%;
text-align: center;
line-height: 16px;
font-size: 12px;
margin-right: 8px;
}
.form-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 400px;
border-radius: 8px;
}
.publish-section {
width: 432px;
padding: 16px 24px;
background-color: #f7f8fa;
display: flex;
flex-direction: column;
border-radius: 8px;
align-items: start;
justify-content: space-between;
margin-top: 24px;
}
.section-title {
font-size: 14px;
color: #333;
font-weight: 500;
}
.task-description {
width: 100%;
font-size: 14px;
height: 126px;
border: none !important;
box-shadow: none !important;
outline: none !important; /* 去除默认的聚焦轮廓 */
}
.task-description::placeholder {
color: #999;
}
.material-section {
border-radius: 8px;
text-align: center;
background-color: #fff;
margin-bottom: 8px;
padding: 16px;
}
.add-material-btn {
width: 240px;
height: 38px;
border-radius: 8px;
font-size: 14px;
border: 1px dashed #e0e0e0 !important;
margin-bottom: 8px;
}
.drag-handle {
position: absolute;
width: 16px;
height: 16px;
background-color: #ff7d00;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.material-hint {
color: #939499;
font-size: 14px;
margin: 0 40px;
}
.size-selector {
margin-bottom: 24px;
text-align: center;
}
.size-tag {
font-size: 14px;
padding: 6px 16px;
border-radius: 16px;
}
2025-09-19 18:07:33 +08:00
.publish-type-select :deep(.ant-select-selection-item) {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
2025-09-18 14:40:47 +08:00
.publish-select {
width: 100%;
height: 40px;
}
.line {
background-color: #e6e6e8;
width: 382px;
height: 1px;
margin-top: 16px;
}
</style>