Merge remote-tracking branch 'origin/main' into feature/0724_新媒体账号状态重构
# Conflicts: # src/views/property-marketing/media-account/account-manage/components/account-table/index.vue # src/views/property-marketing/put-account/account-data/components/filter-block/index.vue # src/views/property-marketing/put-account/account-manage/components/account-table/index.vue # src/views/property-marketing/put-account/account-manage/components/filter-block/index.vue
This commit is contained in:
@ -133,7 +133,7 @@
|
||||
</a-space>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="handleCancel">取消</a-button>
|
||||
<a-button size="large" @click="handleCancel">取消</a-button>
|
||||
<a-button type="primary" size="large" class="rounded-4px" @click="handleOk"> 确定 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
@ -397,14 +397,6 @@ const handleOk = () => {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Border-1, #d7d7d9);
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
&:hover {
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -260,7 +260,7 @@
|
||||
</a-space>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="handleCancel">取消</a-button>
|
||||
<a-button size="large" @click="handleCancel">取消</a-button>
|
||||
<a-button type="primary" size="large" class="rounded-4px" @click="handleOk"> 确定 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
@ -713,14 +713,6 @@ onMounted(() => {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Border-1, #d7d7d9);
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
&:hover {
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -110,7 +110,7 @@
|
||||
</a-space>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="handleCancel">取消</a-button>
|
||||
<a-button size="large" @click="handleCancel">取消</a-button>
|
||||
<a-button type="primary" size="large" class="rounded-4px" @click="handleOk"> 确定 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
@ -318,14 +318,6 @@ const search = () => {
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--Border-1, #d7d7d9);
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
&:hover {
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -54,16 +54,15 @@
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item hide-label class="mt-68px mb-16px">
|
||||
<div
|
||||
<a-button
|
||||
type="primary"
|
||||
class="w-480 h-48 text-16px rounded-8px text-center text-white leading-48px"
|
||||
class="w-480 h-48 !text-16px !rounded-8px"
|
||||
:class="disabledSubmitBtn ? 'cursor-no-drop' : 'cursor-pointer'"
|
||||
:style="{ backgroundColor: disabledSubmitBtn ? '#C5B7FF' : '#6D4CFE' }"
|
||||
:disabled="disabledSubmitBtn"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ isLogin ? '登录' : '注册并开通企业账号' }}
|
||||
</div>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-space class="text-12px color-#737478 justify-start items-center">
|
||||
@ -126,13 +125,16 @@
|
||||
<script setup lang="ts">
|
||||
import PuzzleVerification from './components/PuzzleVerification.vue';
|
||||
import { fetchLoginCaptCha, fetchAuthorizationsCaptcha, fetchProfileInfo } from '@/api/all/login';
|
||||
import { joinEnterpriseByInviteCode } from '@/api/all';
|
||||
import { ref, reactive, onUnmounted, computed } from 'vue';
|
||||
import { useUserStore } from '@/stores';
|
||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||
import { handleUserLogin } from '@/utils/user';
|
||||
import router from '@/router';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const formRef = ref();
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const enterpriseStore = useEnterpriseStore();
|
||||
const countdown = ref(0);
|
||||
@ -145,7 +147,6 @@ const submitting = ref(false);
|
||||
const hasCheck = ref(false);
|
||||
const mobileNumber = ref('');
|
||||
const selectedAccountIndex = ref(0);
|
||||
|
||||
const accounts = ref([]);
|
||||
|
||||
const loginForm = reactive({
|
||||
@ -300,6 +301,15 @@ const handleSubmit = async () => {
|
||||
// 处理登录成功逻辑
|
||||
AMessage.success(isLogin.value ? '登录成功' : '注册成功');
|
||||
userStore.setToken(data.access_token);
|
||||
|
||||
const { invite_code } = route.query;
|
||||
if (invite_code) {
|
||||
const { code } = await joinEnterpriseByInviteCode(invite_code as string);
|
||||
if (code === 200) {
|
||||
AMessage.success('加入企业成功');
|
||||
}
|
||||
}
|
||||
|
||||
getProfileInfo();
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@ -21,13 +21,13 @@
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row flex">
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
|
||||
@ -3,23 +3,11 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
|
||||
:deep(.edit-btn) {
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
|
||||
.table-wrap {
|
||||
width: 100%;
|
||||
|
||||
|
||||
@ -1,13 +1,4 @@
|
||||
.arco-modal {
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
&:hover {
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
}
|
||||
}
|
||||
|
||||
.arco-modal-body {
|
||||
.arco-form-item {
|
||||
margin-bottom: 16px;
|
||||
|
||||
@ -25,13 +25,13 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-row flex">
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium">
|
||||
<a-button type="outline" class="mr-12px" size="medium">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium">
|
||||
<a-button size="medium">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
|
||||
@ -25,13 +25,13 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-row flex">
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium">
|
||||
<a-button type="outline" class="mr-12px" size="medium">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium">
|
||||
<a-button size="medium">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
|
||||
@ -15,11 +15,11 @@
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-button class="w-110px search-btn mr-12px" size="medium" @click="handleExport">
|
||||
<a-button type="outline" class="w-110px mr-12px" size="medium" @click="handleExport">
|
||||
<template #icon> <icon-download /> </template>
|
||||
<template #default>导出数据</template>
|
||||
</a-button>
|
||||
<a-button class="w-110px search-btn" size="medium" @click="openCustomColumn">
|
||||
<a-button type="outline" class="w-110px" size="medium" @click="openCustomColumn">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="14" height="14" />
|
||||
</template>
|
||||
@ -115,7 +115,7 @@
|
||||
}}
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'" #cell="{ record }">
|
||||
<a-button type="outline" size="small" class="search-btn" @click="handleDetail(record)">详情</a-button>
|
||||
<a-button type="outline" size="small" @click="handleDetail(record)">详情</a-button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="column.isRateField" #cell="{ record }">
|
||||
@ -144,7 +144,7 @@
|
||||
</a-table-column>
|
||||
<a-table-column data-index="operation" fixed="right" width="100" title="操作">
|
||||
<template #cell="{ record }">
|
||||
<a-button type="outline" size="small" class="search-btn" @click="handleDetail(record)">详情</a-button>
|
||||
<a-button type="outline" size="small" @click="handleDetail(record)">详情</a-button>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
|
||||
<template #footer>
|
||||
<div style="text-align: right">
|
||||
<a-button class="mr-8px cancel-btn" size="medium" @click="close">取消</a-button>
|
||||
<a-button class="mr-8px" size="medium" @click="close">取消</a-button>
|
||||
<a-button type="primary" size="medium" @click="onSubmit">确定</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -87,13 +87,5 @@
|
||||
}
|
||||
}
|
||||
.arco-modal-footer {
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
&:hover {
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">分组</span>
|
||||
<a-space class="w-200px">
|
||||
<GroupSelect v-model="query.group_ids" multiple :options="groups" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.group_ids" :options="groups" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
@ -31,7 +31,7 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">运营人员</span>
|
||||
<a-space class="w-160px">
|
||||
<OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.operator_id" :multiple="false" :options="operators" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
@ -47,13 +47,13 @@
|
||||
</a-select>
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="w-84px mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button class="w-84px" size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -66,9 +66,8 @@
|
||||
<script setup>
|
||||
import { reactive, defineEmits, defineProps } from 'vue';
|
||||
import { fetchAccountGroups, fetchAccountOperators } from '@/api/all/propertyMarketing';
|
||||
import GroupSelect from '@/views/property-marketing/media-account/components/group-select';
|
||||
import OperatorSelect from '@/views/property-marketing/media-account/components/operator-select';
|
||||
import StatusSelect from '@/views/property-marketing/media-account/components/status-select';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
const props = defineProps({
|
||||
query: {
|
||||
|
||||
@ -2,16 +2,6 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
.filter-wrap {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e6e6e8;
|
||||
|
||||
@ -36,13 +36,13 @@
|
||||
/>
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="w-84px mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button class="w-84px" size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
|
||||
@ -19,16 +19,6 @@
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
}
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
|
||||
.table-wrap {
|
||||
width: 100%;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<span>确认删除 {{ accountName }} 这个账号吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
|
||||
@ -46,6 +46,30 @@
|
||||
<span class="label">运营人员</span>
|
||||
<span class="cts">{{ item.operator?.name || '-' }}</span>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<span class="label">所属项目</span>
|
||||
<span v-if="!item.projects.length" class="cts">-</span>
|
||||
<div v-else class="flex items-center">
|
||||
<a-tooltip
|
||||
v-if="item.projects.length > 2"
|
||||
position="bottom"
|
||||
:content="
|
||||
item.projects
|
||||
.slice(2)
|
||||
.map((v) => v.name)
|
||||
.join(',')
|
||||
"
|
||||
>
|
||||
<div class="tag-box">
|
||||
<span class="text">{{ `+${item.projects.length - 2}` }}</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
|
||||
<div v-for="(project, index) in item.projects.slice(0, 2)" :key="index" class="tag-box">
|
||||
<span class="text">{{ project.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<span class="label">分组</span>
|
||||
<span class="cts">{{ item.group?.name || '-' }}</span>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>确认暂停同步 “{{ accountName }}” 这个账号的数据吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px" size="large" @click="onConfirm">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -1,9 +1,3 @@
|
||||
@mixin ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-container {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
|
||||
@ -19,12 +19,11 @@ import {
|
||||
Message as AMessage,
|
||||
Textarea,
|
||||
} from '@arco-design/web-vue';
|
||||
import TagSelect from '@/views/property-marketing/media-account/components/tag-select';
|
||||
import GroupSelect from '@/views/property-marketing/media-account/components/group-select';
|
||||
import AuthorizedAccountModal from '../authorized-account-modal';
|
||||
// import ImportPromptModal from '../import-prompt-modal';
|
||||
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
|
||||
import SyncDataModal from '../sync-data-modal';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
// import { downloadByUrl } from '@/utils/tools';
|
||||
import { showExportNotification } from '@/utils/arcoD';
|
||||
@ -37,6 +36,7 @@ import {
|
||||
putMediaAccounts,
|
||||
getTemplateUrl,
|
||||
batchMediaAccounts,
|
||||
getProjectList,
|
||||
} from '@/api/all/propertyMarketing';
|
||||
|
||||
import icon1 from '@/assets/img/media-account/icon-download.png';
|
||||
@ -58,6 +58,7 @@ const INITIAL_FORM = {
|
||||
platform: 1,
|
||||
group_id: undefined,
|
||||
tag_ids: [],
|
||||
project_ids: [],
|
||||
end_work_link: undefined,
|
||||
cookie: undefined,
|
||||
};
|
||||
@ -66,6 +67,7 @@ export default {
|
||||
setup(props, { emit, expose }) {
|
||||
const groupOptions = ref([]);
|
||||
const tagOptions = ref([]);
|
||||
const projects = ref([]);
|
||||
const visible = ref(false);
|
||||
const uploadType = ref('manual');
|
||||
const uploadStatus = ref(UploadStatus.DEFAULT);
|
||||
@ -126,6 +128,12 @@ export default {
|
||||
tagOptions.value = data;
|
||||
}
|
||||
};
|
||||
const getProjects = async () => {
|
||||
const { code, data } = await getProjectList();
|
||||
if (code === 200) {
|
||||
projects.value = data;
|
||||
}
|
||||
};
|
||||
function handleUpload(option) {
|
||||
const { fileItem } = option;
|
||||
uploadStatus.value = UploadStatus.WAITING;
|
||||
@ -141,6 +149,9 @@ export default {
|
||||
const reset = () => {
|
||||
formRef.value?.resetFields();
|
||||
formRef.value?.clearValidate();
|
||||
groupOptions.value = [];
|
||||
tagOptions.value = [];
|
||||
projects.value = [];
|
||||
form.value = cloneDeep(INITIAL_FORM);
|
||||
fileName.value = '';
|
||||
file.value = null;
|
||||
@ -162,6 +173,7 @@ export default {
|
||||
}
|
||||
getGroups();
|
||||
getTags();
|
||||
getProjects();
|
||||
visible.value = true;
|
||||
};
|
||||
const getAccountDetail = async () => {
|
||||
@ -364,8 +376,16 @@ export default {
|
||||
<FormItem label="号码持有人" field="holder_name">
|
||||
<Input v-model={form.value.holder_name} placeholder="请输入..." class="w-240px" size="large" />
|
||||
</FormItem>
|
||||
<FormItem label="所属项目">
|
||||
<CommonSelect
|
||||
v-model={form.value.project_ids}
|
||||
options={projects.value}
|
||||
placeholder="请选择…"
|
||||
size="large"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="选择分组">
|
||||
<GroupSelect
|
||||
<CommonSelect
|
||||
v-model={form.value.group_id}
|
||||
multiple={false}
|
||||
options={groupOptions.value}
|
||||
@ -373,8 +393,9 @@ export default {
|
||||
size="large"
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label="选择标签">
|
||||
<TagSelect v-model={form.value.tag_ids} options={tagOptions.value} placeholder="请选择…" size="large" />
|
||||
<CommonSelect v-model={form.value.tag_ids} options={tagOptions.value} placeholder="请选择…" size="large" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="笔记链接"
|
||||
@ -406,7 +427,6 @@ export default {
|
||||
v-model={form.value.cookie}
|
||||
placeholder="请输入..."
|
||||
size="large"
|
||||
max-length={500}
|
||||
auto-size={{ minRows: 5, maxRows: 8 }}
|
||||
/>
|
||||
</FormItem>
|
||||
@ -415,7 +435,7 @@ export default {
|
||||
)}
|
||||
</Form>
|
||||
<div style="display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px;">
|
||||
<Button size="large" class="cancel-btn" onClick={onClose}>
|
||||
<Button size="large" onClick={onClose}>
|
||||
取消
|
||||
</Button>
|
||||
<Button type="primary" size="large" loading={importLoading.value} onClick={onSubmit}>
|
||||
|
||||
@ -76,15 +76,10 @@
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<a-button v-if="modalState === MODAL_STATE.QR_READY" size="large" class="cancel-btn" @click="handleRefreshQrCode">
|
||||
<a-button v-if="modalState === MODAL_STATE.QR_READY" size="large" @click="handleRefreshQrCode">
|
||||
重新生成
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="[MODAL_STATE.SUCCESS, MODAL_STATE.FAILED].includes(modalState)"
|
||||
size="large"
|
||||
class="cancel-btn"
|
||||
@click="close"
|
||||
>
|
||||
<a-button v-if="[MODAL_STATE.SUCCESS, MODAL_STATE.FAILED].includes(modalState)" size="large" @click="close">
|
||||
取消
|
||||
</a-button>
|
||||
<a-button type="primary" size="large" @click="handleOk">
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
<a-form-item label="选择分组" required>
|
||||
<template v-if="editType === 'all'">
|
||||
<div class="flex items-center w-100%">
|
||||
<GroupSelect v-model="form.group_id" :options="groupOptions" :multiple="false" class="flex-1" />
|
||||
<CommonSelect v-model="form.group_id" :options="groupOptions" :multiple="false" class="flex-1" />
|
||||
</div>
|
||||
</template>
|
||||
</a-form-item>
|
||||
@ -47,7 +47,7 @@
|
||||
<a-table-column title="选择分组" data-index="group_id">
|
||||
<template #cell="{ record }">
|
||||
<div class="flex items-center w-100%">
|
||||
<GroupSelect v-model="record.group_id" :options="groupOptions" :multiple="false" />
|
||||
<CommonSelect v-model="record.group_id" :options="groupOptions" :multiple="false" />
|
||||
</div>
|
||||
</template>
|
||||
</a-table-column>
|
||||
@ -56,7 +56,7 @@
|
||||
</template>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button size="large" class="mr-16px cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="onSubmit">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
@ -65,7 +65,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { fetchAccountGroups, batchPutGroup } from '@/api/all/propertyMarketing';
|
||||
import GroupSelect from '@/views/property-marketing/media-account/components/group-select';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
import icon1 from '@/assets/img/icon-question.png';
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@
|
||||
</template>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button size="large" class="mr-16px cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="onSubmit">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -33,16 +33,20 @@
|
||||
<span class="label">平台</span>
|
||||
<a-space class="w-160px">
|
||||
<a-select v-model="query.platform" size="medium" placeholder="全部" allow-clear @change="handleSearch">
|
||||
<a-option v-for="(item, index) in PLATFORM_LIST" :key="index" :value="item.value" :label="item.label">{{
|
||||
item.label
|
||||
}}</a-option>
|
||||
<a-option
|
||||
v-for="(item, index) in MEDIA_ACCOUNT_PLATFORMS"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
>{{ item.label }}</a-option
|
||||
>
|
||||
</a-select>
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">运营人员</span>
|
||||
<a-space class="w-160px">
|
||||
<OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.operator_id" :multiple="false" :options="operators" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
@ -50,22 +54,28 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">分组</span>
|
||||
<a-space class="w-200px">
|
||||
<GroupSelect v-model="query.group_ids" multiple :options="groups" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.group_ids" multiple :options="groups" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">所属项目</span>
|
||||
<a-space class="w-200px">
|
||||
<CommonSelect v-model="query.project_ids" :options="projects" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">标签</span>
|
||||
<a-space class="w-320px">
|
||||
<TagSelect v-model="query.tag_ids" :options="tags" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.tag_ids" :options="tags" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="w-84px mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button class="w-84px" size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -77,13 +87,17 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, defineEmits, defineProps } from 'vue';
|
||||
import { fetchAccountTags, fetchAccountGroups, fetchAccountOperators } from '@/api/all/propertyMarketing';
|
||||
import TagSelect from '@/views/property-marketing/media-account/components/tag-select';
|
||||
import GroupSelect from '@/views/property-marketing/media-account/components/group-select';
|
||||
import OperatorSelect from '@/views/property-marketing/media-account/components/operator-select';
|
||||
import {
|
||||
fetchAccountTags,
|
||||
getProjectList,
|
||||
fetchAccountGroups,
|
||||
fetchAccountOperators,
|
||||
} from '@/api/all/propertyMarketing';
|
||||
import StatusSelect from '@/views/property-marketing/media-account/components/status-select';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
import { INITIAL_QUERY, PLATFORM_LIST } from '@/views/property-marketing/media-account/account-manage/constants';
|
||||
import { INITIAL_QUERY } from '@/views/property-marketing/media-account/account-manage/constants';
|
||||
import { MEDIA_ACCOUNT_PLATFORMS } from '@/utils/platform';
|
||||
|
||||
const props = defineProps({
|
||||
query: {
|
||||
@ -97,6 +111,7 @@ const emits = defineEmits('onSearch', 'onReset', 'update:query');
|
||||
const tags = ref([]);
|
||||
const groups = ref([]);
|
||||
const operators = ref([]);
|
||||
const projects = ref([]);
|
||||
|
||||
const handleSearch = () => {
|
||||
emits('update:query', props.query);
|
||||
@ -127,11 +142,18 @@ const getOperators = async () => {
|
||||
operators.value = data;
|
||||
}
|
||||
};
|
||||
const getProjects = async () => {
|
||||
const { code, data } = await getProjectList();
|
||||
if (code === 200) {
|
||||
projects.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getTags();
|
||||
getGroups();
|
||||
getOperators();
|
||||
getProjects();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px" @click="onSubmit">确认</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>确认删除 "{{ groupName }}" 这个分组吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="close">取消</a-button>
|
||||
<a-button size="large" @click="close">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="handleOk"> 去授权 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -92,13 +92,12 @@
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<a-button v-if="modalState === MODAL_STATE.QR_READY" size="large" class="cancel-btn" @click="handleRefreshQrCode">
|
||||
<a-button v-if="modalState === MODAL_STATE.QR_READY" size="large" @click="handleRefreshQrCode">
|
||||
重新生成
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="modalState === MODAL_STATE.SUCCESS || modalState === MODAL_STATE.FAILED"
|
||||
size="large"
|
||||
class="cancel-btn"
|
||||
@click="close"
|
||||
>
|
||||
取消
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="close">稍后再说</a-button>
|
||||
<a-button size="large" @click="close">稍后再说</a-button>
|
||||
<a-button type="primary" size="large" @click="handleOk"> 更新数据 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -1,7 +1,3 @@
|
||||
<!--
|
||||
* @Author: AI
|
||||
* @Date: 2025-06-27
|
||||
-->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
@ -16,7 +12,7 @@
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px" @click="onSubmit">确认</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>确认删除 "{{ tagName }}" 这个标签吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
|
||||
@ -9,6 +9,7 @@ export const INITIAL_QUERY = {
|
||||
operator_id: '',
|
||||
group_ids: [],
|
||||
tag_ids: [],
|
||||
project_ids: [],
|
||||
};
|
||||
|
||||
export const INITIAL_PAGE_INFO = {
|
||||
|
||||
@ -8,19 +8,19 @@
|
||||
<div class="top flex h-64px px-24px py-10px justify-between items-center">
|
||||
<p class="text-18px font-400 lh-26px color-#211F24 title">账号管理</p>
|
||||
<div class="flex items-center">
|
||||
<a-button class="w-112px mr-12px search-btn" size="medium" @click="handleOpenTagsModal">
|
||||
<a-button class="w-112px mr-12px" type="outline" size="medium" @click="handleOpenTagsModal">
|
||||
<template #icon>
|
||||
<img :src="icon3" width="16" height="16" />
|
||||
</template>
|
||||
<template #default>标签管理</template>
|
||||
</a-button>
|
||||
<a-button class="w-112px mr-12px search-btn" size="medium" @click="handleOpenGroupModal">
|
||||
<a-button class="w-112px mr-12px" type="outline" size="medium" @click="handleOpenGroupModal">
|
||||
<template #icon>
|
||||
<img :src="icon2" width="16" height="16" />
|
||||
</template>
|
||||
<template #default>分组管理</template>
|
||||
</a-button>
|
||||
<a-button type="primary" class="w-112px search-btn" size="medium" @click="handleOpenAccountModal">
|
||||
<a-button type="primary" class="w-112px" size="medium" @click="handleOpenAccountModal">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="16" height="16" />
|
||||
</template>
|
||||
@ -70,7 +70,7 @@
|
||||
</template>
|
||||
<div v-else>
|
||||
<a-space v-if="isAbNormalStatus" class="flex items-center">
|
||||
<a-button class="w-96px err-btn" size="mini" @click="handleOpenAbnormalAccount">
|
||||
<a-button type="primary" status="danger" size="mini" @click="handleOpenAbnormalAccount">
|
||||
<template #default>查看异常账号</template>
|
||||
</a-button>
|
||||
</a-space>
|
||||
|
||||
@ -2,16 +2,6 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
.filter-wrap {
|
||||
.top {
|
||||
.title {
|
||||
@ -47,15 +37,6 @@
|
||||
color: #211f24;
|
||||
}
|
||||
}
|
||||
.err-btn {
|
||||
background-color: #f64b31 !important;
|
||||
color: var(--BG-white, #fff);
|
||||
font-family: 'PingFang SC';
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 166.667% */
|
||||
}
|
||||
.operation-btn {
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-25 14:02:40
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model="selectedGroups"
|
||||
:multiple="multiple"
|
||||
size="medium"
|
||||
:placeholder="placeholder"
|
||||
allow-clear
|
||||
:max-tag-count="3"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-option v-for="(item, index) in options" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Array, String, Number],
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '全部',
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const selectedGroups = ref(props.multiple ? [] : '');
|
||||
|
||||
// 监听外部传入的值变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
selectedGroups.value = newVal;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
// 监听内部值变化,向外部发送更新
|
||||
watch(selectedGroups, (newVal) => {
|
||||
emits('update:modelValue', newVal);
|
||||
});
|
||||
|
||||
const handleChange = (value) => {
|
||||
selectedGroups.value = value;
|
||||
emits('change', value);
|
||||
};
|
||||
</script>
|
||||
@ -1,64 +0,0 @@
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-25 14:02:40
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model="selectedOperators"
|
||||
:multiple="multiple"
|
||||
size="medium"
|
||||
:placeholder="placeholder"
|
||||
allow-clear
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-option v-for="(item, index) in options" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Array, String, Number],
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '全部',
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const selectedOperators = ref(props.multiple ? [] : '');
|
||||
|
||||
// 监听外部传入的值变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
selectedOperators.value = newVal;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// 监听内部值变化,向外部发送更新
|
||||
watch(selectedOperators, (newVal) => {
|
||||
emits('update:modelValue', newVal);
|
||||
});
|
||||
|
||||
const handleChange = (value) => {
|
||||
selectedOperators.value = value;
|
||||
emits('change', value);
|
||||
};
|
||||
</script>
|
||||
@ -1,65 +0,0 @@
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-25 14:02:40
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model="selectedTags"
|
||||
:multiple="multiple"
|
||||
size="medium"
|
||||
:placeholder="placeholder"
|
||||
allow-clear
|
||||
:max-tag-count="3"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-option v-for="(item, index) in options" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Array, String, Number],
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '全部',
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const selectedTags = ref(props.multiple ? [] : '');
|
||||
|
||||
// 监听外部传入的值变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
selectedTags.value = newVal;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// 监听内部值变化,向外部发送更新
|
||||
watch(selectedTags, (newVal) => {
|
||||
emits('update:modelValue', newVal);
|
||||
});
|
||||
|
||||
const handleChange = (value) => {
|
||||
selectedTags.value = value;
|
||||
emits('change', value);
|
||||
};
|
||||
</script>
|
||||
@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
title="添加项目"
|
||||
modal-class="add-project-modal"
|
||||
width="960px"
|
||||
:mask-closable="false"
|
||||
@close="onClose"
|
||||
>
|
||||
<div class="content">
|
||||
<a-steps changeable :current="currentStep" @change="setCurrent" class="mb-24px mx-79px">
|
||||
<a-step v-for="(step, index) in STEPS" :key="index">{{ step.label }}</a-step>
|
||||
</a-steps>
|
||||
|
||||
<component :is="activeComp" v-model:formQuery="formQuery" ref="compRef" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-between items-center w-100%">
|
||||
<div>
|
||||
<a-button type="outline" size="medium" @click="onPrev" v-if="!isFirstStep">上一步</a-button>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<a-button size="medium" class="mr-8px" @click="onCancel">取消</a-button>
|
||||
<a-button type="primary" size="medium" @click="onSubmit">{{ isLastStep ? '确认添加' : '下一步' }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { postAddProject, putProject, getProjectDetail } from '@/api/all/propertyMarketing';
|
||||
|
||||
import StepOne from './stepOne.vue';
|
||||
import StepTwo from './stepTwo.vue';
|
||||
import StepThree from './stepThree.vue';
|
||||
import StepFour from './stepFour.vue';
|
||||
|
||||
const STEPS = [
|
||||
{
|
||||
label: '项目信息',
|
||||
index: 1,
|
||||
comp: StepOne,
|
||||
},
|
||||
{
|
||||
label: '关联平台账号',
|
||||
index: 2,
|
||||
comp: StepTwo,
|
||||
},
|
||||
{
|
||||
label: '关联渠道账户',
|
||||
index: 3,
|
||||
comp: StepThree,
|
||||
},
|
||||
{
|
||||
label: '关联内容稿件',
|
||||
index: 4,
|
||||
comp: StepFour,
|
||||
},
|
||||
];
|
||||
const INITIAL_QUERY = {
|
||||
name: '',
|
||||
budget: '',
|
||||
target: '',
|
||||
background: '',
|
||||
media_account_ids: [],
|
||||
placement_account_ids: [],
|
||||
work_ids: [],
|
||||
};
|
||||
|
||||
const update = inject('update');
|
||||
|
||||
const visible = ref(false);
|
||||
const currentStep = ref(1);
|
||||
const formQuery = ref(cloneDeep(INITIAL_QUERY));
|
||||
const compRef = ref(null);
|
||||
const projectId = ref(null);
|
||||
|
||||
const isFirstStep = computed(() => currentStep.value === 1);
|
||||
const isEdit = computed(() => projectId.value);
|
||||
const isLastStep = computed(() => currentStep.value === STEPS.length);
|
||||
const activeComp = computed(() => STEPS.find((v) => v.index === currentStep.value)?.comp ?? null);
|
||||
|
||||
const open = (id = null) => {
|
||||
projectId.value = id;
|
||||
|
||||
if (id) {
|
||||
getDetail();
|
||||
}
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
const getDetail = (id) => {
|
||||
getProjectDetail(projectId.value).then((res) => {
|
||||
if (res.code === 200) {
|
||||
formQuery.value = res.data;
|
||||
}
|
||||
});
|
||||
};
|
||||
const onClose = () => {
|
||||
currentStep.value = 1;
|
||||
formQuery.value = cloneDeep(INITIAL_QUERY);
|
||||
projectId.value = '';
|
||||
compRef.value?.reset?.();
|
||||
|
||||
visible.value = false;
|
||||
};
|
||||
const onCancel = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (isFirstStep.value) {
|
||||
const valid = await compRef.value.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastStep.value) {
|
||||
isEdit.value ? handleEdit() : handleAdd();
|
||||
} else {
|
||||
currentStep.value++;
|
||||
}
|
||||
};
|
||||
const handleAdd = () => {
|
||||
postAddProject(formQuery.value).then((res) => {
|
||||
if (res.code === 200) {
|
||||
onClose();
|
||||
update();
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleEdit = () => {
|
||||
putProject({ id: projectId.value, ...formQuery.value }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
onClose();
|
||||
update();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setCurrent = async (current) => {
|
||||
if (isFirstStep.value) {
|
||||
const valid = await compRef.value.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
currentStep.value = current;
|
||||
};
|
||||
const onPrev = () => {
|
||||
currentStep.value--;
|
||||
};
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<div class="table-wrap flex h-448px">
|
||||
<div class="left flex-1 pr-12px flex flex-col">
|
||||
<div class="flex items-center mb-16px">
|
||||
<a-input
|
||||
v-model="query.uid"
|
||||
class="w-160px mr-16px"
|
||||
placeholder="搜索序号"
|
||||
size="medium"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-input
|
||||
v-model="query.title"
|
||||
class="w-220px mr-16px"
|
||||
placeholder="搜索内容稿件标题"
|
||||
size="medium"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
|
||||
<a-select
|
||||
v-model="query.uploader_id"
|
||||
size="medium"
|
||||
placeholder="选择上传人员"
|
||||
class="w-160px"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<a-option v-for="(item, index) in uploaders" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name || '-' }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<a-table
|
||||
ref="tableRef"
|
||||
:data="dataSource"
|
||||
column-resizable
|
||||
row-key="id"
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:scroll="{ x: '100%', y: '100%' }"
|
||||
class="flex-1 overflow-hidden"
|
||||
:selected-keys="selectedRowKeys"
|
||||
bordered
|
||||
@select="handleSelect"
|
||||
@select-all="handleSelectAll"
|
||||
>
|
||||
<template #empty>
|
||||
<NoData text="暂无账户" />
|
||||
</template>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in TABLE_COLUMNS"
|
||||
:key="column.dataIndex"
|
||||
:data-index="column.dataIndex"
|
||||
:fixed="column.fixed"
|
||||
:width="column.width"
|
||||
:min-width="column.minWidth"
|
||||
:sortable="column.sortable"
|
||||
:align="column.align"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{{ column.title }}</span>
|
||||
<a-tooltip v-if="column.tooltip" :content="column.tooltip" position="top">
|
||||
<icon-question-circle class="tooltip-icon color-#737478" size="16" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell="{ record }">
|
||||
<template v-if="column.dataIndex === 'created_at'">
|
||||
{{ exactFormatTime(record.created_at) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ formatTableField(column, record, true) }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<div class="right w-320px px-12px flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<p class="mb-16px s1">{{ `已选择(${selectedRows?.length ?? 0})` }}</p>
|
||||
<a-button type="text" @click="onClearSelect" v-if="selectedRows.length">清空</a-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto overflow-x-hidden">
|
||||
<template v-if="selectedRows?.length">
|
||||
<div class="tag-item mb-8px" v-for="item in selectedRows" :key="item.id">
|
||||
<a-tooltip :content="item.name">
|
||||
<p class="name mr-4px">{{ item.name || '-' }}</p>
|
||||
</a-tooltip>
|
||||
<icon-close size="12" class="color-#3C4043 cursor-pointer flex-shrink-0" @click="onDelete(item)" />
|
||||
</div>
|
||||
</template>
|
||||
<NoData v-else text="暂无账户" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||
|
||||
import { getPlacementAccountOperators, getWorksList } from '@/api/all/propertyMarketing';
|
||||
import { getUserList } from '@/api/all/common';
|
||||
|
||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
|
||||
const TABLE_COLUMNS = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'uid',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '内容稿件标题',
|
||||
dataIndex: 'title',
|
||||
},
|
||||
{
|
||||
title: '上传时间',
|
||||
dataIndex: 'created_at',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '上传人员',
|
||||
dataIndex: 'uploader.name',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
const emit = defineEmits(['update:formQuery']);
|
||||
|
||||
const props = defineProps({
|
||||
formQuery: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const { dataSource, selectedRowKeys, selectedRows, rowSelection, handleSelect, handleSelectAll } =
|
||||
useTableSelectionWithPagination({
|
||||
onSelectChange: () => {
|
||||
updateFormQuery();
|
||||
},
|
||||
});
|
||||
|
||||
const query = ref({
|
||||
uid: '',
|
||||
uploader_id: '',
|
||||
title: '',
|
||||
});
|
||||
const uploaders = ref([]);
|
||||
const allData = ref([]);
|
||||
|
||||
const updateFormQuery = () => {
|
||||
emit('update:formQuery', {
|
||||
...props.formQuery,
|
||||
work_ids: selectedRowKeys.value,
|
||||
});
|
||||
};
|
||||
const handleSearch = () => {
|
||||
const { uid, title, uploader_id } = query.value;
|
||||
dataSource.value = allData.value.filter((item) => {
|
||||
const uinMatch = uid === '' ? true : item.uid.includes(uid);
|
||||
const titleMatch = title === '' ? true : item.title === title;
|
||||
const operatorIdMatch = uploader_id === '' ? true : item.uploader?.id === uploader_id;
|
||||
return uinMatch && titleMatch && operatorIdMatch;
|
||||
});
|
||||
};
|
||||
|
||||
const getUsers = async () => {
|
||||
const { code, data } = await getUserList();
|
||||
if (code === 200) {
|
||||
uploaders.value = data.map( v => ({
|
||||
...v,
|
||||
name: v.name || v.mobile
|
||||
}));
|
||||
|
||||
console.log(uploaders.value);
|
||||
}
|
||||
};
|
||||
const getTableData = async () => {
|
||||
const { code, data } = await getWorksList();
|
||||
if (code === 200) {
|
||||
allData.value = data ?? [];
|
||||
dataSource.value = data ?? [];
|
||||
initSelect();
|
||||
}
|
||||
};
|
||||
const initSelect = () => {
|
||||
if (props.formQuery.work_ids?.length) {
|
||||
selectedRowKeys.value = props.formQuery.work_ids;
|
||||
selectedRows.value = dataSource.value.filter((v) => selectedRowKeys.value.includes(v.id));
|
||||
}
|
||||
};
|
||||
|
||||
const onClearSelect = () => {
|
||||
selectedRowKeys.value = [];
|
||||
selectedRows.value = [];
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
const onDelete = (item) => {
|
||||
const { id } = item;
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((v) => v !== id);
|
||||
selectedRows.value = selectedRows.value.filter((v) => v.id !== id);
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getUsers();
|
||||
getTableData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.table-wrap {
|
||||
.s1 {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
.left {
|
||||
border-right: 1px solid var(--Border-2, #e6e6e8);
|
||||
:deep(.arco-table) {
|
||||
}
|
||||
}
|
||||
.right {
|
||||
.tag-item {
|
||||
max-width: 100%;
|
||||
width: fit-content;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
padding: 0px 8px;
|
||||
align-items: center;
|
||||
border-radius: 2px;
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
.name {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px; /* 157.143% */
|
||||
flex: 1;
|
||||
@include ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<a-form ref="formRef" :model="formQuery" :rules="rules" layout="horizontal" auto-label-width class="h-448px">
|
||||
<a-form-item label="项目名称" required field="name">
|
||||
<a-input v-model="formQuery.name" placeholder="请输入项目名称" size="large" class="!w-400px" />
|
||||
</a-form-item>
|
||||
<a-form-item label="项目预算" field="budget">
|
||||
<a-input v-model="formQuery.budget" placeholder="请输入项目预算" size="large" class="!w-400px" />
|
||||
</a-form-item>
|
||||
<a-form-item label="项目目标" field="target">
|
||||
<a-textarea
|
||||
v-model="formQuery.target"
|
||||
placeholder="请输入项目目标"
|
||||
:max-length="500"
|
||||
show-word-limit
|
||||
class="h-154px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="项目背景" field="background">
|
||||
<a-textarea
|
||||
v-model="formQuery.background"
|
||||
placeholder="请输入项目背景"
|
||||
:max-length="500"
|
||||
show-word-limit
|
||||
class="h-154px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
formQuery: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const rules = {
|
||||
name: [{ required: true, message: '请输入项目名称' }],
|
||||
};
|
||||
|
||||
const validate = async () => {
|
||||
const errors = await formRef.value.validate();
|
||||
return !errors
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
formRef.value.resetFields();
|
||||
};
|
||||
|
||||
defineExpose({ validate, reset });
|
||||
</script>
|
||||
@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<div class="table-wrap flex h-448px">
|
||||
<div class="left flex-1 pr-12px flex flex-col">
|
||||
<div class="flex items-center mb-16px">
|
||||
<a-input
|
||||
v-model="query.name"
|
||||
class="w-220px mr-16px"
|
||||
placeholder="搜索账户"
|
||||
size="medium"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-select
|
||||
v-model="query.platform"
|
||||
class="mr-16px w-160px"
|
||||
size="medium"
|
||||
placeholder="选择平台"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<a-option
|
||||
v-for="(item, index) in PLATFORM_LIST"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
>{{ item.label }}</a-option
|
||||
>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model="query.operator_id"
|
||||
size="medium"
|
||||
placeholder="选择运营人员"
|
||||
class="w-160px"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<a-option v-for="(item, index) in operators" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<a-table
|
||||
ref="tableRef"
|
||||
:data="dataSource"
|
||||
column-resizable
|
||||
row-key="id"
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:scroll="{ x: '100%', y: '100%' }"
|
||||
class="flex-1 overflow-hidden"
|
||||
:selected-keys="selectedRowKeys"
|
||||
bordered
|
||||
@select="handleSelect"
|
||||
@select-all="handleSelectAll"
|
||||
>
|
||||
<template #empty>
|
||||
<NoData text="暂无账户"/>
|
||||
</template>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in TABLE_COLUMNS"
|
||||
:key="column.dataIndex"
|
||||
:data-index="column.dataIndex"
|
||||
:fixed="column.fixed"
|
||||
:width="column.width"
|
||||
:min-width="column.minWidth"
|
||||
:sortable="column.sortable"
|
||||
:align="column.align"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{{ column.title }}</span>
|
||||
<a-tooltip v-if="column.tooltip" :content="column.tooltip" position="top">
|
||||
<icon-question-circle class="tooltip-icon color-#737478" size="16" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell="{ record }">
|
||||
<template v-if="column.dataIndex === 'platform'">
|
||||
<img :src="getPutAccountPlatformLogo(record.platform)" width="19" height="19" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ formatTableField(column, record, true) }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<div class="right w-320px px-12px flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<p class="mb-16px s1">{{ `已选择(${selectedRows?.length ?? 0})` }}</p>
|
||||
<a-button type="text" @click="onClearSelect" v-if="selectedRows.length">清空</a-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto overflow-x-hidden">
|
||||
<template v-if="selectedRows?.length">
|
||||
<div class="tag-item mb-8px" v-for="item in selectedRows" :key="item.id">
|
||||
<a-tooltip :content="item.name">
|
||||
<p class="name mr-4px">{{ item.name || '-' }}</p>
|
||||
</a-tooltip>
|
||||
<icon-close size="12" class="color-#3C4043 cursor-pointer flex-shrink-0" @click="onDelete(item)" />
|
||||
</div>
|
||||
</template>
|
||||
<NoData v-else text="暂无账户" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { PLATFORM_LIST, getPutAccountPlatformLogo } from '@/utils/platform';
|
||||
import { formatTableField } from '@/utils/tools';
|
||||
|
||||
import { getPlacementAccountOperators, getPlacementAccountsList } from '@/api/all/propertyMarketing';
|
||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
|
||||
const TABLE_COLUMNS = [
|
||||
{
|
||||
title: '账号名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '渠道',
|
||||
dataIndex: 'platform',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '运营人员',
|
||||
dataIndex: 'operator.name',
|
||||
width: 140,
|
||||
},
|
||||
];
|
||||
const emit = defineEmits(['update:formQuery']);
|
||||
|
||||
const props = defineProps({
|
||||
formQuery: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const { dataSource, selectedRowKeys, selectedRows, rowSelection, handleSelect, handleSelectAll } =
|
||||
useTableSelectionWithPagination({
|
||||
onSelectChange: () => {
|
||||
updateFormQuery();
|
||||
},
|
||||
});
|
||||
|
||||
const query = ref({
|
||||
name: '',
|
||||
operator_id: '',
|
||||
platform: '',
|
||||
});
|
||||
const operators = ref([]);
|
||||
const allData = ref([]);
|
||||
|
||||
const updateFormQuery = () => {
|
||||
emit('update:formQuery', {
|
||||
...props.formQuery,
|
||||
placement_account_ids: selectedRowKeys.value,
|
||||
});
|
||||
};
|
||||
const handleSearch = () => {
|
||||
const { name, platform, operator_id } = query.value;
|
||||
dataSource.value = allData.value.filter((item) => {
|
||||
const nameMatch = name === '' ? true : item.name.includes(name);
|
||||
const platformMatch = platform === '' ? true : item.platform === platform;
|
||||
const operatorIdMatch = operator_id === '' ? true : item.operator_id === operator_id;
|
||||
return nameMatch && platformMatch && operatorIdMatch;
|
||||
});
|
||||
};
|
||||
|
||||
const getOperators = async () => {
|
||||
const { code, data } = await getPlacementAccountOperators();
|
||||
if (code === 200) {
|
||||
operators.value = data;
|
||||
}
|
||||
};
|
||||
const getTableData = async () => {
|
||||
const { code, data } = await getPlacementAccountsList();
|
||||
if (code === 200) {
|
||||
allData.value = data ?? [];
|
||||
dataSource.value = data ?? [];
|
||||
initSelect();
|
||||
}
|
||||
};
|
||||
const initSelect = () => {
|
||||
if (props.formQuery.placement_account_ids?.length) {
|
||||
selectedRowKeys.value = props.formQuery.placement_account_ids;
|
||||
selectedRows.value = dataSource.value.filter((v) => selectedRowKeys.value.includes(v.id));
|
||||
}
|
||||
};
|
||||
|
||||
const onClearSelect = () => {
|
||||
selectedRowKeys.value = [];
|
||||
selectedRows.value = [];
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
const onDelete = (item) => {
|
||||
const { id } = item;
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((v) => v !== id);
|
||||
selectedRows.value = selectedRows.value.filter((v) => v.id !== id);
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getOperators();
|
||||
getTableData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.table-wrap {
|
||||
.s1 {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
.left {
|
||||
border-right: 1px solid var(--Border-2, #e6e6e8);
|
||||
:deep(.arco-table) {
|
||||
}
|
||||
}
|
||||
.right {
|
||||
.tag-item {
|
||||
max-width: 100%;
|
||||
width: fit-content;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
padding: 0px 8px;
|
||||
align-items: center;
|
||||
border-radius: 2px;
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
.name {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px; /* 157.143% */
|
||||
flex: 1;
|
||||
@include ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div class="table-wrap flex h-448px">
|
||||
<div class="left flex-1 pr-12px flex flex-col">
|
||||
<div class="flex items-center mb-16px">
|
||||
<a-input
|
||||
v-model="query.name"
|
||||
class="w-220px mr-16px"
|
||||
placeholder="搜索账号"
|
||||
size="medium"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-select
|
||||
v-model="query.platform"
|
||||
class="mr-16px w-160px"
|
||||
size="medium"
|
||||
placeholder="选择平台"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<a-option
|
||||
v-for="(item, index) in MEDIA_ACCOUNT_PLATFORMS"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
>{{ item.label }}</a-option
|
||||
>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-model="query.operator_id"
|
||||
size="medium"
|
||||
placeholder="选择运营人员"
|
||||
class="w-160px"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<a-option v-for="(item, index) in operators" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<a-table
|
||||
ref="tableRef"
|
||||
:data="dataSource"
|
||||
column-resizable
|
||||
row-key="id"
|
||||
:row-selection="rowSelection"
|
||||
:pagination="false"
|
||||
:scroll="{ x: '100%', y: '100%' }"
|
||||
class="flex-1 overflow-hidden"
|
||||
:selected-keys="selectedRowKeys"
|
||||
bordered
|
||||
@select="handleSelect"
|
||||
@select-all="handleSelectAll"
|
||||
>
|
||||
<template #empty>
|
||||
<NoData text="暂无账号"/>
|
||||
</template>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in TABLE_COLUMNS"
|
||||
:key="column.dataIndex"
|
||||
:data-index="column.dataIndex"
|
||||
:fixed="column.fixed"
|
||||
:width="column.width"
|
||||
:min-width="column.minWidth"
|
||||
:sortable="column.sortable"
|
||||
:align="column.align"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{{ column.title }}</span>
|
||||
<a-tooltip v-if="column.tooltip" :content="column.tooltip" position="top">
|
||||
<icon-question-circle class="tooltip-icon color-#737478" size="16" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell="{ record }">
|
||||
<template v-if="column.dataIndex === 'platform'">
|
||||
<img :src="getMediaAccountPlatformLogo(record.platform)" width="19" height="19" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ formatTableField(column, record, true) }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<div class="right w-320px px-12px flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<p class="mb-16px s1">{{ `已选择(${selectedRows?.length ?? 0})` }}</p>
|
||||
<a-button type="text" @click="onClearSelect" v-if="selectedRows.length">清空</a-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
<div class="flex flex-wrap" v-if="selectedRows?.length">
|
||||
<div class="tag-item mr-8px mb-8px" v-for="item in selectedRows" :key="item.id">
|
||||
<span class="name mr-4px">{{ item.name || '-' }}</span>
|
||||
<icon-close size="12" class="color-#3C4043 cursor-pointer" @click="onDelete(item)" />
|
||||
</div>
|
||||
</div>
|
||||
<NoData v-else text="暂无账号" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { MEDIA_ACCOUNT_PLATFORMS, getMediaAccountPlatformLogo } from '@/utils/platform';
|
||||
import { formatTableField } from '@/utils/tools';
|
||||
|
||||
import { fetchAccountOperators, getMediaAccountList } from '@/api/all/propertyMarketing';
|
||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
|
||||
const TABLE_COLUMNS = [
|
||||
{
|
||||
title: '账号名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '平台',
|
||||
dataIndex: 'platform',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '运营人员',
|
||||
dataIndex: 'operator.name',
|
||||
width: 140,
|
||||
},
|
||||
];
|
||||
const emit = defineEmits(['update:formQuery']);
|
||||
|
||||
const props = defineProps({
|
||||
formQuery: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const { dataSource, selectedRowKeys, selectedRows, rowSelection, handleSelect, handleSelectAll } =
|
||||
useTableSelectionWithPagination({
|
||||
onSelectChange: () => {
|
||||
updateFormQuery();
|
||||
},
|
||||
});
|
||||
|
||||
const query = ref({
|
||||
name: '',
|
||||
operator_id: '',
|
||||
platform: '',
|
||||
});
|
||||
const operators = ref([]);
|
||||
const allData = ref([]);
|
||||
|
||||
const updateFormQuery = () => {
|
||||
emit('update:formQuery', {
|
||||
...props.formQuery,
|
||||
media_account_ids: selectedRowKeys.value,
|
||||
});
|
||||
};
|
||||
const handleSearch = () => {
|
||||
const { name, platform, operator_id } = query.value;
|
||||
dataSource.value = allData.value.filter((item) => {
|
||||
const nameMatch = name === '' ? true : item.name.includes(name);
|
||||
const platformMatch = platform === '' ? true : item.platform === platform;
|
||||
const operatorIdMatch = operator_id === '' ? true : item.operator_id === operator_id;
|
||||
return nameMatch && platformMatch && operatorIdMatch;
|
||||
});
|
||||
};
|
||||
|
||||
const getOperators = async () => {
|
||||
const { code, data } = await fetchAccountOperators();
|
||||
if (code === 200) {
|
||||
operators.value = data;
|
||||
}
|
||||
};
|
||||
const getTableData = async () => {
|
||||
const { code, data } = await getMediaAccountList();
|
||||
if (code === 200) {
|
||||
allData.value = data ?? [];
|
||||
dataSource.value = data ?? [];
|
||||
initSelect();
|
||||
}
|
||||
};
|
||||
const initSelect = () => {
|
||||
if (props.formQuery.media_account_ids?.length) {
|
||||
selectedRowKeys.value = props.formQuery.media_account_ids;
|
||||
selectedRows.value = dataSource.value.filter((v) => selectedRowKeys.value.includes(v.id));
|
||||
}
|
||||
};
|
||||
|
||||
const onClearSelect = () => {
|
||||
selectedRowKeys.value = [];
|
||||
selectedRows.value = [];
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
const onDelete = (item) => {
|
||||
const { id } = item;
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((v) => v !== id);
|
||||
selectedRows.value = selectedRows.value.filter((v) => v.id !== id);
|
||||
updateFormQuery();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getOperators();
|
||||
getTableData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.table-wrap {
|
||||
.s1 {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
.left {
|
||||
border-right: 1px solid var(--Border-2, #e6e6e8);
|
||||
:deep(.arco-table) {
|
||||
}
|
||||
}
|
||||
.right {
|
||||
.tag-item {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
padding: 0px 8px;
|
||||
align-items: center;
|
||||
border-radius: 2px;
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
.name {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: font-family-regular;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px; /* 157.143% */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,3 @@
|
||||
.add-project-modal {
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-25 14:02:40
|
||||
-->
|
||||
<template>
|
||||
<div class="filter-wrap px-24px pt-12px pb-24px">
|
||||
<div class="filter-row flex">
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">项目名称</span>
|
||||
<a-space size="medium">
|
||||
<a-input
|
||||
v-model="query.name"
|
||||
class="w-240px"
|
||||
placeholder="请搜索..."
|
||||
size="medium"
|
||||
allow-clear
|
||||
@change="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<icon-search />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
<template #default>重置</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineEmits, defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
query: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits('onSearch', 'onReset', 'update:query');
|
||||
|
||||
const handleSearch = () => {
|
||||
emits('update:query', props.query);
|
||||
nextTick(() => {
|
||||
emits('onSearch');
|
||||
});
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
emits('onReset');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './style.scss';
|
||||
</style>
|
||||
@ -0,0 +1,23 @@
|
||||
.filter-wrap {
|
||||
.filter-row {
|
||||
.filter-row-item {
|
||||
&:not(:last-child) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
.label {
|
||||
margin-right: 8px;
|
||||
color: #211f24;
|
||||
font-family: $font-family-regular;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
line-height: 22px; /* 157.143% */
|
||||
}
|
||||
:deep(.arco-space-item) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-28 10:33:06
|
||||
*/
|
||||
export const TABLE_COLUMNS = [
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'name',
|
||||
width: 240,
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '项目预算',
|
||||
dataIndex: 'budget',
|
||||
width: 180,
|
||||
prefix: "¥"
|
||||
},
|
||||
{
|
||||
title: '关联平台账号',
|
||||
dataIndex: 'media_account_count',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '关联渠道账户',
|
||||
dataIndex: 'placement_account_count',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '关联内容稿件',
|
||||
dataIndex: 'work_count',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'create_at',
|
||||
width: 180,
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-26 17:44:16
|
||||
-->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
title="删除项目"
|
||||
width="480px"
|
||||
modal-class="project-manage-modal"
|
||||
@close="onClose"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<img :src="icon1" width="20" height="20" class="mr-12px" />
|
||||
<span>确认删除 {{ projectName }} 这个项目吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { deleteProject } from '@/api/all/propertyMarketing';
|
||||
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||
|
||||
const update = inject('update');
|
||||
|
||||
const visible = ref(false);
|
||||
const projectId = ref(null);
|
||||
const projectName = ref('');
|
||||
|
||||
const isBatch = computed(() => Array.isArray(projectId.value));
|
||||
|
||||
function onClose() {
|
||||
visible.value = false;
|
||||
projectId.value = null;
|
||||
projectName.value = '';
|
||||
}
|
||||
|
||||
const open = (record) => {
|
||||
const { id = null, name = '' } = record;
|
||||
projectId.value = id;
|
||||
projectName.value = name;
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
async function onDelete() {
|
||||
const { code } = await deleteProject(projectId.value);
|
||||
if (code === 200) {
|
||||
AMessage.success('删除成功');
|
||||
update()
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<a-table
|
||||
ref="tableRef"
|
||||
:data="dataSource"
|
||||
row-key="id"
|
||||
column-resizable
|
||||
:pagination="false"
|
||||
:scroll="{ x: '100%' }"
|
||||
class="flex-1 project-table w-100%"
|
||||
bordered
|
||||
@sorter-change="handleSorterChange"
|
||||
>
|
||||
<template #empty>
|
||||
<NoData text="暂无项目"/>
|
||||
</template>
|
||||
<template #columns>
|
||||
<a-table-column
|
||||
v-for="column in TABLE_COLUMNS"
|
||||
:key="column.dataIndex"
|
||||
:data-index="column.dataIndex"
|
||||
:fixed="column.fixed"
|
||||
:width="column.width"
|
||||
:min-width="column.minWidth"
|
||||
:sortable="column.sortable"
|
||||
:align="column.align"
|
||||
ellipsis
|
||||
tooltip
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{{ column.title }}</span>
|
||||
<a-tooltip v-if="column.tooltip" :content="column.tooltip" position="top">
|
||||
<icon-question-circle class="tooltip-icon color-#737478" size="16" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'create_at'" #cell="{ record }">
|
||||
{{ exactFormatTime(record.create_at) }}
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'" #cell="{ record }">
|
||||
<div class="flex items-center">
|
||||
<img class="mr-8px cursor-pointer" :src="icon1" width="14" height="14" @click="onDelete(record)" />
|
||||
<a-button type="outline" size="mini" @click="onEdit(record)">编辑</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else #cell="{ record }">
|
||||
{{ formatTableField(column, record, true) }}
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||
import { TABLE_COLUMNS } from './constants';
|
||||
|
||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||
|
||||
const emits = defineEmits(['edit', 'sorterChange', 'delete']);
|
||||
|
||||
const props = defineProps({
|
||||
dataSource: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const tableRef = ref(null);
|
||||
|
||||
// 处理排序变化
|
||||
const handleSorterChange = (column, order) => {
|
||||
emits('sorterChange', column, order === 'ascend' ? 'asc' : 'desc');
|
||||
};
|
||||
const onDelete = (item) => {
|
||||
emits('delete', item);
|
||||
};
|
||||
const onEdit = (item) => {
|
||||
emits('edit', item);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './style.scss';
|
||||
</style>
|
||||
@ -0,0 +1,10 @@
|
||||
.project-table {
|
||||
.cts {
|
||||
color: var(--Text-1, #211f24);
|
||||
font-family: $font-family-medium;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
export const INITIAL_QUERY = {
|
||||
name: '',
|
||||
sort_column: undefined,
|
||||
sort_order: undefined,
|
||||
};
|
||||
@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div class="project-list-wrap">
|
||||
<div class="filter-wrap bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid mb-16px">
|
||||
<div class="top flex h-64px px-24px py-10px justify-between items-center">
|
||||
<p class="text-18px font-400 lh-26px color-#211F24 title">项目列表</p>
|
||||
<div class="flex items-center">
|
||||
<a-button type="primary" class="w-112px search-btn" size="medium" @click="handleOpenAddProjectModal">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="16" height="16" />
|
||||
</template>
|
||||
<template #default>添加项目</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<FilterBlock v-model:query="query" @onSearch="handleSearch" @onReset="handleReset" />
|
||||
</div>
|
||||
<div
|
||||
class="table-wrap bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid px-24px py-24px flex-1 flex flex-col"
|
||||
>
|
||||
<ProjectTable
|
||||
:dataSource="dataSource"
|
||||
@sorterChange="handleSorterChange"
|
||||
@delete="handleDelete"
|
||||
@edit="handleEdit"
|
||||
/>
|
||||
<div v-if="pageInfo.total > 0" class="pagination-box">
|
||||
<a-pagination
|
||||
:total="pageInfo.total"
|
||||
size="mini"
|
||||
show-total
|
||||
show-jumper
|
||||
show-page-size
|
||||
:current="pageInfo.page"
|
||||
:page-size="pageInfo.page_size"
|
||||
@change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AddProjectModal ref="addProjectModalRef" />
|
||||
<DeleteProjectModal ref="deleteProjectModalRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { INITIAL_QUERY } from './constants';
|
||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
import { getProjects } from '@/api/all/propertyMarketing';
|
||||
|
||||
import FilterBlock from './components/filter-block';
|
||||
import ProjectTable from './components/project-table';
|
||||
import AddProjectModal from './components/add-project-modal';
|
||||
import DeleteProjectModal from './components/project-table/delete-project-modal.vue';
|
||||
|
||||
import icon1 from '@/assets/img/media-account/icon-add.png';
|
||||
|
||||
const { dataSource, pageInfo, onPageChange, onPageSizeChange, resetPageInfo } = useTableSelectionWithPagination({
|
||||
onPageChange: () => {
|
||||
getData();
|
||||
},
|
||||
onPageSizeChange: () => {
|
||||
getData();
|
||||
},
|
||||
});
|
||||
|
||||
const addProjectModalRef = ref(null);
|
||||
const deleteProjectModalRef = ref(null);
|
||||
|
||||
const query = ref(cloneDeep(INITIAL_QUERY));
|
||||
|
||||
const getData = async () => {
|
||||
const { page, page_size } = pageInfo.value;
|
||||
const { code, data } = await getProjects({
|
||||
...query.value,
|
||||
page,
|
||||
page_size,
|
||||
});
|
||||
if (code === 200) {
|
||||
dataSource.value = data?.data ?? [];
|
||||
pageInfo.value.total = data.total;
|
||||
}
|
||||
};
|
||||
const handleSearch = () => {
|
||||
reload();
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
resetPageInfo();
|
||||
query.value = cloneDeep(INITIAL_QUERY);
|
||||
reload();
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
pageInfo.value.page = 1;
|
||||
getData();
|
||||
};
|
||||
|
||||
const handleOpenAddProjectModal = () => {
|
||||
addProjectModalRef.value?.open();
|
||||
};
|
||||
const handleSorterChange = (column, order) => {
|
||||
query.value.sort_column = column;
|
||||
query.value.sort_order = order;
|
||||
reload();
|
||||
};
|
||||
|
||||
const handleDelete = (item) => {
|
||||
const { id, name } = item;
|
||||
deleteProjectModalRef.value?.open({ id, name: `“${name}”` });
|
||||
};
|
||||
const handleEdit = (item) => {
|
||||
addProjectModalRef.value?.open(item.id);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getData();
|
||||
});
|
||||
|
||||
provide('update', getData);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './style.scss';
|
||||
</style>
|
||||
@ -0,0 +1,29 @@
|
||||
.project-list-wrap {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.filter-wrap {
|
||||
.top {
|
||||
.title {
|
||||
font-family: $font-family-medium;
|
||||
font-style: normal;
|
||||
}
|
||||
:deep(.arco-btn) {
|
||||
.arco-btn-icon {
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.table-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.pagination-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 16px 24px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,7 +32,7 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">运营人员</span>
|
||||
<a-space class="w-160px">
|
||||
<OperatorSelect v-model="query.operator_id" :options="operators" />
|
||||
<CommonSelect v-model="query.operator_id" :multiple="false" :options="operators" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
@ -43,13 +43,13 @@
|
||||
<a-range-picker v-model="query.data_time" size="medium" allow-clear format="YYYY-MM-DD" class="w-100%" />
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -74,13 +74,13 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import EchartsItem from './components/echarts-item/index';
|
||||
import { PLATFORM_LIST } from '../common_constants';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import {
|
||||
getPlacementAccountsTrend,
|
||||
getPlacementAccountProjectsTrend,
|
||||
fetchAccountOperators,
|
||||
} from '@/api/all/propertyMarketing';
|
||||
import OperatorSelect from '@/views/property-marketing/media-account/components/operator-select/index.vue';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
import AccountSelect from '@/views/components/common/AccountSelect.vue';
|
||||
import PlanSelect from '@/views/components/common/PlanSelect.vue';
|
||||
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<a-button class="w-110px search-btn mr-12px" size="medium" @click="handleExport">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleExport">
|
||||
<template #icon> <icon-download /> </template>
|
||||
<template #default>导出数据</template>
|
||||
</a-button>
|
||||
<a-button class="w-110px search-btn" size="medium" @click="openCustomColumn">
|
||||
<a-button type="outline" size="medium" @click="openCustomColumn">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="14" height="14" />
|
||||
</template>
|
||||
@ -106,7 +106,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'" #cell="{ record }">
|
||||
<a-button type="outline" size="small" class="search-btn" @click="handleDetail(record)">详情</a-button>
|
||||
<a-button type="outline" size="small" @click="handleDetail(record)">详情</a-button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="column.isRateField" #cell="{ record }">
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<div v-if="!isAccountTab" class="filter-row-item flex items-center">
|
||||
<span class="label">计划分组</span>
|
||||
<a-space class="w-200px">
|
||||
<group-select v-model="query.group_ids" multiple :options="groups" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.group_ids" multiple :options="groups" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
@ -31,7 +31,7 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">运营人员</span>
|
||||
<a-space class="w-160px">
|
||||
<OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.operator_id" :multiple="false" :options="operators" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
@ -55,13 +55,13 @@
|
||||
/>
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -78,10 +78,9 @@ import {
|
||||
getPlacementAccountsList,
|
||||
getPlacementAccountOperators,
|
||||
} from '@/api/all/propertyMarketing';
|
||||
import GroupSelect from '../group-select';
|
||||
|
||||
import OperatorSelect from '@/views/property-marketing/put-account/components/operator-select';
|
||||
import StatusSelect from '@/views/property-marketing/put-account/components/status-select';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
import StatusSelect from '@/views/property-marketing/media-account/components/status-select';
|
||||
import AccountSelect from '@/views/property-marketing/put-account/components/account-select';
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px" @click="onSubmit">确认</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>确认删除 "{{ groupName }}" 这个分组吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<a-button class="w-110px search-btn mr-12px" size="medium" @click="handleExport">
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleExport">
|
||||
<template #icon> <icon-download /> </template>
|
||||
<template #default>导出数据</template>
|
||||
</a-button>
|
||||
<a-button class="w-110px search-btn" size="medium" @click="openCustomColumn">
|
||||
<a-button type="outline" size="medium" @click="openCustomColumn">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="14" height="14" />
|
||||
</template>
|
||||
@ -106,7 +106,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'" #cell="{ record }">
|
||||
<a-button type="outline" size="small" class="search-btn" @click="handleDetail(record)">详情</a-button>
|
||||
<a-button type="outline" size="small" @click="handleDetail(record)">详情</a-button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="column.isRateField" #cell="{ record }">
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<a-tab-pane key="1" title="账户"></a-tab-pane>
|
||||
<a-tab-pane key="2" title="计划"></a-tab-pane>
|
||||
<template v-if="!isAccountTab" #extra>
|
||||
<a-button class="w-112px mr-12px search-btn flex items-center" size="medium" @click="handleOpenGroupModal">
|
||||
<a-button type="outline" class="mr-12px flex items-center" size="medium" @click="handleOpenGroupModal">
|
||||
<template #icon>
|
||||
<img :src="icon2" width="16" height="16" />
|
||||
</template>
|
||||
|
||||
@ -2,16 +2,6 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
.filter-wrap {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e6e6e8;
|
||||
|
||||
@ -2,10 +2,6 @@
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-26 17:44:16
|
||||
-->
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-26 17:23:52
|
||||
-->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
@ -19,7 +15,7 @@
|
||||
<span>确认删除 {{ accountName }} 这个账户吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="large" @click="onDelete"
|
||||
>确认删除</a-button
|
||||
>
|
||||
|
||||
@ -41,6 +41,30 @@
|
||||
<span class="label">运营人员</span>
|
||||
<span class="cts">{{ item.operator?.name }}</span>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<span class="label">所属项目</span>
|
||||
<span v-if="!item.projects.length" class="cts">-</span>
|
||||
<div v-else class="flex items-center">
|
||||
<a-tooltip
|
||||
v-if="item.projects.length > 2"
|
||||
position="bottom"
|
||||
:content="
|
||||
item.projects
|
||||
.slice(2)
|
||||
.map((v) => v.name)
|
||||
.join(',')
|
||||
"
|
||||
>
|
||||
<div class="tag-box">
|
||||
<span class="text">{{ `+${item.projects.length - 2}` }}</span>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
|
||||
<div v-for="(project, index) in item.projects.slice(0, 2)" :key="index" class="tag-box">
|
||||
<span class="text">{{ project.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<span class="label">账户总消耗</span>
|
||||
<span class="cts">{{ `¥${formatNumberShow({ value: item.total_use_amount, showExactValue: true })}` }}</span>
|
||||
@ -53,17 +77,18 @@
|
||||
<img :src="icon1" width="16" height="16" class="mr-8px cursor-pointer" @click="openDelete(item)" />
|
||||
<a-button
|
||||
v-if="showPauseButton(item.status)"
|
||||
class="w-64px search-btn mr-8px"
|
||||
type="outline"
|
||||
class="mr-8px"
|
||||
size="mini"
|
||||
@click="handlePause(item)"
|
||||
>
|
||||
<template #default>暂停同步</template>
|
||||
</a-button>
|
||||
<a-button class="w-64px search-btn mr-8px" size="mini" @click="handleReauthorize(item)">
|
||||
<a-button type="outline" class="mr-8px" size="mini" @click="handleReauthorize(item)">
|
||||
<template #default>获取凭证</template>
|
||||
</a-button>
|
||||
|
||||
<a-button class="w-40px search-btn" size="mini" @click="openEdit(item)">
|
||||
<a-button type="outline" size="mini" @click="openEdit(item)">
|
||||
<template #default>编辑</template>
|
||||
</a-button>
|
||||
</div>
|
||||
@ -76,8 +101,8 @@
|
||||
|
||||
<script setup>
|
||||
import { defineProps, ref, computed } from 'vue';
|
||||
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
|
||||
import { EnumPutAccountStatus } from '@/views/property-marketing/put-account/components/status-select/constants';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import { EnumStatus } from '@/views/property-marketing/put-account/components/status-select/constants';
|
||||
|
||||
import { formatNumberShow, exactFormatTime } from '@/utils/tools';
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>确认暂停同步 “{{ accountName }}” 这个账号的数据吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px !bg-#f64b31" size="large" @click="onConfirm">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -1,9 +1,3 @@
|
||||
@mixin ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-container {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
|
||||
@ -111,6 +111,9 @@
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属项目" field="project_ids">
|
||||
<CommonSelect v-model="form.project_ids" :options="projects" placeholder="请选择…" size="large" />
|
||||
</a-form-item>
|
||||
<template v-if="isEdit">
|
||||
<a-form-item label="账户总消耗" field="total_use_amount">
|
||||
<a-input v-model="form.total_use_amount" placeholder="请输入..." size="large" disabled />
|
||||
@ -131,7 +134,7 @@
|
||||
</template>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="onSubmit" :loading="importLoading">
|
||||
{{ confirmBtnText }}
|
||||
</a-button>
|
||||
@ -148,7 +151,9 @@ import { ref, defineEmits } from 'vue';
|
||||
import AuthorizedAccountModal from '../authorized-account-modal';
|
||||
// import ImportPromptModal from '../import-prompt-modal';
|
||||
import StatusBox from '../status-box';
|
||||
import { PLATFORM_LIST, ENUM_PLATFORM } from '@/views/property-marketing/put-account/common_constants';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
import { PLATFORM_LIST, ENUM_PUT_ACCOUNT_PLATFORM } from '@/utils/platform';
|
||||
|
||||
import { showExportNotification } from '@/utils/arcoD';
|
||||
import { genRandomId } from '@/utils/tools';
|
||||
@ -158,6 +163,7 @@ import {
|
||||
putPlacementAccounts,
|
||||
getPlacementAccountsTemplateUrl,
|
||||
batchPlacementAccounts,
|
||||
getProjectList,
|
||||
} from '@/api/all/propertyMarketing';
|
||||
|
||||
import icon1 from '@/assets/img/media-account/icon-download.png';
|
||||
@ -177,6 +183,7 @@ const INITIAL_FORM = {
|
||||
holder_name: '',
|
||||
platform: 0,
|
||||
is_sync_project: 1,
|
||||
project_ids: [],
|
||||
};
|
||||
|
||||
const visible = ref(false);
|
||||
@ -191,6 +198,7 @@ const authorizedAccountModalRef = ref(null);
|
||||
const uploadRef = ref(null);
|
||||
const file = ref(null);
|
||||
const form = ref(cloneDeep(INITIAL_FORM));
|
||||
const projects = ref([]);
|
||||
const importLoading = ref(false);
|
||||
|
||||
const rules = {
|
||||
@ -245,6 +253,7 @@ const reset = () => {
|
||||
fileName.value = '';
|
||||
file.value = null;
|
||||
isEdit.value = false;
|
||||
projects.value = [];
|
||||
importLoading.value = false;
|
||||
uploadStatus.value = UploadStatus.DEFAULT;
|
||||
uploadType.value = 'manual';
|
||||
@ -258,12 +267,19 @@ const open = (accountId = '') => {
|
||||
id.value = accountId;
|
||||
isEdit.value = !!accountId;
|
||||
|
||||
getProjects();
|
||||
if (accountId) {
|
||||
getAccountDetail();
|
||||
}
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
const getProjects = async () => {
|
||||
const { code, data } = await getProjectList();
|
||||
if (code === 200) {
|
||||
projects.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
const getAccountDetail = async () => {
|
||||
const { code, data } = await getPlacementAccountsDetail(id.value);
|
||||
@ -288,7 +304,7 @@ const handleBatchImport = async () => {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
if (code === 200) {
|
||||
const id = genRandomId();
|
||||
showExportNotification(`正在导入“${file.value.name}”,请稍后...`, { id });
|
||||
@ -308,7 +324,7 @@ const handleBatchImport = async () => {
|
||||
|
||||
const handleAdd = async () => {
|
||||
// 聚光无子账号
|
||||
if (form.value.platform === ENUM_PLATFORM.jg) {
|
||||
if (form.value.platform === ENUM_PUT_ACCOUNT_PLATFORM.jg) {
|
||||
const { code, data } = await postPlacementAccounts(form.value);
|
||||
if (code === 200) {
|
||||
update();
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
</template>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="cancel-btn" @click="close">取消</a-button>
|
||||
<a-button size="large" @click="close">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="handleOk">{{ confirmBtnText }} </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
@ -67,7 +67,6 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { defineExpose, ref, computed, defineEmits } from 'vue';
|
||||
import { exactFormatTime } from '@/utils/tools';
|
||||
import { ENUM_PLATFORM } from '@/views/property-marketing/put-account/common_constants';
|
||||
import {
|
||||
putPlacementAccountsAuthorized,
|
||||
getPlacementAccountsAuthorizedStatus,
|
||||
|
||||
@ -42,18 +42,24 @@
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">运营人员</span>
|
||||
<a-space class="w-160px">
|
||||
<OperatorSelect v-model="query.operator_id" :options="operators" @change="handleSearch" />
|
||||
<CommonSelect v-model="query.operator_id" :multiple="false" :options="operators" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-row flex">
|
||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">所属项目</span>
|
||||
<a-space class="w-200px">
|
||||
<CommonSelect v-model="query.project_ids" :options="projects" @change="handleSearch" />
|
||||
</a-space>
|
||||
</div>
|
||||
<a-button type="outline" class="mr-12px" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -65,10 +71,10 @@
|
||||
|
||||
<script setup>
|
||||
import { defineEmits, defineProps } from 'vue';
|
||||
import { getPlacementAccountOperators } from '@/api/all/propertyMarketing';
|
||||
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
|
||||
import { getPlacementAccountOperators, getProjectList } from '@/api/all/propertyMarketing';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import StatusSelect from '@/views/property-marketing/put-account/components/status-select';
|
||||
import OperatorSelect from '@/views/property-marketing/put-account/components/operator-select';
|
||||
import CommonSelect from '@/components/common-select';
|
||||
|
||||
const props = defineProps({
|
||||
query: {
|
||||
@ -80,6 +86,7 @@ const props = defineProps({
|
||||
const emits = defineEmits('onSearch', 'onReset', 'update:query');
|
||||
|
||||
const operators = ref([]);
|
||||
const projects = ref([]);
|
||||
|
||||
const handleSearch = () => {
|
||||
emits('update:query', props.query);
|
||||
@ -97,9 +104,16 @@ const getOperators = async () => {
|
||||
operators.value = data;
|
||||
}
|
||||
};
|
||||
const getProjects = async () => {
|
||||
const { code, data } = await getProjectList();
|
||||
if (code === 200) {
|
||||
projects.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getOperators();
|
||||
getProjects();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" class="mr-16px cancel-btn" @click="close">取消</a-button>
|
||||
<a-button size="large" @click="close">取消</a-button>
|
||||
<a-button type="primary" size="large" @click="handleOk"> 去授权 </a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
>已选<span class="color-#6D4CFE num mx-3px">{{ selectedRows.length }}个</span>账户</span
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<a-button class="cancel-btn" size="large" @click="onClose">取消</a-button>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
class="ml-16px"
|
||||
|
||||
@ -8,4 +8,5 @@ export const INITIAL_QUERY = {
|
||||
status: '',
|
||||
platform: '',
|
||||
operator_id: '',
|
||||
project_ids: [],
|
||||
};
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="top flex h-64px px-24px py-10px justify-between items-center">
|
||||
<p class="text-18px font-400 lh-26px color-#211F24 title">账户管理</p>
|
||||
<div class="flex items-center">
|
||||
<a-button type="primary" class="w-112px search-btn" size="medium" @click="handleOpenAccountModal">
|
||||
<a-button type="primary" class="w-112px" size="medium" @click="handleOpenAccountModal">
|
||||
<template #icon>
|
||||
<img :src="icon1" width="16" height="16" />
|
||||
</template>
|
||||
@ -53,7 +53,7 @@
|
||||
</template>
|
||||
<div v-else>
|
||||
<a-space v-if="isAbNormalStatus" class="flex items-center">
|
||||
<a-button class="w-96px err-btn" size="mini" @click="handleOpenAbnormalAccount">
|
||||
<a-button type="primary" status="danger" size="mini" @click="handleOpenAbnormalAccount">
|
||||
<template #default>查看异常账号</template>
|
||||
</a-button>
|
||||
</a-space>
|
||||
@ -79,7 +79,7 @@
|
||||
show-page-size
|
||||
:page-size-options="[8, 16, 20, 32, 64]"
|
||||
:current="pageInfo.page"
|
||||
:page-size="pageInfo.pageSize"
|
||||
:page-size="pageInfo.page_size"
|
||||
@change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
/>
|
||||
@ -117,7 +117,7 @@ let queryTaskTimer = null;
|
||||
|
||||
const pageInfo = ref({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
page_size: 20,
|
||||
total: 0,
|
||||
});
|
||||
const query = ref(cloneDeep(INITIAL_QUERY));
|
||||
@ -173,10 +173,10 @@ const getHealthData = async () => {
|
||||
}
|
||||
};
|
||||
const getAccountData = async () => {
|
||||
const { page, pageSize } = pageInfo.value;
|
||||
const { page, page_size } = pageInfo.value;
|
||||
const { code, data, total } = await getPlacementAccounts({
|
||||
page,
|
||||
page_size: pageSize,
|
||||
page_size,
|
||||
...query.value,
|
||||
});
|
||||
if (code === 200) {
|
||||
@ -189,11 +189,11 @@ const reload = () => {
|
||||
getData();
|
||||
};
|
||||
const handleSearch = () => {
|
||||
getData();
|
||||
reload();
|
||||
};
|
||||
const handleReset = () => {
|
||||
pageInfo.value.page = 1;
|
||||
pageInfo.value.pageSize = 20;
|
||||
pageInfo.value.page_size = 20;
|
||||
pageInfo.value.total = 0;
|
||||
selectedItems.value = [];
|
||||
query.value = cloneDeep(INITIAL_QUERY);
|
||||
@ -205,7 +205,7 @@ const onPageChange = (current) => {
|
||||
getData();
|
||||
};
|
||||
const onPageSizeChange = (pageSize) => {
|
||||
pageInfo.value.pageSize = pageSize;
|
||||
pageInfo.value.page_size = pageSize;
|
||||
reload();
|
||||
};
|
||||
|
||||
|
||||
@ -2,16 +2,6 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
:deep(.search-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||
color: #6d4cfe;
|
||||
}
|
||||
:deep(.reset-btn) {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--BG-500, #b1b2b5);
|
||||
background: var(--BG-white, #fff);
|
||||
}
|
||||
.filter-wrap {
|
||||
.top {
|
||||
.title {
|
||||
@ -41,15 +31,6 @@
|
||||
color: #211f24;
|
||||
}
|
||||
}
|
||||
.err-btn {
|
||||
background-color: #f64b31 !important;
|
||||
color: var(--BG-white, #fff);
|
||||
font-family: 'PingFang SC';
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 166.667% */
|
||||
}
|
||||
.operation-btn {
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
<!--
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-25 14:02:40
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model="selectedOperators"
|
||||
:multiple="multiple"
|
||||
size="medium"
|
||||
:placeholder="placeholder"
|
||||
allow-clear
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-option v-for="(item, index) in options" :key="index" :value="item.id" :label="item.name">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Array, String, Number],
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '全部',
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const selectedOperators = ref(props.multiple ? [] : '');
|
||||
|
||||
// 监听外部传入的值变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
selectedOperators.value = newVal;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// 监听内部值变化,向外部发送更新
|
||||
watch(selectedOperators, (newVal) => {
|
||||
emits('update:modelValue', newVal);
|
||||
});
|
||||
|
||||
const handleChange = (value) => {
|
||||
selectedOperators.value = value;
|
||||
emits('change', value);
|
||||
};
|
||||
</script>
|
||||
@ -31,7 +31,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { IconDelete } from '@arco-design/web-vue/es/icon';
|
||||
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
const columns = [
|
||||
|
||||
@ -35,13 +35,13 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-row-item flex items-center">
|
||||
<a-button class="w-84px search-btn mr-12px" :disabled="disabled" size="medium" @click="handleSearch">
|
||||
<a-button type="outline" class="mr-12px" :disabled="disabled" size="medium" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
<template #default>搜索</template>
|
||||
</a-button>
|
||||
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||
<a-button size="medium" @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
@ -54,7 +54,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineEmits, defineProps } from 'vue';
|
||||
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import AccountSelect from '@/views/components/common/AccountSelect.vue';
|
||||
import PlanSelect from '@/views/components/common/PlanSelect.vue';
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { PLATFORM_LIST } from '../../../common_constants';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
|
||||
const props = defineProps({
|
||||
listData: {
|
||||
|
||||
@ -77,7 +77,7 @@ import { reactive, ref } from 'vue';
|
||||
|
||||
import MonthData from './components/month-data/index.vue';
|
||||
import PlacementSuggestions from './components/placement-suggestions/index.vue';
|
||||
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants.ts';
|
||||
import { PLATFORM_LIST } from '@/utils/platform';
|
||||
import { getPlacementGuideDetail } from '@/api/all/propertyMarketing';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { uploadPdf } from '@/views/property-marketing/put-account/investment-guidelines/constants';
|
||||
|
||||
Reference in New Issue
Block a user