Merge remote-tracking branch 'origin/main' into feature/0905_登录注册流程重构
# Conflicts: # src/App.vue # src/views/components/login/index.vue # src/views/components/management/person/index.vue # src/views/login/style.scss
This commit is contained in:
@ -55,7 +55,7 @@ const checkHasInviteCode = () => {
|
||||
|
||||
<template>
|
||||
<Layout :class="['layout-wrap', { mobile: appStore.hideMenu }]" class="h-full flex flex-col w-full">
|
||||
<JoinModal v-model:visible="joinEnterpriseVisible" ref="joinModalRef" />
|
||||
<JoinModal v-model:open="joinEnterpriseVisible" centered ref="joinModalRef" />
|
||||
<Layout.Header class="layout-header-wrap">
|
||||
<Navbar />
|
||||
</Layout.Header>
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, Result } from 'ant-design-vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const back = () => {
|
||||
router.replace('/');
|
||||
@ -7,9 +10,9 @@ const back = () => {
|
||||
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-result class="result" status="404" subtitle="页面跑路了" />
|
||||
<div class="operation-row">
|
||||
<a-button key="back" type="primary" @click="back">返回</a-button>
|
||||
<Result class="result" status="404" sub-title="页面跑路了" />
|
||||
<div class="operation-row flex justify-center">
|
||||
<Button key="back" type="primary" @click="back">返回</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -19,8 +22,10 @@ const back = () => {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -95px;
|
||||
margin-top: -121px;
|
||||
text-align: center;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: 32px 32px 24px;
|
||||
// margin-left: -95px;
|
||||
// margin-top: -121px;
|
||||
// text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,13 +3,14 @@
|
||||
* @Date: 2025-06-26 17:23:52
|
||||
-->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
<Modal
|
||||
v-model:open="visible"
|
||||
width="400px"
|
||||
modal-class="exit-account-modal"
|
||||
wrapClassName="exit-account-modal"
|
||||
show-close="false"
|
||||
:footer="false"
|
||||
@close="onClose"
|
||||
:footer="null"
|
||||
@cancel="onClose"
|
||||
centered
|
||||
>
|
||||
<div class="flex items-center mb-16px">
|
||||
<img :src="icon1" width="20" height="20" class="mr-12px" />
|
||||
@ -17,15 +18,14 @@
|
||||
</div>
|
||||
<p class="m-0 p-0 mb-24px s2 ml-32px">退出登录后,你将无法收到该账号的通知</p>
|
||||
<div class="flex items-center justify-end">
|
||||
<a-button class="!rounded-4px" size="medium" @click="onClose">返回</a-button>
|
||||
<a-button type="primary" class="ml-16px danger-btn" status="danger" size="medium" @click="onLogout"
|
||||
>退出登录</a-button
|
||||
>
|
||||
<Button @click="onClose">返回</Button>
|
||||
<Button danger type="primary" @click="onLogout" class="ml-8px">退出登录</Button>
|
||||
</div>
|
||||
</a-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Modal, Button, message } from 'ant-design-vue';
|
||||
import { ref } from 'vue';
|
||||
import { fetchLogOut } from '@/api/all/login';
|
||||
import { handleUserLogout } from '@/utils/user';
|
||||
@ -46,7 +46,7 @@ async function onLogout() {
|
||||
const { code } = await fetchLogOut();
|
||||
if (code === 200) {
|
||||
handleUserLogout();
|
||||
AMessage.success('退出登录成功');
|
||||
message.success('退出登录成功');
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
@ -56,14 +56,14 @@ defineExpose({ open });
|
||||
|
||||
<style lang="scss">
|
||||
.exit-account-modal {
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--BG-300, #e6e6e8) !important;
|
||||
background-color: var(--BG-white, #fff) !important;
|
||||
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1);
|
||||
.arco-modal-header {
|
||||
// border-radius: 8px;
|
||||
// border: 1px solid var(--BG-300, #e6e6e8) !important;
|
||||
// background-color: var(--BG-white, #fff) !important;
|
||||
// box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1);
|
||||
.ant-modal-header {
|
||||
display: none;
|
||||
}
|
||||
.arco-modal-body {
|
||||
.ant-modal-body {
|
||||
padding: 24px;
|
||||
.s1 {
|
||||
color: var(--Text-1, #211f24);
|
||||
@ -81,15 +81,6 @@ defineExpose({ open });
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 166.667% */
|
||||
}
|
||||
.cancel-btn {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.danger-btn {
|
||||
background: var(--Functional-Danger-6, #f64b31) !important;
|
||||
&:hover {
|
||||
background: var(--Functional-Danger-6, #f64b31) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -10,33 +10,31 @@
|
||||
<div class="agent-entry mx-16px" :class="isAgentRoute ? 'agent' : ''" @click="handleAgentClick"></div>
|
||||
|
||||
<!-- 头像设置 -->
|
||||
<a-dropdown trigger="click" class="layout-avatar-dropdown">
|
||||
<a-avatar class="cursor-pointer" :size="32">
|
||||
<img alt="avatar" src="@/assets/avatar.svg" />
|
||||
</a-avatar>
|
||||
<template #content>
|
||||
<div>
|
||||
<a-doption>
|
||||
<a-space class="flex justify-between w-100%" @click="setServerMenu">
|
||||
<Dropdown trigger="click" overlayClassName="layout-avatar-dropdown">
|
||||
<img alt="avatar" src="@/assets/avatar.svg" class="cursor-pointer w-32px h-32px rounded-50%" />
|
||||
<template #overlay>
|
||||
<Menu>
|
||||
<MenuItem>
|
||||
<div class="h-full flex justify-between items-center w-100%" @click="setServerMenu">
|
||||
<div class="flex items-center">
|
||||
<img :src="icon1" class="w-16px h-16px mr-8px" />
|
||||
<span>管理中心</span>
|
||||
</div>
|
||||
<icon-right size="12" />
|
||||
</a-space>
|
||||
</a-doption>
|
||||
<a-dsubmenu value="option-1" position="lt" trigger="hover" class="enterprises-dsubmenu">
|
||||
<a-doption class="enterprises-doption">
|
||||
<a-space class="flex justify-between w-100%">
|
||||
<div class="flex items-center">
|
||||
<img :src="icon3" class="w-16px h-16px mr-8px" />
|
||||
<span>切换企业账号</span>
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<SubMenu value="option-1" position="lt" trigger="hover" popupClassName="enterprises-dsubmenu">
|
||||
<template #title>
|
||||
<div class="flex justify-between w-100% h-full items-center">
|
||||
<div class="flex items-center">
|
||||
<img :src="icon3" class="w-16px h-16px mr-8px" />
|
||||
<span>切换企业账号</span>
|
||||
</div>
|
||||
<icon-right size="12" />
|
||||
</div>
|
||||
<icon-right size="12" />
|
||||
</a-space>
|
||||
</a-doption>
|
||||
<template #content>
|
||||
<a-doption
|
||||
</template>
|
||||
<MenuItem
|
||||
v-for="(item, index) in enterprises"
|
||||
:key="index"
|
||||
class="rounded-8px hover:bg-#F2F3F5"
|
||||
@ -49,21 +47,21 @@
|
||||
<span>{{ item.name }}</span>
|
||||
<icon-check v-if="enterpriseInfo?.id === item.id" size="16" />
|
||||
</div>
|
||||
</a-doption>
|
||||
</template>
|
||||
</a-dsubmenu>
|
||||
<a-doption>
|
||||
<a-space class="flex justify-between w-100%" @click="clickExit">
|
||||
</MenuItem>
|
||||
</SubMenu>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<div class="flex justify-between w-100% h-full items-center" @click="clickExit">
|
||||
<div class="flex items-center">
|
||||
<img :src="icon2" class="w-16px h-16px mr-8px" />
|
||||
<span>退出登录</span>
|
||||
</div>
|
||||
<icon-right size="12" />
|
||||
</a-space>
|
||||
</a-doption>
|
||||
</div>
|
||||
</div>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</Dropdown>
|
||||
|
||||
<ExitAccountModal ref="exitAccountModalRef" />
|
||||
<DownloadCenterModal ref="downloadCenterModalRef" />
|
||||
@ -71,6 +69,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Dropdown, Menu, MenuItem, SubMenu } from 'ant-design-vue';
|
||||
import router from '@/router';
|
||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||
import { useSidebarStore } from '@/stores/modules/side-bar';
|
||||
@ -137,35 +136,51 @@ const handleAgentClick = () => {
|
||||
<style lang="scss">
|
||||
.layout-avatar-dropdown,
|
||||
.enterprises-dsubmenu {
|
||||
.arco-dropdown {
|
||||
.ant-dropdown-menu {
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--BG-300, #e6e6e8);
|
||||
background: var(--BG-white, #fff);
|
||||
padding: 12px 0px;
|
||||
.arco-dropdown-option {
|
||||
.ant-dropdown-menu-item {
|
||||
padding: 0 12px;
|
||||
margin-bottom: 4px;
|
||||
&-content {
|
||||
|
||||
.ant-dropdown-menu-title-content {
|
||||
display: flex;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
padding: 10px 24px;
|
||||
align-items: center;
|
||||
.menu-item-text {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: $font-family-regular;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
.ant-dropdown-menu-submenu {
|
||||
width: 100%;
|
||||
.ant-dropdown-menu-submenu-title {
|
||||
padding: 0;
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
.ant-dropdown-menu-title-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
.ant-dropdown-menu-submenu-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.arco-dropdown-option-content {
|
||||
.menu-item-text {
|
||||
color: var(--Text-2, #3c4043);
|
||||
font-family: $font-family-regular;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
}
|
||||
.ant-dropdown-menu-title-content {
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
&:not(.arco-dropdown-option-disabled):hover {
|
||||
&:not(.ant-dropdown-menu-item):hover {
|
||||
background-color: transparent;
|
||||
.arco-dropdown-option-content {
|
||||
.ant-dropdown-menu-title-content {
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
}
|
||||
}
|
||||
@ -175,29 +190,29 @@ const handleAgentClick = () => {
|
||||
.layout-avatar-dropdown,
|
||||
.enterprises-dsubmenu {
|
||||
width: 200px;
|
||||
.arco-dropdown {
|
||||
.ant-dropdown-menu {
|
||||
padding: 12px 4px;
|
||||
.arco-dropdown-option {
|
||||
.ant-dropdown-menu-item {
|
||||
padding: 0 !important;
|
||||
&-content {
|
||||
.ant-dropdown-menu-title-content {
|
||||
padding: 0 12px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.arco-dropdown-option-suffix {
|
||||
.ant-dropdown-option-suffix {
|
||||
display: none;
|
||||
}
|
||||
.enterprises-doption {
|
||||
.arco-dropdown-option-content {
|
||||
padding: 0 !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
&:not(.arco-dropdown-option-disabled):hover {
|
||||
background-color: transparent;
|
||||
.arco-dropdown-option-content {
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
}
|
||||
}
|
||||
}
|
||||
// .enterprises-doption {
|
||||
// .ant-dropdown-menu-title-content {
|
||||
// padding: 0 !important;
|
||||
// border-radius: 8px;
|
||||
// }
|
||||
// &:not(.ant-dropdown-option-disabled):hover {
|
||||
// background-color: transparent;
|
||||
// .ant-dropdown-menu-title-content {
|
||||
// background: var(--BG-200, #f2f3f5);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
<Modal
|
||||
v-model:open="visible"
|
||||
:title="isBatch ? '批量删除下载记录' : '删除下载记录'"
|
||||
width="400px"
|
||||
@close="onClose"
|
||||
@cancel="onClose"
|
||||
centered
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<img :src="icon1" width="20" height="20" class="mr-12px" />
|
||||
<span>确认删除 {{ accountName }} 这条记录吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px !bg-#f64b31 !border-none" status="danger" size="large" @click="onDelete"
|
||||
>确定</a-button
|
||||
>
|
||||
<Button @click="onClose">取消</Button>
|
||||
<Button type="primary" danger @click="onDelete">确定</Button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Modal, Button, message } from 'ant-design-vue';
|
||||
import { ref } from 'vue';
|
||||
import { deleteTask, deleteBatchTasks } from '@/api/all/common';
|
||||
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||
@ -52,7 +52,7 @@ async function onDelete() {
|
||||
|
||||
const { code } = await _fn(_params);
|
||||
if (code === 200) {
|
||||
AMessage.success('删除成功');
|
||||
message.success('删除成功');
|
||||
isBatch.value ? emits('batchUpdate') : emits('update');
|
||||
onClose();
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
<script lang="jsx">
|
||||
import { ref, computed } from 'vue';
|
||||
import { Input, Table, TableColumn, Checkbox, Pagination, Button, Tooltip, Notification } from '@arco-design/web-vue';
|
||||
import { Button, Checkbox, Input, Tooltip, Table, Pagination, message, notification } from 'ant-design-vue';
|
||||
import { IconSearch, IconClose, IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
||||
|
||||
import NoData from '@/components/no-data';
|
||||
import { getTask, postRedoTask, postBatchDownload, batchQueryTaskStatus } from '@/api/all/common';
|
||||
import { INITIAL_FORM, TABLE_COLUMNS } from './constants';
|
||||
@ -21,8 +22,6 @@ export default {
|
||||
dataSource,
|
||||
pageInfo,
|
||||
onPageChange,
|
||||
onPageSizeChange,
|
||||
rowSelection,
|
||||
handleSelect,
|
||||
handleSelectAll,
|
||||
DEFAULT_PAGE_INFO,
|
||||
@ -30,9 +29,6 @@ export default {
|
||||
onPageChange: () => {
|
||||
getData();
|
||||
},
|
||||
onPageSizeChange: () => {
|
||||
getData();
|
||||
},
|
||||
});
|
||||
let queryTaskTimer = null;
|
||||
|
||||
@ -75,10 +71,12 @@ export default {
|
||||
getData();
|
||||
};
|
||||
|
||||
const handleSorterChange = (column, order) => {
|
||||
query.value.sort_column = column;
|
||||
query.value.sort_order = order === 'ascend' ? 'asc' : 'desc';
|
||||
reload();
|
||||
const handleSorterChange = (pagination, filters, sorter) => {
|
||||
if (sorter && !Array.isArray(sorter) && sorter.columnKey) {
|
||||
query.value.sort_column = sorter.columnKey;
|
||||
query.value.sort_order = sorter.order === 'ascend' ? 'asc' : 'desc';
|
||||
reload();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
@ -137,10 +135,10 @@ export default {
|
||||
completeTaskNum++;
|
||||
|
||||
const notificationId = downloadTaskInfos.value.find((v) => v.id === id)?.randomId;
|
||||
notificationId && Notification.remove(notificationId);
|
||||
notificationId && notification.close(notificationId);
|
||||
|
||||
if (status === 1) {
|
||||
AMessage.success('批量下载已完成,正在下载文件...');
|
||||
message.success('批量下载已完成,正在下载文件...');
|
||||
downloadByUrl(file);
|
||||
} else if (status === 2) {
|
||||
const onReDownload = () => {
|
||||
@ -208,11 +206,11 @@ export default {
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">操作人员</span>
|
||||
<Input
|
||||
v-model={query.value.operator_name}
|
||||
v-model:value={query.value.operator_name}
|
||||
class="w-240px"
|
||||
placeholder="请输入操作人员"
|
||||
size="medium"
|
||||
allow-clear
|
||||
size="middle"
|
||||
allowClear
|
||||
onChange={handleSearch}
|
||||
v-slots={{
|
||||
prefix: () => <IconSearch />,
|
||||
@ -222,11 +220,11 @@ export default {
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">所属模块</span>
|
||||
<Input
|
||||
v-model={query.value.module}
|
||||
v-model:value={query.value.module}
|
||||
class="w-240px"
|
||||
placeholder="请输入所属模块"
|
||||
size="medium"
|
||||
allow-clear
|
||||
size="middle"
|
||||
allowClear
|
||||
onChange={handleSearch}
|
||||
v-slots={{
|
||||
prefix: () => <IconSearch />,
|
||||
@ -239,17 +237,17 @@ export default {
|
||||
{dataSource.value.length > 0 && selectedRows.value.length > 0 && (
|
||||
<div
|
||||
class={[
|
||||
'tip-row flex justify-between px-16px py-10px w-100% mb-16px h-42px',
|
||||
'tip-row flex justify-between px-16px py-10px w-100% mb-16px h-48px items-center',
|
||||
selectedRows.value.length > 0 ? ' selected' : '',
|
||||
].join('')}
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center">
|
||||
<Checkbox
|
||||
modelValue={checkedAll.value}
|
||||
checked={checkedAll.value}
|
||||
indeterminate={indeterminate.value}
|
||||
class="mr-8px"
|
||||
onChange={handleSelectAll}
|
||||
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||
/>
|
||||
<span class="label mr-24px">
|
||||
已选
|
||||
@ -271,104 +269,96 @@ export default {
|
||||
{/* 表格 */}
|
||||
<Table
|
||||
ref="tableRef"
|
||||
data={dataSource.value}
|
||||
column-resizable
|
||||
row-key="id"
|
||||
row-selection={rowSelection.value}
|
||||
selected-keys={selectedRowKeys.value}
|
||||
dataSource={dataSource.value}
|
||||
rowKey="id"
|
||||
rowSelection={{
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onSelect: handleSelect,
|
||||
onSelectAll: handleSelectAll,
|
||||
}}
|
||||
pagination={false}
|
||||
scroll={{ x: '100%', y: '100%' }}
|
||||
class="w-100% flex-1 overflow-hidden"
|
||||
bordered
|
||||
onSorterChange={handleSorterChange}
|
||||
onSelect={handleSelect}
|
||||
onSelectAll={handleSelectAll}
|
||||
showSorterTooltip={false}
|
||||
onChange={handleSorterChange}
|
||||
v-slots={{
|
||||
empty: () => <NoData />,
|
||||
columns: () => (
|
||||
<>
|
||||
{TABLE_COLUMNS.map((column) => (
|
||||
<TableColumn
|
||||
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
|
||||
v-slots={{
|
||||
title: () => (
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{column.title}</span>
|
||||
{column.tooltip && (
|
||||
<Tooltip content={column.tooltip} position="top">
|
||||
<IconQuestionCircle class="tooltip-icon color-#737478" size={16} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
cell: ({ record }) => {
|
||||
if (column.dataIndex === 'status') {
|
||||
return (
|
||||
<div class={['status-box', `status-box-${record.status}`]}>
|
||||
<span>{EXPORT_TASK_STATUS.find((v) => v.value === record.status)?.label}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (column.dataIndex === 'operator.name') {
|
||||
return record.operator?.name || record.operator?.mobile;
|
||||
} else if (column.dataIndex === 'created_at') {
|
||||
return exactFormatTime(record.created_at, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss');
|
||||
} else {
|
||||
return formatTableField(column, record, true);
|
||||
}
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<TableColumn
|
||||
data-index="operation"
|
||||
width={dataSource.value.some((record) => record.status !== enumTaskStatus.Exporting) ? 120 : 60}
|
||||
fixed="right"
|
||||
title="操作"
|
||||
v-slots={{
|
||||
cell: ({ record }) => (
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
src={icon1}
|
||||
width="14"
|
||||
height="14"
|
||||
class="mr-8px cursor-pointer"
|
||||
onClick={() => handleDelete(record)}
|
||||
/>
|
||||
{record.status !== enumTaskStatus.Exporting && (
|
||||
<Button type="outline" size="mini" class="search-btn" onClick={() => handleDownload(record)}>
|
||||
{record.status === enumTaskStatus.Failed ? '重新导出' : '下载'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
emptyText: () => <NoData />,
|
||||
}}
|
||||
/>
|
||||
>
|
||||
{TABLE_COLUMNS.map((column) => (
|
||||
<Table.Column
|
||||
key={column.dataIndex}
|
||||
dataIndex={column.dataIndex}
|
||||
fixed={column.fixed}
|
||||
width={column.width}
|
||||
minWidth={column.minWidth}
|
||||
sorter={column.sortable}
|
||||
align={column.align}
|
||||
ellipsis
|
||||
title={() => (
|
||||
<>
|
||||
<span class="cts mr-4px">{column.title}</span>
|
||||
{column.tooltip && (
|
||||
<Tooltip title={column.tooltip} placement="top">
|
||||
<IconQuestionCircle class="tooltip-icon color-#737478" size={16} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
customRender={({ record }) => {
|
||||
if (column.dataIndex === 'status') {
|
||||
return (
|
||||
<div class={['status-box', `status-box-${record.status}`]}>
|
||||
<span>{EXPORT_TASK_STATUS.find((v) => v.value === record.status)?.label}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (column.dataIndex === 'operator.name') {
|
||||
return record.operator?.name || record.operator?.mobile;
|
||||
} else if (column.dataIndex === 'created_at') {
|
||||
return exactFormatTime(record.created_at, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss');
|
||||
} else {
|
||||
return formatTableField(column, record, true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<Table.Column
|
||||
dataIndex="operation"
|
||||
width={dataSource.value.some((record) => record.status !== enumTaskStatus.Exporting) ? 120 : 60}
|
||||
fixed="right"
|
||||
title="操作"
|
||||
customRender={({ record }) => (
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
src={icon1}
|
||||
width="14"
|
||||
height="14"
|
||||
class="mr-8px cursor-pointer"
|
||||
onClick={() => handleDelete(record)}
|
||||
/>
|
||||
{record.status !== enumTaskStatus.Exporting && (
|
||||
<Button type="primary" ghost size="small" class="search-btn" onClick={() => handleDownload(record)}>
|
||||
{record.status === enumTaskStatus.Failed ? '重新导出' : '下载'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
{/* 分页 */}
|
||||
{pageInfo.value.total > 0 && (
|
||||
<div class="flex justify-end my-16px">
|
||||
<Pagination
|
||||
total={pageInfo.value.total}
|
||||
size="mini"
|
||||
show-total
|
||||
show-jumper
|
||||
show-page-size
|
||||
size="small"
|
||||
showTotal={(total, range) => `共 ${total} 条记录`}
|
||||
showQuickJumper
|
||||
showSizeChanger
|
||||
current={pageInfo.value.page}
|
||||
page-size={pageInfo.value.page_size}
|
||||
pageSize={pageInfo.value.page_size}
|
||||
onChange={onPageChange}
|
||||
onPageSizeChange={onPageSizeChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
<Modal
|
||||
v-model:open="visible"
|
||||
:title="isBatch ? '批量删除导入记录' : '删除导入记录'"
|
||||
width="400px"
|
||||
@close="onClose"
|
||||
centered
|
||||
@cancel="onClose"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<img :src="icon1" width="20" height="20" class="mr-12px" />
|
||||
<span>确认删除 {{ accountName }} 这条记录吗?</span>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button size="large" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" class="ml-16px !bg-#f64b31 !border-none" status="danger" size="large" @click="onDelete"
|
||||
>确定</a-button
|
||||
>
|
||||
<Button @click="onClose">取消</Button>
|
||||
<Button type="primary" danger @click="onDelete">确定</Button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { Modal, Button, message } from 'ant-design-vue';
|
||||
import { deleteTask, deleteBatchTasks } from '@/api/all/common';
|
||||
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||
|
||||
@ -51,7 +51,7 @@ async function onDelete() {
|
||||
const _params = isBatch.value ? { ids: taskId.value } : taskId.value;
|
||||
const { code } = await _fn(_params);
|
||||
if (code === 200) {
|
||||
AMessage.success('删除成功');
|
||||
message.success('删除成功');
|
||||
isBatch.value ? emits('batchUpdate') : emits('update');
|
||||
onClose();
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script lang="jsx">
|
||||
import { ref, computed } from 'vue';
|
||||
import { Input, Table, TableColumn, Checkbox, Pagination, Button, Tooltip, Notification } from '@arco-design/web-vue';
|
||||
import { Button, Tooltip, Table, Pagination } from 'ant-design-vue';
|
||||
import { IconSearch, IconClose, IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
||||
import NoData from '@/components/no-data';
|
||||
import { getTask } from '@/api/all/common';
|
||||
@ -21,8 +21,6 @@ export default {
|
||||
dataSource,
|
||||
pageInfo,
|
||||
onPageChange,
|
||||
onPageSizeChange,
|
||||
rowSelection,
|
||||
handleSelect,
|
||||
handleSelectAll,
|
||||
DEFAULT_PAGE_INFO,
|
||||
@ -30,9 +28,6 @@ export default {
|
||||
onPageChange: () => {
|
||||
getData();
|
||||
},
|
||||
onPageSizeChange: () => {
|
||||
getData();
|
||||
},
|
||||
});
|
||||
|
||||
const query = ref({ ...INITIAL_FORM });
|
||||
@ -72,10 +67,12 @@ export default {
|
||||
getData();
|
||||
};
|
||||
|
||||
const handleSorterChange = (column, order) => {
|
||||
query.value.sort_column = column;
|
||||
query.value.sort_order = order === 'ascend' ? 'asc' : 'desc';
|
||||
reload();
|
||||
const handleSorterChange = (pagination, filters, sorter) => {
|
||||
if (sorter && sorter.columnKey) {
|
||||
query.value.sort_column = sorter.columnKey;
|
||||
query.value.sort_order = sorter.order === 'ascend' ? 'asc' : 'desc';
|
||||
reload();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
@ -118,171 +115,98 @@ export default {
|
||||
|
||||
return () => (
|
||||
<div class="import-task-wrap">
|
||||
{/* 筛选行 */}
|
||||
{/* <div class="filter-row flex mb-16px">
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">操作人员</span>
|
||||
<Input
|
||||
v-model={query.value.operator_name}
|
||||
class="w-240px"
|
||||
placeholder="请输入操作人员"
|
||||
size="medium"
|
||||
allow-clear
|
||||
onChange={handleSearch}
|
||||
v-slots={{
|
||||
prefix: () => <IconSearch />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="filter-row-item flex items-center">
|
||||
<span class="label">所属模块</span>
|
||||
<Input
|
||||
v-model={query.value.module}
|
||||
class="w-240px"
|
||||
placeholder="请输入所属模块"
|
||||
size="medium"
|
||||
allow-clear
|
||||
onChange={handleSearch}
|
||||
v-slots={{
|
||||
prefix: () => <IconSearch />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* 已选提示行 */}
|
||||
{/* {dataSource.value.length > 0 && selectedRows.value.length > 0 && (
|
||||
<div
|
||||
class={[
|
||||
'tip-row flex justify-between px-16px py-10px w-100% mb-16px h-42px',
|
||||
selectedRows.value.length > 0 ? ' selected' : '',
|
||||
].join('')}
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center">
|
||||
<Checkbox
|
||||
modelValue={checkedAll.value}
|
||||
indeterminate={indeterminate.value}
|
||||
class="mr-8px"
|
||||
onChange={handleSelectAll}
|
||||
/>
|
||||
<span class="label mr-24px">
|
||||
已选
|
||||
<span class="color-#6D4CFE">{selectedRows.value.length}</span>
|
||||
个文件
|
||||
</span>
|
||||
<span class="operation-btn" onClick={handleBatchDownload}>
|
||||
批量下载
|
||||
</span>
|
||||
<span class="operation-btn red" onClick={handleBatchDelete}>
|
||||
批量删除
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<IconClose size={16} class="cursor-pointer color-#737478" onClick={handleCloseTip} />
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
{/* 表格 */}
|
||||
<Table
|
||||
ref="tableRef"
|
||||
data={dataSource.value}
|
||||
column-resizable
|
||||
row-key="id"
|
||||
selected-keys={selectedRowKeys.value}
|
||||
dataSource={dataSource.value}
|
||||
rowKey="id"
|
||||
rowSelection={{
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onSelect: handleSelect,
|
||||
onSelectAll: handleSelectAll,
|
||||
}}
|
||||
pagination={false}
|
||||
scroll={{ x: '100%', y: '100%' }}
|
||||
class="w-100% flex-1 overflow-hidden"
|
||||
bordered
|
||||
onSorterChange={handleSorterChange}
|
||||
onSelect={handleSelect}
|
||||
onSelectAll={handleSelectAll}
|
||||
showSorterTooltip={false}
|
||||
onChange={handleSorterChange}
|
||||
v-slots={{
|
||||
empty: () => <NoData />,
|
||||
columns: () => (
|
||||
<>
|
||||
{TABLE_COLUMNS.map((column) => (
|
||||
<TableColumn
|
||||
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
|
||||
v-slots={{
|
||||
title: () => (
|
||||
<div class="flex items-center">
|
||||
<span class="cts mr-4px">{column.title}</span>
|
||||
{column.tooltip && (
|
||||
<Tooltip content={column.tooltip} position="top">
|
||||
<IconQuestionCircle class="tooltip-icon color-#737478" size={16} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
cell: ({ record }) => {
|
||||
if (column.dataIndex === 'status') {
|
||||
return (
|
||||
<div class={['status-box', `status-box-${record.status}`]}>
|
||||
<span>{IMPORT_TASK_STATUS.find((v) => v.value === record.status)?.label}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (column.dataIndex === 'operator.name') {
|
||||
return <span>{record.operator?.name || record.operator?.mobile}</span>;
|
||||
} else if (column.dataIndex === 'created_at') {
|
||||
return exactFormatTime(record.created_at, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss');
|
||||
} else {
|
||||
return formatTableField(column, record, true);
|
||||
}
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<TableColumn
|
||||
data-index="operation"
|
||||
width={dataSource.value.some((record) => record.status === enumTaskStatus.Failed) ? 180 : 60}
|
||||
fixed="right"
|
||||
title="操作"
|
||||
v-slots={{
|
||||
cell: ({ record }) => (
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
src={icon1}
|
||||
width="14"
|
||||
height="14"
|
||||
class="mr-8px cursor-pointer"
|
||||
onClick={() => handleDelete(record)}
|
||||
/>
|
||||
{record.status === enumTaskStatus.Failed && (
|
||||
<Button type="outline" size="mini" class="search-btn" onClick={() => handleDownload(record)}>
|
||||
下载问题表格
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
>
|
||||
{TABLE_COLUMNS.map((column) => (
|
||||
<Table.Column
|
||||
key={column.dataIndex}
|
||||
dataIndex={column.dataIndex}
|
||||
fixed={column.fixed}
|
||||
width={column.width}
|
||||
minWidth={column.minWidth}
|
||||
sorter={column.sortable}
|
||||
align={column.align}
|
||||
ellipsis
|
||||
title={() => (
|
||||
<>
|
||||
<span class="cts mr-4px">{column.title}</span>
|
||||
{column.tooltip && (
|
||||
<Tooltip title={column.tooltip} placement="top">
|
||||
<IconQuestionCircle class="tooltip-icon color-#737478" size={16} />
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
customRender={({ record }) => {
|
||||
if (column.dataIndex === 'status') {
|
||||
return (
|
||||
<div class={['status-box', `status-box-${record.status}`]}>
|
||||
<span>{IMPORT_TASK_STATUS.find((v) => v.value === record.status)?.label}</span>
|
||||
</div>
|
||||
);
|
||||
} else if (column.dataIndex === 'operator.name') {
|
||||
return <span>{record.operator?.name || record.operator?.mobile}</span>;
|
||||
} else if (column.dataIndex === 'created_at') {
|
||||
return exactFormatTime(record.created_at, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss');
|
||||
} else {
|
||||
return formatTableField(column, record, true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<Table.Column
|
||||
dataIndex="operation"
|
||||
width={dataSource.value.some((record) => record.status === enumTaskStatus.Failed) ? 180 : 60}
|
||||
fixed="right"
|
||||
title="操作"
|
||||
customRender={({ record }) => (
|
||||
<div class="flex items-center">
|
||||
<img
|
||||
src={icon1}
|
||||
width="14"
|
||||
height="14"
|
||||
class="mr-8px cursor-pointer"
|
||||
onClick={() => handleDelete(record)}
|
||||
/>
|
||||
{record.status === enumTaskStatus.Failed && (
|
||||
<Button type="primary" ghost size="small" class="search-btn" onClick={() => handleDownload(record)}>
|
||||
下载问题表格
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
{/* 分页 */}
|
||||
{pageInfo.value.total > 0 && (
|
||||
<div class="flex justify-end my-16px">
|
||||
<Pagination
|
||||
total={pageInfo.value.total}
|
||||
size="mini"
|
||||
show-total
|
||||
show-jumper
|
||||
show-page-size
|
||||
size="small"
|
||||
showTotal={(total, range) => `共 ${total} 条记录`}
|
||||
showQuickJumper
|
||||
showSizeChanger
|
||||
current={pageInfo.value.page}
|
||||
page-size={pageInfo.value.page_size}
|
||||
pageSize={pageInfo.value.page_size}
|
||||
onChange={onPageChange}
|
||||
onPageSizeChange={onPageSizeChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1,37 +1,39 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
<Modal
|
||||
v-model:open="visible"
|
||||
title="任务中心"
|
||||
modal-class="task-center-modal"
|
||||
wrapClassName="task-center-modal"
|
||||
width="860px"
|
||||
:mask-closable="false"
|
||||
:footer="false"
|
||||
@close="onClose"
|
||||
:footer="null"
|
||||
@cancel="onClose"
|
||||
centered
|
||||
>
|
||||
<a-tabs :active-key="activeTab" @tab-click="handleTabClick">
|
||||
<a-tab-pane key="0" title="导入"> </a-tab-pane>
|
||||
<a-tab-pane key="1" title="导出"> </a-tab-pane>
|
||||
</a-tabs>
|
||||
<Tabs v-model:activeKey="activeTab" @change="handleTabClick">
|
||||
<TabPane key="1" tab="导入"> </TabPane>
|
||||
<TabPane key="2" tab="导出"> </TabPane>
|
||||
</Tabs>
|
||||
<div class="content">
|
||||
<component :is="activeTab === '0' ? ImportTask : ExportTask" ref="componentRef" />
|
||||
<component :is="activeTab === '1' ? ImportTask : ExportTask" ref="componentRef" />
|
||||
</div>
|
||||
</a-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { Checkbox, Modal, Button, Tabs, notification } from 'ant-design-vue';
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
import ExportTask from './components/export-task';
|
||||
import ImportTask from './components/import-task';
|
||||
|
||||
const visible = ref(false);
|
||||
const componentRef = ref(null);
|
||||
const activeTab = ref('0');
|
||||
const activeTab = ref('1');
|
||||
|
||||
let timer = null;
|
||||
|
||||
const handleTabClick = (key) => {
|
||||
activeTab.value = key;
|
||||
// activeTab.value = key;
|
||||
nextTick(() => {
|
||||
getData();
|
||||
});
|
||||
@ -42,20 +44,21 @@ const getData = () => {
|
||||
};
|
||||
|
||||
const open = () => {
|
||||
getData();
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
getData();
|
||||
});
|
||||
|
||||
timer = setInterval(() => {
|
||||
getData();
|
||||
}, 10000);
|
||||
|
||||
visible.value = true;
|
||||
};
|
||||
const onClose = () => {
|
||||
activeTab.value = '0';
|
||||
|
||||
clearTimer();
|
||||
componentRef.value?.unloadComp?.();
|
||||
Notification.clear();
|
||||
notification.destroy();
|
||||
visible.value = false;
|
||||
};
|
||||
const clearTimer = () => {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.task-center-modal {
|
||||
.arco-modal-header {
|
||||
.ant-modal-header {
|
||||
border-bottom: none !important;
|
||||
.arco-modal-title {
|
||||
.ant-modal-title {
|
||||
color: var(--Text-1, #211f24);
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
@ -10,7 +10,7 @@
|
||||
font-family: $font-family-medium;
|
||||
}
|
||||
}
|
||||
.arco-modal-body {
|
||||
.ant-modal-body {
|
||||
padding: 0 !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user