Merge commit '892234762d1c9de0a0540a722428fe8cc4970f12' into test_任务管理v2
* commit '892234762d1c9de0a0540a722428fe8cc4970f12': (35 commits) refactor(material-center): 重构删除文件模态框组件 perf(material-center): 优化原料上传逻辑 refactor(user): 重构用户信息获 perf: 调整 perf: 增加拖拽文件进入态 perf: 增加maskClosable限制 perf(add-raw-material-drawer): 添加文件夹上传检查并调整样式 perf: 去掉轮训 perf: 标签为空展示 perf(table): 更新标签文本样式 ``` style(ant-select.scss): 更新复选样式和标签样式在`ant-select.scss`文件中添加了复选相关的样式,并对`.ant-tag`元素进行了详细的样式定义,包括内边距、边框半径、背景色等。同时调整了`.ant-tag .anticon-close`的字体大小。 ``` perf(ant-tag.scss): 更新标签样式并增加字体属性更新了.ant-tag的样式,包括:- 将border-radius从2px改为4px- 添加了font-family, font-style和font-weight属性feat(add-raw-material-drawer, edit-raw-material-modal): 增加标签渲染功能 ``` perf: 标签选择交互调整 style(layout): 优化导航栏右侧菜单项样式 style(input): 优化输入框样式和功能 style(button): 调整按钮激活状态样式 feat(manuscript): 新增稿件来源列并优化相关展示 feat(material-center): 增加原料库编辑功能并优化列表展示 feat: 添加文件类型扩展名常量和优化表格列显示 feat: 优化原料库上传功能和标签管理 ...
This commit is contained in:
16
src/App.vue
16
src/App.vue
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<ConfigProvider :locale="zhCN" :theme="redTheme">
|
<ConfigProvider :autoInsertSpaceInButton="false" :locale="zhCN" :theme="redTheme">
|
||||||
<router-view v-if="$route.path === '/login' || ['ExploreList', 'ExploreDetail', 'Trial'].includes($route.name)" />
|
<router-view v-if="$route.meta.withoutLayout" />
|
||||||
<LayoutBasic v-else />
|
<LayoutBasic v-else />
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</template>
|
</template>
|
||||||
@ -8,18 +8,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
// import { useChatStore } from '@/stores/modules/chat';
|
// import { useChatStore } from '@/stores/modules/chat';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { initApp } from '@/utils/user';
|
import { handleUserHome, initApp } from '@/utils/user';
|
||||||
import { useSidebarStore } from '@/stores/modules/side-bar';
|
import { useSidebarStore } from '@/stores/modules/side-bar';
|
||||||
|
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||||
|
|
||||||
import { ConfigProvider } from 'ant-design-vue';
|
import { ConfigProvider } from 'ant-design-vue';
|
||||||
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
||||||
import 'dayjs/locale/zh-cn';
|
import 'dayjs/locale/zh-cn';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
// const route = useRoute();
|
const route = useRoute();
|
||||||
const sidebarStore = useSidebarStore();
|
const sidebarStore = useSidebarStore();
|
||||||
// const chatStore = useChatStore();
|
// const chatStore = useChatStore();
|
||||||
|
const enterpriseStore = useEnterpriseStore();
|
||||||
|
|
||||||
const redTheme = {
|
const redTheme = {
|
||||||
token: {
|
token: {
|
||||||
@ -34,7 +36,9 @@ const init = async () => {
|
|||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
await initApp();
|
await initApp();
|
||||||
|
|
||||||
sidebarStore.startUnreadInfoPolling();
|
if (enterpriseStore.isOpenEnterprise && route.name === 'Trial') {
|
||||||
|
handleUserHome();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sidebarStore.stopUnreadInfoPolling();
|
sidebarStore.stopUnreadInfoPolling();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,6 +73,11 @@ export const getVideoPreSignedUrl = (params = {}) => {
|
|||||||
return Http.get('/v1/oss/video-pre-signed-url', params);
|
return Http.get('/v1/oss/video-pre-signed-url', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取文件上传地址
|
||||||
|
export const getFilePreSignedUrl = (params = {}) => {
|
||||||
|
return Http.get('/v1/oss/file-pre-signed-url', params);
|
||||||
|
};
|
||||||
|
|
||||||
// 清除限流
|
// 清除限流
|
||||||
export const postClearRateLimiter = (params = {}) => {
|
export const postClearRateLimiter = (params = {}) => {
|
||||||
return Http.post(`/v1/rate-limiter/clear`, params);
|
return Http.post(`/v1/rate-limiter/clear`, params);
|
||||||
|
|||||||
@ -170,3 +170,40 @@ export const batchDeleteRawMaterials = (params = {}) => {
|
|||||||
export const postRawMaterialsAI = (params = {}) => {
|
export const postRawMaterialsAI = (params = {}) => {
|
||||||
return Http.post('/v1/raw-materials/ai', params);
|
return Http.post('/v1/raw-materials/ai', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 原料库标签-列表
|
||||||
|
export const getRawMaterialTagsList = (params = {}) => {
|
||||||
|
return Http.get('/v1/raw-material-tags/list', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库标签-添加
|
||||||
|
export const posRawMaterialTags = (params = {}) => {
|
||||||
|
return Http.post('/v1/raw-material-tags', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库标签-修改
|
||||||
|
export const putRawMaterialTag = (params = {}) => {
|
||||||
|
const { id, ...rest } = params as { id: string; [key: string]: any };
|
||||||
|
return Http.put(`/v1/raw-material-tags/${id}`, rest);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库标签-删除
|
||||||
|
export const deleteRawMaterialTag = (id: string) => {
|
||||||
|
return Http.delete(`/v1/raw-material-tags/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库-本地批量添加
|
||||||
|
export const postBatchRawMaterial = (params = {}) => {
|
||||||
|
return Http.post('/v1/raw-materials/batch', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库-修改
|
||||||
|
export const putRawMaterial = (params = {}) => {
|
||||||
|
const { id, ...rest } = params as { id: string; [key: string]: any };
|
||||||
|
return Http.put(`/v1/raw-materials/${id}`, rest);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 原料库-详情
|
||||||
|
export const getRawMaterialDetail = (id: string) => {
|
||||||
|
return Http.get(`/v1/raw-materials/${id}`);
|
||||||
|
};
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export const fetchLogOut = (params = {}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 导出一个名为fetchProfileInfo的函数,用于获取用户信息
|
// 导出一个名为fetchProfileInfo的函数,用于获取用户信息
|
||||||
export const fetchProfileInfo = (params = {}) => {
|
export const fetchUserInfo = (params = {}) => {
|
||||||
// 使用Http.put方法,向/v1/me接口发送put请求,并将params作为参数传递
|
// 使用Http.put方法,向/v1/me接口发送put请求,并将params作为参数传递
|
||||||
return Http.get('/v1/me', params);
|
return Http.get('/v1/me', params);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -20,12 +20,22 @@
|
|||||||
|
|
||||||
<!-- 头像设置 -->
|
<!-- 头像设置 -->
|
||||||
<Dropdown trigger="click" overlayClassName="layout-avatar-dropdown">
|
<Dropdown trigger="click" overlayClassName="layout-avatar-dropdown">
|
||||||
<div class="cursor-pointer">
|
<div
|
||||||
<Avatar :src="userInfo.head_image" :size="32" v-if="userInfo.head_image" />
|
class="w-126px h-32px flex items-center justify-between px-4px pl-4px pr-8px rounded-30px bg-white bg-opacity-60 group"
|
||||||
<div v-else class="w-32px h-32px rounded-50% bg-#6D4CFE flex items-center justify-center">
|
>
|
||||||
<span class="color-#FFF text-14px font-400 lh-22px">{{ userInfo.mobile?.slice(-3) }}</span>
|
<div class="flex mr-4px overflow-hidden h-24px lh-24px items-center">
|
||||||
|
<div class="cursor-pointer mr-4px">
|
||||||
|
<Avatar v-if="userData.head_image" :size="24" :src="userData.head_image" />
|
||||||
|
<div v-else class="w-24px h-24px rounded-50% bg-#6D4CFE flex items-center justify-center">
|
||||||
|
<span class="color-#FFF text-11px font-400 lh-20px">{{ userData.mobile?.slice(-3) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<TextOverTips :context="userData.name || userData.mobile" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<icon-caret-down class="icon-caret color-#939499" size="14" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem>
|
<MenuItem>
|
||||||
@ -65,7 +75,7 @@
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<template v-if="item.audit_status === 1">
|
<template v-if="item.audit_status === 1">
|
||||||
<div class="w-full h-1px bg-#E6E6E8 mb-8px" v-if="enterprises.length > 0"></div>
|
<div v-if="enterprises.length > 1" class="w-full h-1px bg-#E6E6E8 mb-8px"></div>
|
||||||
<MenuItem class="rounded-8px hover:bg-#F2F3F5 h-36px !mb-0" @click="onCreate(item)">
|
<MenuItem class="rounded-8px hover:bg-#F2F3F5 h-36px !mb-0" @click="onCreate(item)">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<SvgIcon size="16.5" name="svg-organization" class="color-#737478 mr-8px" />
|
<SvgIcon size="16.5" name="svg-organization" class="color-#737478 mr-8px" />
|
||||||
@ -83,7 +93,7 @@
|
|||||||
class="flex items-center w-100% flex-1 overflow-hidden"
|
class="flex items-center w-100% flex-1 overflow-hidden"
|
||||||
:class="enterpriseInfo?.id === item.id ? '!color-#6D4CFE' : ''"
|
:class="enterpriseInfo?.id === item.id ? '!color-#6D4CFE' : ''"
|
||||||
>
|
>
|
||||||
<TextoverTips :context="item.name" />
|
<TextOverTips :context="item.name" />
|
||||||
<img :src="icon4" width="12" height="12" class="ml-4px" />
|
<img :src="icon4" width="12" height="12" class="ml-4px" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@ -145,7 +155,7 @@ import icon1 from '@/assets/option.svg';
|
|||||||
import icon2 from '@/assets/exit.svg';
|
import icon2 from '@/assets/exit.svg';
|
||||||
import icon3 from '@/assets/change.svg';
|
import icon3 from '@/assets/change.svg';
|
||||||
import icon4 from './img/admin.png';
|
import icon4 from './img/admin.png';
|
||||||
import TextoverTips from '@/components/text-over-tips/index.vue';
|
import TextOverTips from '@/components/text-over-tips/index.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
isAgentRoute: {
|
isAgentRoute: {
|
||||||
@ -174,7 +184,8 @@ const primary_enterprise = computed(() => userStore.userInfo?.primary_enterprise
|
|||||||
const enterprises = computed(() => {
|
const enterprises = computed(() => {
|
||||||
return userStore.userInfo?.enterprises ?? [];
|
return userStore.userInfo?.enterprises ?? [];
|
||||||
});
|
});
|
||||||
const userInfo = computed(() => userStore.userInfo);
|
const userData = computed(() => userStore.userInfo ?? {});
|
||||||
|
|
||||||
const enterpriseInfo = computed(() => {
|
const enterpriseInfo = computed(() => {
|
||||||
return enterpriseStore?.enterpriseInfo ?? {};
|
return enterpriseStore?.enterpriseInfo ?? {};
|
||||||
});
|
});
|
||||||
@ -231,7 +242,6 @@ const handleSubAccountClick = (item) => {
|
|||||||
|
|
||||||
.ant-dropdown-menu-item {
|
.ant-dropdown-menu-item {
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
margin-bottom: 8px;
|
|
||||||
font-family: $font-family-regular;
|
font-family: $font-family-regular;
|
||||||
color: var(--Text-1, #211f24);
|
color: var(--Text-1, #211f24);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@ -239,6 +249,10 @@ const handleSubAccountClick = (item) => {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-dropdown-menu-title-content {
|
.ant-dropdown-menu-title-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|||||||
@ -31,4 +31,17 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group {
|
||||||
|
&.ant-dropdown-open {
|
||||||
|
.icon-caret {
|
||||||
|
color: #6D4CFE;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.overflow-text) {
|
||||||
|
color: #6D4CFE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export const router = createRouter({
|
|||||||
meta: {
|
meta: {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
requireLogin: false,
|
requireLogin: false,
|
||||||
|
withoutLayout: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -50,6 +51,7 @@ export const router = createRouter({
|
|||||||
meta: {
|
meta: {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
requireLogin: true,
|
requireLogin: true,
|
||||||
|
withoutLayout: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -120,6 +120,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [
|
|||||||
requireLogin: false,
|
requireLogin: false,
|
||||||
hideFooter: true,
|
hideFooter: true,
|
||||||
hideSidebar: true,
|
hideSidebar: true,
|
||||||
|
withoutLayout: true,
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
},
|
},
|
||||||
component: () => import('@/views/material-center/components/finished-products/explore/list/index.vue'),
|
component: () => import('@/views/material-center/components/finished-products/explore/list/index.vue'),
|
||||||
@ -133,6 +134,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [
|
|||||||
requireLogin: false,
|
requireLogin: false,
|
||||||
hideFooter: true,
|
hideFooter: true,
|
||||||
hideSidebar: true,
|
hideSidebar: true,
|
||||||
|
withoutLayout: true,
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
},
|
},
|
||||||
component: () => import('@/views/material-center/components/finished-products/explore/detail/index.vue'),
|
component: () => import('@/views/material-center/components/finished-products/explore/detail/index.vue'),
|
||||||
|
|||||||
1
src/router/typeings.d.ts
vendored
1
src/router/typeings.d.ts
vendored
@ -19,5 +19,6 @@ declare module 'vue-router' {
|
|||||||
requireLogin?: boolean; // 是否需要登陆才能访问
|
requireLogin?: boolean; // 是否需要登陆才能访问
|
||||||
independent?: boolean; // 独立于layout的路由
|
independent?: boolean; // 独立于layout的路由
|
||||||
group?: string; // 路由分组
|
group?: string; // 路由分组
|
||||||
|
withoutLayout?: boolean; // 不使用layout,默认false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export const useChatStore = defineStore('chat', {
|
|||||||
clearAgentInfo() {
|
clearAgentInfo() {
|
||||||
this.agentInfo = {};
|
this.agentInfo = {};
|
||||||
this.searchValue = '';
|
this.searchValue = '';
|
||||||
|
rlsWithCatch('agentInfo');
|
||||||
},
|
},
|
||||||
async onCreateSession() {
|
async onCreateSession() {
|
||||||
const { code, data } = await createSession();
|
const { code, data } = await createSession();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { fetchEnterpriseInfo } from '@/api/all/login';
|
import { fetchEnterpriseInfo } from '@/api/all/login';
|
||||||
import { glsWithCatch, slsWithCatch } from '@/utils/stroage';
|
import { glsWithCatch, slsWithCatch, rlsWithCatch } from '@/utils/stroage';
|
||||||
|
|
||||||
interface EnterpriseInfo {
|
interface EnterpriseInfo {
|
||||||
id: number | string;
|
id: number | string;
|
||||||
@ -34,7 +34,7 @@ export const useEnterpriseStore = defineStore('enterprise', {
|
|||||||
},
|
},
|
||||||
clearUserEnterpriseInfo() {
|
clearUserEnterpriseInfo() {
|
||||||
this.enterpriseInfo = null;
|
this.enterpriseInfo = null;
|
||||||
localStorage.removeItem('enterpriseInfo');
|
rlsWithCatch('enterpriseInfo');
|
||||||
},
|
},
|
||||||
setEnterpriseName(name: string) {
|
setEnterpriseName(name: string) {
|
||||||
if (this.enterpriseInfo) {
|
if (this.enterpriseInfo) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { fetchProfileInfo } from '@/api/all/login';
|
import { fetchUserInfo } from '@/api/all/login';
|
||||||
// import { useSidebarStore } from '@/stores/modules/side-bar';
|
// import { useSidebarStore } from '@/stores/modules/side-bar';
|
||||||
import { glsWithCatch, rlsWithCatch, slsWithCatch } from '@/utils/stroage';
|
import { glsWithCatch, rlsWithCatch, slsWithCatch } from '@/utils/stroage';
|
||||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||||
@ -72,7 +72,7 @@ export const useUserStore = defineStore('user', {
|
|||||||
async getUserInfo() {
|
async getUserInfo() {
|
||||||
const enterpriseStore = useEnterpriseStore();
|
const enterpriseStore = useEnterpriseStore();
|
||||||
|
|
||||||
const { code, data } = await fetchProfileInfo();
|
const { code, data } = await fetchUserInfo();
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
this.setUserInfo(data);
|
this.setUserInfo(data);
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.ant-btn-default {
|
.ant-btn-default {
|
||||||
&:disabled {
|
&:disabled {
|
||||||
@ -51,6 +52,8 @@
|
|||||||
background-color: $color-primary !important;
|
background-color: $color-primary !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
|
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
@ -66,7 +69,14 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
outline-offset: unset;
|
outline-offset: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: #fff !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
background-color: $color-primary-7 !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.ant-btn-dangerous {
|
&.ant-btn-dangerous {
|
||||||
background-color: $color-error !important;
|
background-color: $color-error !important;
|
||||||
&:disabled {
|
&:disabled {
|
||||||
@ -76,6 +86,10 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: $color-error-5 !important;
|
background-color: $color-error-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: $color-error-7 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.ant-btn-background-ghost {
|
&.ant-btn-background-ghost {
|
||||||
@ -93,6 +107,12 @@
|
|||||||
color: $color-primary-5 !important;
|
color: $color-primary-5 !important;
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: $color-primary-7 !important;
|
||||||
|
color: $color-primary-7 !important;
|
||||||
|
background-color: #fff !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.ant-btn-dangerous {
|
&.ant-btn-dangerous {
|
||||||
border: 1px solid $color-error !important;
|
border: 1px solid $color-error !important;
|
||||||
@ -107,6 +127,11 @@
|
|||||||
border-color: $color-error-5 !important;
|
border-color: $color-error-5 !important;
|
||||||
color: $color-error-5 !important;
|
color: $color-error-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: $color-error-7 !important;
|
||||||
|
color: $color-error-7 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +149,13 @@
|
|||||||
border-color: $color-primary-5 !important;
|
border-color: $color-primary-5 !important;
|
||||||
color: $color-primary-5 !important;
|
color: $color-primary-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: $color-primary-7 !important;
|
||||||
|
color: $color-primary-7 !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.ant-btn-dangerous {
|
&.ant-btn-dangerous {
|
||||||
border: 1px solid $color-error !important;
|
border: 1px solid $color-error !important;
|
||||||
color: $color-error !important;
|
color: $color-error !important;
|
||||||
@ -137,6 +168,11 @@
|
|||||||
border-color: $color-error-5 !important;
|
border-color: $color-error-5 !important;
|
||||||
color: $color-error-5 !important;
|
color: $color-error-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: $color-error-7 !important;
|
||||||
|
color: $color-error-7 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,6 +190,11 @@
|
|||||||
color: $color-primary-5 !important;
|
color: $color-primary-5 !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: $color-primary-7 !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.ant-btn-dangerous {
|
&.ant-btn-dangerous {
|
||||||
color: $color-error !important;
|
color: $color-error !important;
|
||||||
@ -164,6 +205,10 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: $color-error-5 !important;
|
color: $color-error-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: $color-error-7 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,6 +226,11 @@
|
|||||||
color: $color-primary-5 !important;
|
color: $color-primary-5 !important;
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: $color-primary-7 !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.ant-btn-dangerous {
|
&.ant-btn-dangerous {
|
||||||
color: $color-error !important;
|
color: $color-error !important;
|
||||||
@ -191,6 +241,10 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: $color-error-5 !important;
|
color: $color-error-5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: $color-error-7 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/styles/components/ant-drawer.scss
Normal file
20
src/styles/components/ant-drawer.scss
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.ant-drawer {
|
||||||
|
.ant-drawer-header {
|
||||||
|
.ant-drawer-header-title {
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.ant-drawer-close {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-drawer-title {
|
||||||
|
color: #211f24;
|
||||||
|
font-family: $font-family-medium;
|
||||||
|
font-size: 18px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@
|
|||||||
color: var(--Text-4, #939499);
|
color: var(--Text-4, #939499);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
}
|
}
|
||||||
@ -43,6 +44,15 @@
|
|||||||
border-color: $color-error !important;
|
border-color: $color-error !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:-webkit-autofill,
|
||||||
|
&:-webkit-autofill:hover,
|
||||||
|
&:-webkit-autofill:focus,
|
||||||
|
&:-webkit-autofill:active {
|
||||||
|
-webkit-transition-delay: 99999s;
|
||||||
|
-webkit-transition: color 99999s ease-out,
|
||||||
|
background-color 99999s ease-out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
input.ant-input {
|
input.ant-input {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@ -60,29 +70,7 @@ textarea.ant-input {
|
|||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
@include box;
|
@include box;
|
||||||
&.ant-input-affix-wrapper-disabled {
|
|
||||||
background-color: var(--BG-200, #f2f3f5) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ant-input-affix-wrapper-status-error {
|
|
||||||
&:not(.ant-input-affix-wrapper-disabled) {
|
|
||||||
border-color: $color-error !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:focus,
|
|
||||||
&-focused {
|
|
||||||
box-shadow: none !important;
|
|
||||||
border-color: $color-primary !important;
|
|
||||||
}
|
|
||||||
.ant-input {
|
|
||||||
height: 30px;
|
|
||||||
&.ant-input-lg {
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
&.ant-input-sm {
|
|
||||||
height: 26px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-input-suffix {
|
.ant-input-suffix {
|
||||||
.ant-input-show-count-suffix {
|
.ant-input-show-count-suffix {
|
||||||
color: var(--Text-4, #939499);
|
color: var(--Text-4, #939499);
|
||||||
@ -92,5 +80,51 @@ textarea.ant-input {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-input-clear-icon {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-input-affix-wrapper-disabled {
|
||||||
|
background-color: var(--BG-200, #f2f3f5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.ant-input-affix-wrapper-disabled) {
|
||||||
|
&.ant-input-affix-wrapper-status-error {
|
||||||
|
border-color: $color-error !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $color-primary !important;
|
||||||
|
|
||||||
|
.ant-input-clear-icon {
|
||||||
|
&:not(.ant-input-clear-icon-hidden) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:focus,
|
||||||
|
&-focused {
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-color: $color-primary !important;
|
||||||
|
|
||||||
|
.ant-input-clear-icon {
|
||||||
|
&:not(.ant-input-clear-icon-hidden) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
height: 30px;
|
||||||
|
&.ant-input-lg {
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
&.ant-input-sm {
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-modal-body {
|
.ant-modal-body {
|
||||||
padding: 24px 20px;
|
padding: 20px 24px;
|
||||||
}
|
}
|
||||||
.ant-modal-footer {
|
.ant-modal-footer {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
@ -38,5 +38,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-modal-confirm-body-wrapper {
|
||||||
|
.ant-modal-confirm-title {
|
||||||
|
.anticon {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-confirm-content {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: var(--Text-2, #55585F);
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ant-modal-confirm-btns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,11 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-select-arrow {
|
||||||
|
color: #737478;
|
||||||
|
//font-size: 14px;
|
||||||
|
}
|
||||||
&:focus,
|
&:focus,
|
||||||
&-focused {
|
&-focused {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
@ -36,6 +41,19 @@
|
|||||||
border-color: $color-error !important;
|
border-color: $color-error !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.ant-select-disabled) {
|
||||||
|
&:hover {
|
||||||
|
.ant-select-selector {
|
||||||
|
border-color: rgb(var(--primary-6)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled {
|
||||||
|
.ant-select-selector {
|
||||||
|
background-color: var(--BG-200, #f2f3f5) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,12 +74,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 复选
|
||||||
&.ant-select-multiple {
|
&.ant-select-multiple {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
padding: 0 12px 0 4px !important;
|
height: fit-content !important;
|
||||||
|
padding: 0 28px 0 4px !important;
|
||||||
|
|
||||||
.ant-select-selection-overflow-item {
|
.ant-select-selection-overflow-item {
|
||||||
|
margin-right: 4px;
|
||||||
.ant-select-selection-item {
|
.ant-select-selection-item {
|
||||||
|
margin-right: 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #E6E6E8;
|
background: #E6E6E8;
|
||||||
border: none;
|
border: none;
|
||||||
@ -71,6 +93,22 @@
|
|||||||
color: #737478;
|
color: #737478;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-tag {
|
||||||
|
padding: 1px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--BG-300, #E6E6E8);
|
||||||
|
color: var(--Text-1, #211F24);
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
.anticon-close {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,25 +136,78 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-tag {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
&.ant-select-single {
|
||||||
|
|
||||||
.ant-select.ant-select-single {
|
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
height: 32px !important;
|
height: 32px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-select-lg {
|
&.ant-select-lg {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
height: 36px !important;
|
height: 36px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-select-sm {
|
&.ant-select-sm {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
height: 28px !important;
|
height: 28px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-dropdown {
|
||||||
|
padding: 4px 0;
|
||||||
|
|
||||||
|
.ant-select-item-option {
|
||||||
|
padding: 0 12px;
|
||||||
|
height: 36px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.ant-select-item-option-state {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.ant-select-item-option-disabled) {
|
||||||
|
&:hover {
|
||||||
|
background-color: #F2F3F5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-item-option-content {
|
||||||
|
color: #211F24;
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-item-option-selected {
|
||||||
|
background-color: transparent !important;
|
||||||
|
color: #6D4CFE !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #F2F3F5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select-item-option-content {
|
||||||
|
color: #6D4CFE;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: $font-family-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-select-item-option-active {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
.ant-tag{
|
.ant-tag {
|
||||||
border-radius: 2px;
|
border-radius: 4px;
|
||||||
border: none;
|
border: none;
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
@ -2,4 +2,25 @@
|
|||||||
.ant-input {
|
.ant-input {
|
||||||
padding: 8px 12px 4px 12px;
|
padding: 8px 12px 4px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.ant-input-textarea-disabled) {
|
||||||
|
&:hover {
|
||||||
|
.ant-input {
|
||||||
|
border-color: rgb(var(--primary-6)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.ant-input-textarea-show-count {
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
bottom: 4px;
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
color: #939499;
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,3 +27,4 @@
|
|||||||
@import "./ant-switch.scss";
|
@import "./ant-switch.scss";
|
||||||
@import "./ant-step.scss";
|
@import "./ant-step.scss";
|
||||||
@import "./ant-spin.scss";
|
@import "./ant-spin.scss";
|
||||||
|
@import "./ant-drawer.scss";
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
|
||||||
export function toFixed(num: number | string, n: number): number {
|
export function toFixed(num: number | string, n: number): number {
|
||||||
return parseFloat(parseFloat(num.toString()).toFixed(n));
|
return parseFloat(parseFloat(num.toString()).toFixed(n));
|
||||||
}
|
}
|
||||||
@ -111,11 +112,15 @@ export function genRandomId() {
|
|||||||
return `id_${dayjs().unix()}_${Math.floor(Math.random() * 10000)}`;
|
return `id_${dayjs().unix()}_${Math.floor(Math.random() * 10000)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFileExtension(filename) {
|
||||||
|
const match = filename.match(/\.([^.]+)$/);
|
||||||
|
return match ? match[1].toLowerCase() : '';
|
||||||
|
}
|
||||||
export function formatFileSize(bytes: number): string {
|
export function formatFileSize(bytes: number): string {
|
||||||
if (bytes === 0) return '0 Bytes';
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
|
||||||
const k = 1024;
|
const k = 1024;
|
||||||
const sizes = ['Bytes', 'kb', 'mB', 'gB', 'tB'];
|
const sizes = ['Bytes', 'kb', 'mb', 'gb', 'tb'];
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||||
@ -217,7 +222,7 @@ export function getVideoInfo(file: File): Promise<{ duration: number; firstFrame
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 设置视频源以触发加载
|
// 设置视频源以触发加载
|
||||||
video.src = URL.createObjectURL(file);
|
video.src = window.URL.createObjectURL(file);
|
||||||
|
|
||||||
// 设置超时,防止长时间无响应
|
// 设置超时,防止长时间无响应
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@ -42,9 +42,9 @@ export async function initApp() {
|
|||||||
const enterpriseStore = useEnterpriseStore();
|
const enterpriseStore = useEnterpriseStore();
|
||||||
|
|
||||||
await userStore.getUserInfo(); // 初始化用户信息
|
await userStore.getUserInfo(); // 初始化用户信息
|
||||||
|
await getUserEnterpriseInfo(); // 初始化企业信息
|
||||||
|
|
||||||
if (enterpriseStore.isOpenEnterprise) {
|
if (enterpriseStore.isOpenEnterprise) {
|
||||||
await getUserEnterpriseInfo(); // 初始化企业信息
|
|
||||||
chatStore.getAgentInfo(); // 初始化智能体信息
|
chatStore.getAgentInfo(); // 初始化智能体信息
|
||||||
|
|
||||||
sidebarStore.startUnreadInfoPolling(); // 初始化未读信息
|
sidebarStore.startUnreadInfoPolling(); // 初始化未读信息
|
||||||
|
|||||||
@ -14,18 +14,25 @@
|
|||||||
<p class="cts mt-36px !color-#211F24 mb-24px">验证成功,请更改密码</p>
|
<p class="cts mt-36px !color-#211F24 mb-24px">验证成功,请更改密码</p>
|
||||||
<Form ref="formRef" :model="formData" :rules="formRules" auto-label-width class="w-348 form-wrap">
|
<Form ref="formRef" :model="formData" :rules="formRules" auto-label-width class="w-348 form-wrap">
|
||||||
<FormItem name="password" class="password-form-item">
|
<FormItem name="password" class="password-form-item">
|
||||||
<Input.Password v-model:value="formData.password" placeholder="新密码" size="large" class="!h-48px">
|
<Input.Password
|
||||||
|
v-model:value="formData.password"
|
||||||
|
class="!h-48px"
|
||||||
|
placeholder="新密码"
|
||||||
|
size="large"
|
||||||
|
@change="onPasswordChange"
|
||||||
|
>
|
||||||
<template #iconRender="visible">
|
<template #iconRender="visible">
|
||||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||||
</template>
|
</template>
|
||||||
</Input.Password>
|
</Input.Password>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="confirm_password" class="password-form-item">
|
<FormItem class="password-form-item !mb-36px" name="confirm_password">
|
||||||
<Input.Password
|
<Input.Password
|
||||||
v-model:value="formData.confirm_password"
|
v-model:value="formData.confirm_password"
|
||||||
placeholder="密码确认"
|
placeholder="密码确认"
|
||||||
size="large"
|
size="large"
|
||||||
class="!h-48px"
|
class="!h-48px"
|
||||||
|
@change="onPasswordChange"
|
||||||
>
|
>
|
||||||
<template #iconRender="visible">
|
<template #iconRender="visible">
|
||||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||||
@ -37,7 +44,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
:disabled="disabledSubmitBtn"
|
:disabled="disabledSubmitBtn"
|
||||||
:loading="submitLoading"
|
:loading="submitLoading"
|
||||||
class="w-full !h-48px mt-36px !rounded-8px"
|
class="w-full !h-48px mt-36px !rounded-8px h-22px"
|
||||||
@click="handleSubmit"
|
@click="handleSubmit"
|
||||||
>完成更改
|
>完成更改
|
||||||
</Button>
|
</Button>
|
||||||
@ -54,7 +61,9 @@
|
|||||||
<p class="cts !text-12px !lh-20px !color-#939499" v-if="countdown > 0">
|
<p class="cts !text-12px !lh-20px !color-#939499" v-if="countdown > 0">
|
||||||
{{ countdown }} 秒后您可以再次发送验证码
|
{{ countdown }} 秒后您可以再次发送验证码
|
||||||
</p>
|
</p>
|
||||||
<Button type="text" class="pl-0" v-if="hasGetCode && countdown === 0" @click="getCaptcha">重新发送</Button>
|
<Button v-if="hasGetCode && countdown === 0" class="pl-0 h-22px" type="text" @click="getCaptcha"
|
||||||
|
>重新发送
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -79,6 +88,11 @@ import icon2 from '@/assets/img/login/icon-open.png';
|
|||||||
|
|
||||||
const emit = defineEmits(['success', 'cancel']);
|
const emit = defineEmits(['success', 'cancel']);
|
||||||
|
|
||||||
|
const INITIAL_FORM_DATA = {
|
||||||
|
captcha: '',
|
||||||
|
password: '',
|
||||||
|
confirm_password: '',
|
||||||
|
};
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const phone = ref('');
|
const phone = ref('');
|
||||||
const isCheckPass = ref(false);
|
const isCheckPass = ref(false);
|
||||||
@ -90,11 +104,7 @@ const timer = ref<number | null>(null);
|
|||||||
const hasGetCode = ref(false);
|
const hasGetCode = ref(false);
|
||||||
const submitLoading = ref(false);
|
const submitLoading = ref(false);
|
||||||
const verificationCodeRef = ref(null);
|
const verificationCodeRef = ref(null);
|
||||||
const formData = ref({
|
const formData = ref(cloneDeep(INITIAL_FORM_DATA));
|
||||||
captcha: '',
|
|
||||||
password: '',
|
|
||||||
confirm_password: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const formRules = {
|
const formRules = {
|
||||||
password: [
|
password: [
|
||||||
@ -113,7 +123,7 @@ const formRules = {
|
|||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
validator: (_rule, value) => {
|
validator: (_rule, value) => {
|
||||||
if (value !== formData.value.password) {
|
if (value && value !== formData.value.password) {
|
||||||
return Promise.reject('确认密码与设置的密码不同');
|
return Promise.reject('确认密码与设置的密码不同');
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@ -143,6 +153,12 @@ const onCheckPass = (captcha) => {
|
|||||||
formData.value.captcha = captcha;
|
formData.value.captcha = captcha;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onPasswordChange = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
formRef.value.clearValidate('confirm_password');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getCaptcha = async () => {
|
const getCaptcha = async () => {
|
||||||
try {
|
try {
|
||||||
const { code, message: msg } = await postUpdatePasswordCaptcha();
|
const { code, message: msg } = await postUpdatePasswordCaptcha();
|
||||||
@ -216,6 +232,8 @@ const onClose = () => {
|
|||||||
countdown.value = 0;
|
countdown.value = 0;
|
||||||
hasGetCode.value = false;
|
hasGetCode.value = false;
|
||||||
submitLoading.value = false;
|
submitLoading.value = false;
|
||||||
|
isCheckPass.value = false;
|
||||||
|
formData.value = cloneDeep(INITIAL_FORM_DATA);
|
||||||
formRef.value?.resetFields();
|
formRef.value?.resetFields();
|
||||||
formRef.value?.clearValidate();
|
formRef.value?.clearValidate();
|
||||||
clearTimer();
|
clearTimer();
|
||||||
|
|||||||
@ -39,14 +39,10 @@
|
|||||||
|
|
||||||
.ant-form {
|
.ant-form {
|
||||||
.ant-form-item {
|
.ant-form-item {
|
||||||
&:not(:last-child) {
|
|
||||||
margin-bottom: 24px !important;
|
margin-bottom: 24px !important;
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-affix-wrapper {
|
.ant-input-affix-wrapper {
|
||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,9 @@
|
|||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
:class="{ error: item.error, fill: item.value }"
|
:class="{ error: isError, fill: item.value }"
|
||||||
@input="handleInput(index, $event.target.value)"
|
@input="handleInput(index, $event.target.value)"
|
||||||
@focus="handleFocus(index)"
|
@focus="handleFocus"
|
||||||
@blur="handleBlur(index)"
|
|
||||||
:maxlength="1"
|
:maxlength="1"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
/>
|
/>
|
||||||
@ -34,11 +33,21 @@ const emits = defineEmits(['success']);
|
|||||||
const codeArray = ref([]);
|
const codeArray = ref([]);
|
||||||
const activeIndex = ref(0); // 当前激活的输入框索引
|
const activeIndex = ref(0); // 当前激活的输入框索引
|
||||||
const errorMessage = ref('');
|
const errorMessage = ref('');
|
||||||
|
const isError = ref(false);
|
||||||
const inputRef = ref(null);
|
const inputRef = ref(null);
|
||||||
|
|
||||||
|
const handleFocus = (index) => {
|
||||||
|
isError.value = false;
|
||||||
|
errorMessage.value = '';
|
||||||
|
};
|
||||||
// 处理输入事件
|
// 处理输入事件
|
||||||
const handleInput = (index, value) => {
|
const handleInput = (index, value) => {
|
||||||
if (!value || !/^\d$/.test(value)) return;
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isError.value = false;
|
||||||
|
errorMessage.value = '';
|
||||||
|
|
||||||
codeArray.value[index].value = value;
|
codeArray.value[index].value = value;
|
||||||
|
|
||||||
@ -48,45 +57,36 @@ const handleInput = (index, value) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFocus = (index) => {
|
|
||||||
activeIndex.value = index;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBlur = (index) => {
|
|
||||||
const _value = codeArray.value[index].value;
|
|
||||||
if (!_value || !/^\d$/.test(_value)) {
|
|
||||||
codeArray.value[index].error = true;
|
|
||||||
} else {
|
|
||||||
if (errorMessage.value) {
|
|
||||||
codeArray.value.forEach((item) => {
|
|
||||||
item.error = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
errorMessage.value = '';
|
|
||||||
codeArray.value[index].error = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 验证验证码逻辑
|
// 验证验证码逻辑
|
||||||
const validateCode = async () => {
|
const validateCode = async () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
isError.value = codeArray.value.some((_value) => !_value);
|
||||||
|
isError.value ? reject() : resolve();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
validateCode().then(async () => {
|
||||||
const captcha = codeArray.value.map((item) => item.value).join('');
|
const captcha = codeArray.value.map((item) => item.value).join('');
|
||||||
const { code } = await postCheckUpdatePasswordCaptcha({ captcha });
|
const { code } = await postCheckUpdatePasswordCaptcha({ captcha });
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
emits('success', captcha);
|
emits('success', captcha);
|
||||||
} else {
|
} else {
|
||||||
|
inputRef.value?.[activeIndex.value]?.blur?.();
|
||||||
activeIndex.value = 0;
|
activeIndex.value = 0;
|
||||||
inputRef.value?.[activeIndex.value]?.focus?.();
|
|
||||||
errorMessage.value = '验证码错误,请检查后重试';
|
errorMessage.value = '验证码错误,请检查后重试';
|
||||||
|
isError.value = true;
|
||||||
codeArray.value.forEach((item) => {
|
codeArray.value.forEach((item) => {
|
||||||
item.error = true;
|
|
||||||
item.value = '';
|
item.value = '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
activeIndex.value = 0;
|
activeIndex.value = 0;
|
||||||
errorMessage.value = '';
|
errorMessage.value = '';
|
||||||
|
isError.value = false;
|
||||||
inputRef.value = null;
|
inputRef.value = null;
|
||||||
codeArray.value = new Array(6).fill().map(() => ({ value: '', error: false }));
|
codeArray.value = new Array(6).fill().map(() => ({ value: '', error: false }));
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ watch(
|
|||||||
() => codeArray.value,
|
() => codeArray.value,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
if (newVal.every((item) => item.value)) {
|
if (newVal.every((item) => item.value)) {
|
||||||
validateCode();
|
onSubmit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
@ -129,17 +129,20 @@ defineExpose({ init });
|
|||||||
|
|
||||||
caret-color: #6d4cfe;
|
caret-color: #6d4cfe;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
border-color: #f64b31 !important;
|
||||||
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #6d4cfe !important;
|
border-color: #6d4cfe !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus-within {
|
||||||
|
border-color: #6d4cfe !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.fill {
|
&.fill {
|
||||||
color: #6d4cfe;
|
color: #6d4cfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
|
||||||
border-color: #f64b31 !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,12 +43,12 @@
|
|||||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||||
</template>
|
</template>
|
||||||
</Input.Password>
|
</Input.Password>
|
||||||
<p class="color-#F64B31 text-12px font-400 lh-20px font-family-regular" v-show="errMsg">
|
<p v-show="errMsg" class="color-#F64B31 h-20px text-12px font-400 lh-20px font-family-regular">
|
||||||
{{ errMsg }}
|
{{ errMsg }}
|
||||||
</p>
|
</p>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<FormItem class="mt-52px">
|
<FormItem class="mt-32px">
|
||||||
<div class="text-12px flex justify-center items-center mb-16px">
|
<div class="text-12px flex justify-center items-center mb-16px">
|
||||||
<Checkbox v-model:checked="hasCheck" class="mr-8px"></Checkbox>
|
<Checkbox v-model:checked="hasCheck" class="mr-8px"></Checkbox>
|
||||||
<span class="text-12px color-#737478 font-400 lh-20px font-family-regular"
|
<span class="text-12px color-#737478 font-400 lh-20px font-family-regular"
|
||||||
@ -67,14 +67,18 @@
|
|||||||
登录
|
登录
|
||||||
</Button>
|
</Button>
|
||||||
<div class="flex justify-between btn-row">
|
<div class="flex justify-between btn-row">
|
||||||
|
<div>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
v-show="!isCaptchaLogin"
|
||||||
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
||||||
size="small"
|
size="small"
|
||||||
|
type="text"
|
||||||
@click="onForgetPassword"
|
@click="onForgetPassword"
|
||||||
>
|
>
|
||||||
忘记密码?
|
忘记密码?
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
||||||
@ -101,7 +105,7 @@
|
|||||||
import { Button, Checkbox, Form, FormItem, Input, message, Tabs, Typography } from 'ant-design-vue';
|
import { Button, Checkbox, Form, FormItem, Input, message, Tabs, Typography } from 'ant-design-vue';
|
||||||
import PuzzleVerification from '../PuzzleVerification.vue';
|
import PuzzleVerification from '../PuzzleVerification.vue';
|
||||||
import SelectAccountModal from '../select-account-modal/index.vue';
|
import SelectAccountModal from '../select-account-modal/index.vue';
|
||||||
import { fetchAuthorizationsCaptcha, fetchLoginCaptCha, fetchProfileInfo, postLoginPassword } from '@/api/all/login';
|
import { fetchAuthorizationsCaptcha, fetchLoginCaptCha, fetchUserInfo, postLoginPassword } from '@/api/all/login';
|
||||||
import { postClearRateLimiter } from '@/api/all/common';
|
import { postClearRateLimiter } from '@/api/all/common';
|
||||||
import { joinEnterpriseByInviteCode } from '@/api/all';
|
import { joinEnterpriseByInviteCode } from '@/api/all';
|
||||||
import { computed, onUnmounted, reactive, ref } from 'vue';
|
import { computed, onUnmounted, reactive, ref } from 'vue';
|
||||||
@ -264,7 +268,7 @@ const onTabChange = () => {
|
|||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
const getProfileInfo = async () => {
|
const getProfileInfo = async () => {
|
||||||
const { code, data } = await fetchProfileInfo();
|
const { code, data } = await fetchUserInfo();
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
const enterprises = data['enterprises'];
|
const enterprises = data['enterprises'];
|
||||||
mobileNumber.value = data['mobile'];
|
mobileNumber.value = data['mobile'];
|
||||||
@ -279,6 +283,7 @@ const getProfileInfo = async () => {
|
|||||||
selectAccountModalRef.value.open();
|
selectAccountModalRef.value.open();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
userStore.setUserInfo(data);
|
||||||
router.push({ name: 'Trial' });
|
router.push({ name: 'Trial' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center w-400 h-100%">
|
<div class="flex items-center w-400 h-100%">
|
||||||
<div class="w-full bg-#fff rounded-16px px-40px py-32px flex flex-col items-center">
|
<div class="w-full bg-#fff rounded-16px px-40px py-32px flex flex-col items-center">
|
||||||
<div class="flex items-center mb-24px w-full cursor-pointer" @click="onBack">
|
<div class="flex items-center mb-24px w-full">
|
||||||
<icon-left size="24" class="mr-4px color-#000" />
|
<div class="flex items-center cursor-pointer" @click="onBack">
|
||||||
|
<icon-left class="mr-4px color-#000" size="24" />
|
||||||
<span class="color-#000 text-20px font-500 lh-28px font-family-medium">{{
|
<span class="color-#000 text-20px font-500 lh-28px font-family-medium">{{
|
||||||
isResetPassword ? '重置密码' : '手机注册'
|
isResetPassword ? '重置密码' : '手机注册'
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<Form ref="formRef" :model="formData" :rules="formRules" auto-label-width class="w-320 form-wrap">
|
<Form ref="formRef" :model="formData" :rules="formRules" auto-label-width class="w-320 form-wrap">
|
||||||
<FormItem name="mobile">
|
<FormItem name="mobile">
|
||||||
<Input
|
<Input
|
||||||
@ -19,14 +21,14 @@
|
|||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="password" class="password-form-item">
|
<FormItem name="password" class="password-form-item">
|
||||||
<Input.Password v-model:value="formData.password" placeholder="新密码" @change="clearErrorMsg">
|
<Input.Password v-model:value="formData.password" placeholder="新密码" @change="onPasswordChange">
|
||||||
<template #iconRender="visible">
|
<template #iconRender="visible">
|
||||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||||
</template>
|
</template>
|
||||||
</Input.Password>
|
</Input.Password>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem name="confirm_password" class="password-form-item">
|
<FormItem name="confirm_password" class="password-form-item">
|
||||||
<Input.Password v-model:value="formData.confirm_password" placeholder="密码确认" @change="clearErrorMsg">
|
<Input.Password v-model:value="formData.confirm_password" placeholder="密码确认" @change="onPasswordChange">
|
||||||
<template #iconRender="visible">
|
<template #iconRender="visible">
|
||||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||||
</template>
|
</template>
|
||||||
@ -48,12 +50,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Input>
|
</Input>
|
||||||
<p class="color-#F64B31 text-12px font-400 lh-20px font-family-regular" v-show="errMsg">
|
<p class="color-#F64B31 text-12px font-400 lh-20px h-20px font-family-regular">
|
||||||
{{ errMsg }}
|
{{ errMsg }}
|
||||||
</p>
|
</p>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<FormItem class="mt-52px">
|
<FormItem class="mt-32px">
|
||||||
<div class="text-12px flex justify-center items-center mb-16px">
|
<div class="text-12px flex justify-center items-center mb-16px">
|
||||||
<Checkbox v-model:checked="hasCheck" class="mr-8px"></Checkbox>
|
<Checkbox v-model:checked="hasCheck" class="mr-8px"></Checkbox>
|
||||||
<span class="text-12px color-#737478 font-400 lh-20px font-family-regular"
|
<span class="text-12px color-#737478 font-400 lh-20px font-family-regular"
|
||||||
@ -90,7 +92,7 @@ import PuzzleVerification from '../PuzzleVerification.vue';
|
|||||||
import SelectAccountModal from '../select-account-modal/index.vue';
|
import SelectAccountModal from '../select-account-modal/index.vue';
|
||||||
import { postClearRateLimiter } from '@/api/all/common';
|
import { postClearRateLimiter } from '@/api/all/common';
|
||||||
import {
|
import {
|
||||||
fetchProfileInfo,
|
fetchUserInfo,
|
||||||
postForgetPassword,
|
postForgetPassword,
|
||||||
postForgetPasswordCaptcha,
|
postForgetPasswordCaptcha,
|
||||||
postRegister,
|
postRegister,
|
||||||
@ -186,7 +188,7 @@ const formRules = {
|
|||||||
// if (value.length < 6) {
|
// if (value.length < 6) {
|
||||||
// return Promise.reject('密码长度不能小于6位');
|
// return Promise.reject('密码长度不能小于6位');
|
||||||
// }
|
// }
|
||||||
if (value !== formData.value.password) {
|
if (value && value !== formData.value.password) {
|
||||||
return Promise.reject('确认密码与设置的密码不同');
|
return Promise.reject('确认密码与设置的密码不同');
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@ -229,13 +231,20 @@ const canGetCaptcha = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const disabledSubmitBtn = computed(() => {
|
const disabledSubmitBtn = computed(() => {
|
||||||
return !isPassPassword.value || !hasCheck.value || !isLegalMobile.value || !formData.value.password.trim();
|
return !isPassPassword.value || !hasCheck.value || !isLegalMobile.value || !formData.value.password.trim() || !formData.value.captcha;
|
||||||
});
|
});
|
||||||
|
|
||||||
const clearErrorMsg = () => {
|
const clearErrorMsg = () => {
|
||||||
errMsg.value = '';
|
errMsg.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onPasswordChange = () => {
|
||||||
|
clearErrorMsg();
|
||||||
|
nextTick(() => {
|
||||||
|
formRef.value.clearValidate('confirm_password');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const validateField = (field) => {
|
const validateField = (field) => {
|
||||||
formRef.value.validateFields(field);
|
formRef.value.validateFields(field);
|
||||||
};
|
};
|
||||||
@ -286,8 +295,9 @@ const handleVerificationSubmit = async () => {
|
|||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
const getProfileInfo = async () => {
|
const getProfileInfo = async () => {
|
||||||
const { code, data } = await fetchProfileInfo();
|
const { code, data } = await fetchUserInfo();
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
|
|
||||||
const enterprises = data['enterprises'];
|
const enterprises = data['enterprises'];
|
||||||
mobileNumber.value = data['mobile'];
|
mobileNumber.value = data['mobile'];
|
||||||
accounts.value = enterprises;
|
accounts.value = enterprises;
|
||||||
@ -302,6 +312,7 @@ const getProfileInfo = async () => {
|
|||||||
selectAccountModalRef.value.open();
|
selectAccountModalRef.value.open();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
userStore.setUserInfo(data);
|
||||||
router.push({ name: 'Trial' });
|
router.push({ name: 'Trial' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,7 +350,7 @@ const handleSubmit = async () => {
|
|||||||
}, 1500);
|
}, 1500);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
userStore.setToken(data.access_token);
|
userStore.setToken(data.access_token);
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@
|
|||||||
}
|
}
|
||||||
.ant-input-affix-wrapper {
|
.ant-input-affix-wrapper {
|
||||||
height: 48px;
|
height: 48px;
|
||||||
padding: 0 10px;
|
padding: 10px 16px;
|
||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
.ant-input {
|
.ant-input {
|
||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
font-size: 16px;
|
font-size: 16px !important;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
@ -44,16 +44,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:deep(.btn-login) {
|
|
||||||
&:disabled {
|
//:deep(.btn-login) {
|
||||||
background-color: #c5b7ff !important;
|
// //&:disabled {
|
||||||
}
|
// // background-color: #c5b7ff !important;
|
||||||
&:not(:disabled) {
|
// //}
|
||||||
&:hover {
|
// //&:not(:disabled) {
|
||||||
background-color: $color-primary-3 !important;
|
// // &:hover {
|
||||||
}
|
// // background-color: $color-primary-3 !important;
|
||||||
}
|
// // }
|
||||||
}
|
// //}
|
||||||
|
//}
|
||||||
.login-bg {
|
.login-bg {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|||||||
@ -23,23 +23,23 @@
|
|||||||
</Input>
|
</Input>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-row-item">
|
<!-- <div class="filter-row-item">-->
|
||||||
<span class="label">序号</span>
|
<!-- <span class="label">序号</span>-->
|
||||||
<Space size="medium">
|
<!-- <Space size="medium">-->
|
||||||
<Input
|
<!-- <Input-->
|
||||||
v-model:value="query.uid"
|
<!-- v-model:value="query.uid"-->
|
||||||
class="!w-160px"
|
<!-- class="!w-160px"-->
|
||||||
placeholder="请输入序号"
|
<!-- placeholder="请输入序号"-->
|
||||||
size="medium"
|
<!-- size="medium"-->
|
||||||
allowClear
|
<!-- allowClear-->
|
||||||
@change="handleSearch"
|
<!-- @change="handleSearch"-->
|
||||||
>
|
<!-- >-->
|
||||||
<template #prefix>
|
<!-- <template #prefix>-->
|
||||||
<icon-search />
|
<!-- <icon-search />-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</Input>
|
<!-- </Input>-->
|
||||||
</Space>
|
<!-- </Space>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="filter-row-item" v-if="query.audit_status === AuditStatus.Pending">
|
<div class="filter-row-item" v-if="query.audit_status === AuditStatus.Pending">
|
||||||
<span class="label">上传时间</span>
|
<span class="label">上传时间</span>
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
@ -83,7 +83,7 @@
|
|||||||
<div class="filter-row-item">
|
<div class="filter-row-item">
|
||||||
<Button type="primary" ghost class="mr-12px" size="medium" @click="handleSearch">
|
<Button type="primary" ghost class="mr-12px" size="medium" @click="handleSearch">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-search class="mr-8px"/>
|
<icon-search class="mr-8px" />
|
||||||
</template>
|
</template>
|
||||||
<template #default>搜索</template>
|
<template #default>搜索</template>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -60,6 +60,9 @@
|
|||||||
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
||||||
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'origin'" #customRender="{ record }">
|
||||||
|
{{ ORIGIN_LIST.find((item) => item.value === record.origin)?.label ?? '-' }}
|
||||||
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img :src="record.type === EnumManuscriptType.Image ? icon2 : icon3" width="16" height="16" class="mr-4px" />
|
<img :src="record.type === EnumManuscriptType.Image ? icon2 : icon3" width="16" height="16" class="mr-4px" />
|
||||||
@ -113,6 +116,7 @@ import { ref } from 'vue';
|
|||||||
import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
import { EnumManuscriptType } from '@/views/material-center/components/finished-products/manuscript/list/constants';
|
import { EnumManuscriptType } from '@/views/material-center/components/finished-products/manuscript/list/constants';
|
||||||
import { patchWorkAuditsAudit } from '@/api/all/generationWorkshop';
|
import { patchWorkAuditsAudit } from '@/api/all/generationWorkshop';
|
||||||
import {
|
import {
|
||||||
@ -123,8 +127,8 @@ import { AuditStatus } from '@/views/material-center/components/finished-product
|
|||||||
|
|
||||||
import { slsWithCatch } from '@/utils/stroage.ts';
|
import { slsWithCatch } from '@/utils/stroage.ts';
|
||||||
|
|
||||||
import TextOverTips from '@/components/text-over-tips'
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
import ImgLazyLoad from "@/components/img-lazy-load";
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
import ShareModal from '@/views/material-center/components/finished-products/manuscript/components/share-manuscript-modal/share-modal.vue';
|
import ShareModal from '@/views/material-center/components/finished-products/manuscript/components/share-manuscript-modal/share-modal.vue';
|
||||||
import HoverImagePreview from '@/components/hover-image-preview';
|
import HoverImagePreview from '@/components/hover-image-preview';
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,11 @@ export const TABLE_COLUMNS1 = [
|
|||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
width: 300,
|
width: 300,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'origin',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '客户意见',
|
title: '客户意见',
|
||||||
dataIndex: 'customer_opinion',
|
dataIndex: 'customer_opinion',
|
||||||
|
|||||||
@ -309,7 +309,7 @@ export default {
|
|||||||
placeholder="请输入标题"
|
placeholder="请输入标题"
|
||||||
size="large"
|
size="large"
|
||||||
class="!w-500px"
|
class="!w-500px"
|
||||||
maxlength={30}
|
maxlength={20}
|
||||||
showCount
|
showCount
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -25,20 +25,20 @@
|
|||||||
@change="handleSearch"
|
@change="handleSearch"
|
||||||
/>
|
/>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="filter-row-item">
|
<!-- <div class="filter-row-item">-->
|
||||||
<span class="label">序号</span>
|
<!-- <span class="label">序号</span>-->
|
||||||
<Input
|
<!-- <Input-->
|
||||||
v-model:value="query.uid"
|
<!-- v-model:value="query.uid"-->
|
||||||
class="!w-160px"
|
<!-- class="!w-160px"-->
|
||||||
placeholder="请输入序号"
|
<!-- placeholder="请输入序号"-->
|
||||||
allowClear
|
<!-- allowClear-->
|
||||||
@change="handleSearch"
|
<!-- @change="handleSearch"-->
|
||||||
>
|
<!-- >-->
|
||||||
<template #prefix>
|
<!-- <template #prefix>-->
|
||||||
<icon-search />
|
<!-- <icon-search />-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</Input>
|
<!-- </Input>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="filter-row-item">
|
<div class="filter-row-item">
|
||||||
<span class="label">审核状态</span>
|
<span class="label">审核状态</span>
|
||||||
<CommonSelect
|
<CommonSelect
|
||||||
|
|||||||
@ -38,6 +38,11 @@ export const TABLE_COLUMNS = [
|
|||||||
dataIndex: 'audit_status',
|
dataIndex: 'audit_status',
|
||||||
width: 120,
|
width: 120,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'origin',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '上传时间',
|
title: '上传时间',
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
|
|||||||
@ -47,6 +47,9 @@
|
|||||||
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
||||||
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'origin'" #customRender="{ record }">
|
||||||
|
{{ ORIGIN_LIST.find((item) => item.value === record.origin)?.label ?? '-' }}
|
||||||
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'audit_status'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'audit_status'" #customRender="{ record }">
|
||||||
<div
|
<div
|
||||||
class="flex items-center w-fit h-28px px-8px rounded-2px"
|
class="flex items-center w-fit h-28px px-8px rounded-2px"
|
||||||
@ -96,6 +99,7 @@ import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
|||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||||
import { TABLE_COLUMNS } from './constants';
|
import { TABLE_COLUMNS } from './constants';
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
import {
|
import {
|
||||||
CHECK_STATUS,
|
CHECK_STATUS,
|
||||||
EnumManuscriptType,
|
EnumManuscriptType,
|
||||||
@ -104,7 +108,7 @@ import { CUSTOMER_OPINION } from '@/views/material-center/components/finished-pr
|
|||||||
|
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
import HoverImagePreview from '@/components/hover-image-preview';
|
import HoverImagePreview from '@/components/hover-image-preview';
|
||||||
import ImgLazyLoad from "@/components/img-lazy-load";
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
|
|
||||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||||
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
export const INITIAL_QUERY = {
|
export const INITIAL_QUERY = {
|
||||||
title: '',
|
title: '',
|
||||||
// project_ids: [],
|
// project_ids: [],
|
||||||
uid: '',
|
// uid: '',
|
||||||
audit_status: undefined,
|
audit_status: undefined,
|
||||||
created_at: [],
|
created_at: [],
|
||||||
sort_column: undefined,
|
sort_column: undefined,
|
||||||
|
|||||||
@ -0,0 +1,537 @@
|
|||||||
|
<script lang="tsx">
|
||||||
|
import { Drawer, Button, Upload, Table, Input, Progress, message, Select, Modal, Tag, Tooltip } from 'ant-design-vue';
|
||||||
|
|
||||||
|
const { Column } = Table;
|
||||||
|
const { TextArea } = Input;
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
// import CommonSelect from '@/components/common-select';
|
||||||
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
|
// import TextOverTips from '@/components/text-over-tips';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import { formatFileSize, getVideoInfo, getFileExtension } from '@/utils/tools';
|
||||||
|
import { getRawMaterialTagsList, postBatchRawMaterial, posRawMaterialTags } from '@/api/all/generationWorkshop';
|
||||||
|
import { getFilePreSignedUrl } from '@/api/all/common';
|
||||||
|
import {
|
||||||
|
imageExtensions,
|
||||||
|
videoExtensions,
|
||||||
|
documentExtensions,
|
||||||
|
} from '@/views/material-center/components/raw-material/constants';
|
||||||
|
|
||||||
|
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||||
|
import icon2 from '../../img/icon-no-text.png';
|
||||||
|
|
||||||
|
enum EnumUploadStatus {
|
||||||
|
done = 'done',
|
||||||
|
error = 'error',
|
||||||
|
uploading = 'uploading',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
emits: ['update'],
|
||||||
|
setup(_, { emit, expose }) {
|
||||||
|
const visible = ref(false);
|
||||||
|
const submitLoading = ref(false);
|
||||||
|
const uploadData = ref([]);
|
||||||
|
const tagData = ref([]);
|
||||||
|
const modalRef = ref(null);
|
||||||
|
const isDragOver = ref(false);
|
||||||
|
|
||||||
|
const uploadSuccessNum = computed(() => {
|
||||||
|
return uploadData.value.filter((item) => item.uploadStatus === EnumUploadStatus.done).length;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加拖拽事件处理函数
|
||||||
|
const handleDragEnter = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isDragOver.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragOver = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isDragOver.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragLeave = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isDragOver.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrop = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isDragOver.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTagData = async () => {
|
||||||
|
const { code, data } = await getRawMaterialTagsList();
|
||||||
|
if (code === 200) {
|
||||||
|
tagData.value = data ?? [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTagChange = (value, option, record) => {
|
||||||
|
if (value.length < 6) {
|
||||||
|
record.tag_ids = value;
|
||||||
|
} else {
|
||||||
|
message.warning('最多选择5个');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加处理标签输入的函数
|
||||||
|
const handleTagInputPressEnter = async (e, record) => {
|
||||||
|
const inputValue = e.target.value.trim();
|
||||||
|
|
||||||
|
if (!inputValue) return;
|
||||||
|
const _target = tagData.value.find((item) => item.name === inputValue);
|
||||||
|
if (_target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record.tag_ids.length >= 5) {
|
||||||
|
message.warning('最多选择5个');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { code, data } = await posRawMaterialTags({ name: inputValue });
|
||||||
|
|
||||||
|
if (code === 200 && data) {
|
||||||
|
tagData.value.push({
|
||||||
|
id: data.id,
|
||||||
|
name: data.name,
|
||||||
|
});
|
||||||
|
e.target.value = '';
|
||||||
|
|
||||||
|
record.tag_ids = [...record.tag_ids, data.id];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error('添加标签失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
if (!uploadData.value.length) {
|
||||||
|
onClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modalRef.value = Modal.warning({
|
||||||
|
title: '确定要取消上传吗?',
|
||||||
|
content: '取消后上传将中断,已传输的内容不会保存',
|
||||||
|
cancelText: '取消',
|
||||||
|
okText: '确定',
|
||||||
|
centered: true,
|
||||||
|
footer: (
|
||||||
|
<div class="flex items-center justify-end mt-24px">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
modalRef.value.destroy();
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
class="mr-12px"
|
||||||
|
>
|
||||||
|
确认取消
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
modalRef.value.destroy();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
继续上传
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
getTagData();
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
visible.value = false;
|
||||||
|
|
||||||
|
uploadData.value = [];
|
||||||
|
tagData.value = [];
|
||||||
|
modalRef.value?.destroy();
|
||||||
|
modalRef.value = null;
|
||||||
|
submitLoading.value = false;
|
||||||
|
isDragOver.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpload = async (option) => {
|
||||||
|
const { file } = option;
|
||||||
|
const { name, size, type, uid } = file;
|
||||||
|
|
||||||
|
let statusText = '';
|
||||||
|
const ext = name.slice(name.lastIndexOf('.')).toLowerCase();
|
||||||
|
const isImage = imageExtensions.includes(ext);
|
||||||
|
const isVideo = videoExtensions.includes(ext);
|
||||||
|
const isDocument = documentExtensions.includes(ext);
|
||||||
|
|
||||||
|
if (!isImage && !isVideo && !isDocument) {
|
||||||
|
statusText = '当前格式不支持';
|
||||||
|
} else if (
|
||||||
|
(isImage && size > 20 * 1024 * 1024) || // 图片大于20MB
|
||||||
|
(isVideo && size > 1000 * 1024 * 1024) || // 视频大于1000MB
|
||||||
|
(isDocument && size > 20 * 1024 * 1024) // 文档大于20MB
|
||||||
|
) {
|
||||||
|
statusText = '文件大小超出限制';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { fileTypeLabel, cover, fileType } = await getFileInfo(file);
|
||||||
|
|
||||||
|
const currentData = {
|
||||||
|
uid,
|
||||||
|
name,
|
||||||
|
// type,
|
||||||
|
type: fileType,
|
||||||
|
uploadStatus: statusText ? EnumUploadStatus.error : EnumUploadStatus.uploading,
|
||||||
|
statusText,
|
||||||
|
percent: 0,
|
||||||
|
size,
|
||||||
|
fileTypeLabel,
|
||||||
|
tag_ids: [],
|
||||||
|
cover,
|
||||||
|
file: '',
|
||||||
|
};
|
||||||
|
uploadData.value.push(currentData);
|
||||||
|
|
||||||
|
if (statusText) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await getFilePreSignedUrl({ suffix: getFileExtension(name) });
|
||||||
|
const { upload_url, file_url } = response?.data;
|
||||||
|
const _target = uploadData.value.find((item) => item.uid === uid);
|
||||||
|
_target.file = file_url;
|
||||||
|
if (!upload_url) {
|
||||||
|
throw new Error('未能获取有效的预签名上传地址');
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob([file], { type });
|
||||||
|
await axios.put(upload_url, blob, {
|
||||||
|
headers: { 'Content-Type': type },
|
||||||
|
onUploadProgress: (progressEvent) => {
|
||||||
|
const percentCompleted = Math.round(progressEvent.progress * 100);
|
||||||
|
|
||||||
|
_target.percent = percentCompleted;
|
||||||
|
percentCompleted === 100 && (_target.uploadStatus = EnumUploadStatus.done);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
currentData.uploadStatus = EnumUploadStatus.error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFileInfo = async (file: any) => {
|
||||||
|
const { name } = file;
|
||||||
|
const ext = name.slice(name.lastIndexOf('.')).toLowerCase();
|
||||||
|
|
||||||
|
if (imageExtensions.includes(ext)) {
|
||||||
|
return {
|
||||||
|
fileTypeLabel: '图片',
|
||||||
|
fileType: 0,
|
||||||
|
cover: URL.createObjectURL(file),
|
||||||
|
};
|
||||||
|
} else if (videoExtensions.includes(ext)) {
|
||||||
|
const { firstFrame } = await getVideoInfo(file);
|
||||||
|
return {
|
||||||
|
fileTypeLabel: '视频',
|
||||||
|
fileType: 1,
|
||||||
|
cover: firstFrame,
|
||||||
|
};
|
||||||
|
} else if (documentExtensions.includes(ext)) {
|
||||||
|
return {
|
||||||
|
fileTypeLabel: '文本',
|
||||||
|
fileType: 2,
|
||||||
|
cover: icon2,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
fileType: '',
|
||||||
|
fileTypeLabel: '其他',
|
||||||
|
cover: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onConfirm = async () => {
|
||||||
|
const hasUploading = uploadData.value.some((item) => item.uploadStatus === EnumUploadStatus.uploading);
|
||||||
|
if (hasUploading) {
|
||||||
|
modalRef.value = Modal.warning({
|
||||||
|
title: '上传未完成',
|
||||||
|
content: <p class="h-22px">当前原料正在上传中,关闭弹窗将导致上传失败,请等待上传完成后再点击“确定”</p>,
|
||||||
|
okText: '我知道了',
|
||||||
|
centered: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw_materials = uploadData.value.filter((item) => item.uploadStatus !== EnumUploadStatus.error);
|
||||||
|
const { code } = await postBatchRawMaterial({ raw_materials });
|
||||||
|
if (code === 200) {
|
||||||
|
message.success('上传成功');
|
||||||
|
emit('update');
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const openDeleteModal = (file) => {
|
||||||
|
modalRef.value = Modal.warning({
|
||||||
|
title: '确定删除该文件吗?',
|
||||||
|
content: <p class="h-22px"></p>,
|
||||||
|
cancelText: '取消',
|
||||||
|
okText: '确定',
|
||||||
|
centered: true,
|
||||||
|
footer: (
|
||||||
|
<div class="flex items-center justify-end mt-24px">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
modalRef.value.destroy();
|
||||||
|
}}
|
||||||
|
class="mr-12px"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
uploadData.value = uploadData.value.filter((item) => item.uid !== file.uid);
|
||||||
|
modalRef.value.destroy();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderUploadStatus = (record) => {
|
||||||
|
if (record.uploadStatus === EnumUploadStatus.error) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p class="upload-text">上传失败</p>
|
||||||
|
<p class="upload-text !color-#F64B31">{record.statusText}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<span class="upload-text ml-26px">
|
||||||
|
{record.uploadStatus === EnumUploadStatus.done ? '上传成功' : '上传中'}
|
||||||
|
</span>
|
||||||
|
<Progress percent={record.percent} class="m-0 p-0 " />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderUploadList = () => {
|
||||||
|
if (!uploadData.value.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p class="cts !color-#939499 mb-10px">
|
||||||
|
已上传:<span class="!color-#211F24">{`${uploadSuccessNum.value}/${uploadData.value.length}`}</span>
|
||||||
|
</p>
|
||||||
|
<Table
|
||||||
|
ref="tableRef"
|
||||||
|
dataSource={uploadData.value}
|
||||||
|
pagination={false}
|
||||||
|
class="w-100% flex-1"
|
||||||
|
scroll={{ y: '100%' }}
|
||||||
|
>
|
||||||
|
<Column
|
||||||
|
title="文件名称"
|
||||||
|
dataIndex="name"
|
||||||
|
key="name"
|
||||||
|
width={380}
|
||||||
|
ellipsis={true}
|
||||||
|
customRender={({ text, record }) => {
|
||||||
|
return (
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<ImgLazyLoad width={64} height={64} src={record.cover} class="!rounded-6px mr-16px flex-shrink-0" />
|
||||||
|
|
||||||
|
<TextArea
|
||||||
|
v-model:value={record.name}
|
||||||
|
placeholder="请输入文件名称"
|
||||||
|
size="large"
|
||||||
|
class="w-full !h-72px"
|
||||||
|
showCount
|
||||||
|
maxlength={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Column
|
||||||
|
title="上传状态"
|
||||||
|
dataIndex="uploadStatus"
|
||||||
|
key="uploadStatus"
|
||||||
|
width={164}
|
||||||
|
customRender={({ text, record }) => renderUploadStatus(record)}
|
||||||
|
/>
|
||||||
|
<Column
|
||||||
|
title="标签"
|
||||||
|
dataIndex="tag_ids"
|
||||||
|
key="tag_ids"
|
||||||
|
width={243}
|
||||||
|
customRender={({ text, record }) => {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
disabled={record.uploadStatus === EnumUploadStatus.uploading}
|
||||||
|
value={record.tag_ids}
|
||||||
|
mode="multiple"
|
||||||
|
size="middle"
|
||||||
|
placeholder="请选择标签"
|
||||||
|
allowClear
|
||||||
|
autoClearSearchValue
|
||||||
|
class="w-full"
|
||||||
|
showSearch
|
||||||
|
showArrow
|
||||||
|
maxTagCount={5}
|
||||||
|
options={tagData.value}
|
||||||
|
optionFilterProp="name"
|
||||||
|
field-names={{ label: 'name', value: 'id' }}
|
||||||
|
onChange={(value, option) => handleTagChange(value, option, record)}
|
||||||
|
onInputKeyDown={(e) => {
|
||||||
|
// 检测回车键
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleTagInputPressEnter(e, record);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
v-slots={{
|
||||||
|
tagRender: (val) => {
|
||||||
|
const { label, value } = val;
|
||||||
|
if (label.length > 5) {
|
||||||
|
return (
|
||||||
|
<div class="my-2px">
|
||||||
|
<Tooltip title={label}>
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={() => (record.tag_ids = record.tag_ids.filter((item) => item !== value))}
|
||||||
|
class="mr-0 !color-#55585F h-20px !lh-20px !text-12px"
|
||||||
|
>
|
||||||
|
{label.slice(0, 5) + '...'}
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div class="my-2px">
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={() => (record.tag_ids = record.tag_ids.filter((item) => item !== value))}
|
||||||
|
class="mr-0 !color-#55585F h-20px !lh-20px !text-12px"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Column title="类型" dataIndex="fileTypeLabel" key="fileTypeLabel" width={80} />
|
||||||
|
<Column
|
||||||
|
title="大小"
|
||||||
|
dataIndex="size"
|
||||||
|
key="size"
|
||||||
|
width={100}
|
||||||
|
customRender={({ record }) => {
|
||||||
|
return formatFileSize(record.size);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Column
|
||||||
|
title="操作"
|
||||||
|
key="action"
|
||||||
|
width={80}
|
||||||
|
fixed="right"
|
||||||
|
align="right"
|
||||||
|
customRender={({ text, record }) => {
|
||||||
|
return (
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
class="cursor-pointer"
|
||||||
|
src={icon1}
|
||||||
|
width="14"
|
||||||
|
height="14"
|
||||||
|
onClick={() => openDeleteModal(record)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Table>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
expose({
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
return () => (
|
||||||
|
<Drawer
|
||||||
|
width={1100}
|
||||||
|
title="上传到原料库"
|
||||||
|
rootClassName="xt-add-raw-material-modal"
|
||||||
|
v-model:open={visible.value}
|
||||||
|
onClose={onClose}
|
||||||
|
maskClosable={false}
|
||||||
|
>
|
||||||
|
<section class="content flex-1 pt-8px px-24px pb-24px overflow-hidden flex flex-col">
|
||||||
|
<div class="rounded-16px bg-#F7F8FA p-16px flex flex-col items-center mb-24px">
|
||||||
|
<Upload
|
||||||
|
file-list={uploadData.value}
|
||||||
|
action="/"
|
||||||
|
multiple
|
||||||
|
customRequest={handleUpload}
|
||||||
|
class="w-full mb-16px"
|
||||||
|
showUploadList={false}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class={`upload-box rounded-8px cursor-pointer h-100px w-full border border-dashed border-#D7D7D9 flex flex-col items-center justify-center w-full ${
|
||||||
|
isDragOver.value ? 'bg-#F0EDFF' : 'bg-#F7F8FA'
|
||||||
|
}`}
|
||||||
|
onDragenter={handleDragEnter}
|
||||||
|
onDragover={handleDragOver}
|
||||||
|
onDragleave={handleDragLeave}
|
||||||
|
onDrop={handleDrop}
|
||||||
|
>
|
||||||
|
<icon-plus size="14" class="mb-10px color-#55585F" />
|
||||||
|
<span class="cts">点击或拖拽文件到此处上传</span>
|
||||||
|
</div>
|
||||||
|
</Upload>
|
||||||
|
<p class="mb-4px cts !color-#939499 !text-12px !lh-20px">{`视频格式:视频格式:MP4、AVI、MOV,大小<1000MB`}</p>
|
||||||
|
<p class="mb-4px cts !color-#939499 !text-12px !lh-20px">{`图片格式:PNG、JPG、JPEG、GIF、WEBP、BMP,大小<20MB`}</p>
|
||||||
|
<p class="cts !color-#939499 !text-12px !lh-20px">{`文本格式:TXT、DOC、DOCX、PDF,大小<20MB`}</p>
|
||||||
|
</div>
|
||||||
|
{renderUploadList()}
|
||||||
|
</section>
|
||||||
|
<footer class="footer h-68px px-24px flex items-center justify-end">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Button size="large" onClick={onCancel} class="mr-12px">
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button size="large" type="primary" onClick={onConfirm} loading={submitLoading.value}>
|
||||||
|
确定
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
.xt-add-raw-material-modal {
|
||||||
|
.ant-drawer-header {
|
||||||
|
height: 58px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-upload {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select {
|
||||||
|
//.ant-select-selection-overflow-item {
|
||||||
|
// max-width: 50%;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-drawer-body {
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.cts {
|
||||||
|
color: #211f24;
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
.upload-box {
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #6d4cfe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-text {
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-progress {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.ant-progress-outer {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 6px !important;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.ant-progress-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 100px;
|
||||||
|
height: 6px !important;
|
||||||
|
background: var(--BG-200, #F2F3F5);
|
||||||
|
|
||||||
|
.ant-progress-bg {
|
||||||
|
height: 6px !important;
|
||||||
|
background-color: #6D4CFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ant-progress-text {
|
||||||
|
color: var(--Text-1, #211F24);
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ant-progress-status-success {
|
||||||
|
.ant-progress-outer {
|
||||||
|
.ant-progress-bg {
|
||||||
|
background-color: #25C883;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-progress-text {
|
||||||
|
color: #25C883;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,291 @@
|
|||||||
|
<script lang="tsx">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Button, Modal, Form, FormItem, Input, message, Select, Tag, Tooltip } from 'ant-design-vue';
|
||||||
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
|
|
||||||
|
const { TextArea } = Input;
|
||||||
|
|
||||||
|
import { formatFileSize, exactFormatTime } from '@/utils/tools';
|
||||||
|
import {
|
||||||
|
getRawMaterialDetail,
|
||||||
|
putRawMaterial,
|
||||||
|
getRawMaterialTagsList,
|
||||||
|
posRawMaterialTags,
|
||||||
|
} from '@/api/all/generationWorkshop';
|
||||||
|
import { TABS_LIST, ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
|
|
||||||
|
const INITIAL_FORM = {
|
||||||
|
name: '',
|
||||||
|
tag_ids: [],
|
||||||
|
uid: '',
|
||||||
|
type: '',
|
||||||
|
origin: '',
|
||||||
|
size: '',
|
||||||
|
created_at: '',
|
||||||
|
uploader: {
|
||||||
|
name: '',
|
||||||
|
mobile: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup(props, { emit, expose }) {
|
||||||
|
const formRef = ref();
|
||||||
|
const id = ref('');
|
||||||
|
const visible = ref(false);
|
||||||
|
const submitLoading = ref(false);
|
||||||
|
const form = ref(cloneDeep(INITIAL_FORM));
|
||||||
|
const tagOptions = ref([]);
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
mobile: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (_rule, value) => {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject('请填写手机号');
|
||||||
|
}
|
||||||
|
if (!/^1[3-9]\d{9}$/.test(value)) {
|
||||||
|
return Promise.reject('手机号格式不正确');
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
operator_name: [{ required: true, message: '请输入运营人员' }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMaterialDetail = async () => {
|
||||||
|
const { code, data } = await getRawMaterialDetail(id.value);
|
||||||
|
if (code === 200) {
|
||||||
|
form.value = data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getTags = async () => {
|
||||||
|
const { code, data } = await getRawMaterialTagsList();
|
||||||
|
if (code === 200) {
|
||||||
|
tagOptions.value = data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
form.value = cloneDeep(INITIAL_FORM);
|
||||||
|
tagOptions.value = [];
|
||||||
|
submitLoading.value = false;
|
||||||
|
id.value = '';
|
||||||
|
};
|
||||||
|
const open = (materialId = '') => {
|
||||||
|
id.value = materialId;
|
||||||
|
getMaterialDetail();
|
||||||
|
getTags();
|
||||||
|
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
const onClose = () => {
|
||||||
|
reset();
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
formRef.value.validate().then(async () => {
|
||||||
|
try {
|
||||||
|
submitLoading.value = true;
|
||||||
|
const { code } = await putRawMaterial({ id: id.value, ...form.value });
|
||||||
|
if (code === 200) {
|
||||||
|
message.success('修改成功');
|
||||||
|
emit('update');
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
submitLoading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTagChange = (value) => {
|
||||||
|
if (value.length < 6) {
|
||||||
|
form.value.tag_ids = value;
|
||||||
|
} else {
|
||||||
|
message.warning('最多选择5个');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTag = (tagId) => {
|
||||||
|
form.value.tag_ids = form.value.tag_ids.filter((item) => item !== tagId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加处理标签输入的函数
|
||||||
|
const handleTagInputPressEnter = async (e) => {
|
||||||
|
const inputValue = e.target.value.trim();
|
||||||
|
|
||||||
|
if (!inputValue) return;
|
||||||
|
const _target = tagOptions.value.find((item) => item.name === inputValue);
|
||||||
|
if (_target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form.value.tag_ids.length >= 5) {
|
||||||
|
message.warning('最多选择5个');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { code, data } = await posRawMaterialTags({ name: inputValue });
|
||||||
|
|
||||||
|
if (code === 200 && data) {
|
||||||
|
tagOptions.value.push({
|
||||||
|
id: data.id,
|
||||||
|
name: data.name,
|
||||||
|
});
|
||||||
|
e.target.value = '';
|
||||||
|
|
||||||
|
form.value.tag_ids = [...form.value.tag_ids, data.id];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error('添加标签失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expose({ open });
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<Modal
|
||||||
|
v-model:open={visible.value}
|
||||||
|
title="编辑素材"
|
||||||
|
wrapClassName="edit-material-modal"
|
||||||
|
width="480px"
|
||||||
|
centered
|
||||||
|
maskClosable={false}
|
||||||
|
onCancel={onClose}
|
||||||
|
v-slots={{
|
||||||
|
footer: () => (
|
||||||
|
<div class="flex">
|
||||||
|
<Button onClick={onClose}>取消</Button>
|
||||||
|
<Button type="primary" loading={submitLoading.value} onClick={onSubmit}>
|
||||||
|
确定
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
ref={formRef}
|
||||||
|
model={form.value}
|
||||||
|
rules={rules}
|
||||||
|
layout="horizontal"
|
||||||
|
labelAlign="right"
|
||||||
|
labelCol={{ span: 4 }}
|
||||||
|
wrapperCol={{ span: 20 }}
|
||||||
|
>
|
||||||
|
<FormItem label="文件名称" name="name">
|
||||||
|
<TextArea
|
||||||
|
v-model:value={form.value.name}
|
||||||
|
placeholder="请输入..."
|
||||||
|
size="large"
|
||||||
|
class="!h-72px"
|
||||||
|
showCount
|
||||||
|
maxlength={20}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="序号" name="uid">
|
||||||
|
<Input v-model:value={form.value.uid} placeholder="请输入..." size="large" disabled />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="类型" name="type">
|
||||||
|
<Input
|
||||||
|
value={TABS_LIST.find((item) => item.value === form.value.type)?.label ?? '-'}
|
||||||
|
placeholder="请输入..."
|
||||||
|
size="large"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="标签" name="tag_ids" v-model:value={form.value.tag_ids}>
|
||||||
|
<Select
|
||||||
|
value={form.value.tag_ids}
|
||||||
|
mode="multiple"
|
||||||
|
size="large"
|
||||||
|
placeholder="请选择标签"
|
||||||
|
allowClear
|
||||||
|
autoClearSearchValue
|
||||||
|
class="w-full"
|
||||||
|
showSearch
|
||||||
|
showArrow
|
||||||
|
maxTagCount={5}
|
||||||
|
optionFilterProp="name"
|
||||||
|
options={tagOptions.value}
|
||||||
|
field-names={{ label: 'name', value: 'id' }}
|
||||||
|
onChange={handleTagChange}
|
||||||
|
onInputKeyDown={(e) => {
|
||||||
|
// 检测回车键
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleTagInputPressEnter(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
v-slots={{
|
||||||
|
tagRender: (val) => {
|
||||||
|
const { label, value } = val;
|
||||||
|
if (label.length > 5) {
|
||||||
|
return (
|
||||||
|
<div class="my-2px">
|
||||||
|
<Tooltip title={label}>
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={() => (form.value.tag_ids = form.value.tag_ids.filter((item) => item !== value))}
|
||||||
|
class="mr-0"
|
||||||
|
>
|
||||||
|
{`${label.slice(0, 5)}...`}
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div class="my-2px">
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={() => (form.value.tag_ids = form.value.tag_ids.filter((item) => item !== value))}
|
||||||
|
class=" mr-0 "
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="来源" name="origin">
|
||||||
|
<Input
|
||||||
|
value={ORIGIN_LIST.find((item) => item.value === form.value.origin)?.label ?? '-'}
|
||||||
|
placeholder="请输入..."
|
||||||
|
size="large"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</FormItem>{' '}
|
||||||
|
<FormItem label="大小" name="size">
|
||||||
|
<Input value={formatFileSize(form.value.size)} placeholder="请输入..." size="large" disabled />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="上传时间" name="created_at">
|
||||||
|
<Input value={exactFormatTime(form.value.created_at)} placeholder="请输入..." size="large" disabled />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="上传人员" name="uploader">
|
||||||
|
<Input
|
||||||
|
value={form.value.uploader.name || form.value.uploader.mobile}
|
||||||
|
placeholder="请输入..."
|
||||||
|
size="large"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
@ -16,13 +16,30 @@
|
|||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-row-item">
|
<div class="filter-row-item">
|
||||||
<span class="label">序号</span>
|
<span class="label">标签</span>
|
||||||
<Input v-model:value="query.uid" class="!w-160px" placeholder="请输入序号" allowClear @change="handleSearch">
|
<Select
|
||||||
<template #prefix>
|
v-model:value="query.tag_ids"
|
||||||
<icon-search />
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
</template>
|
:maxTagCount="1"
|
||||||
</Input>
|
:options="tagData"
|
||||||
|
allowClear
|
||||||
|
class="!w-200px"
|
||||||
|
mode="multiple"
|
||||||
|
optionFilterProp="name"
|
||||||
|
placeholder="请选择标签"
|
||||||
|
showArrow
|
||||||
|
showSearch
|
||||||
|
@change="handleSearch"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div class="filter-row-item">-->
|
||||||
|
<!-- <span class="label">序号</span>-->
|
||||||
|
<!-- <Input v-model:value="query.uid" class="!w-160px" placeholder="请输入序号" allowClear @change="handleSearch">-->
|
||||||
|
<!-- <template #prefix>-->
|
||||||
|
<!-- <icon-search />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </Input>-->
|
||||||
|
<!-- </div>-->
|
||||||
<div class="filter-row-item">
|
<div class="filter-row-item">
|
||||||
<span class="label">上传时间</span>
|
<span class="label">上传时间</span>
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
@ -54,8 +71,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineEmits, defineProps, ref, nextTick } from 'vue';
|
import { defineEmits, defineProps, ref, nextTick } from 'vue';
|
||||||
import { Button, Input, DatePicker } from 'ant-design-vue';
|
import { Button, Input, DatePicker, Select } from 'ant-design-vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { getRawMaterialTagsList } from '@/api/all/generationWorkshop';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
query: {
|
query: {
|
||||||
@ -67,6 +85,14 @@ const props = defineProps({
|
|||||||
const emits = defineEmits(['search', 'reset', 'update:query']);
|
const emits = defineEmits(['search', 'reset', 'update:query']);
|
||||||
|
|
||||||
const created_at = ref([]);
|
const created_at = ref([]);
|
||||||
|
const tagData = ref([]);
|
||||||
|
|
||||||
|
const getTagData = async () => {
|
||||||
|
const { code, data } = await getRawMaterialTagsList();
|
||||||
|
if (code === 200) {
|
||||||
|
tagData.value = data ?? [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
emits('update:query', props.query);
|
emits('update:query', props.query);
|
||||||
@ -96,4 +122,18 @@ const handleReset = () => {
|
|||||||
created_at.value = [];
|
created_at.value = [];
|
||||||
emits('reset');
|
emits('reset');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTagData();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.common-filter-wrap {
|
||||||
|
:deep(.ant-select) {
|
||||||
|
.ant-select-selection-overflow-item {
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -17,7 +17,9 @@ import { Button, Modal, message } from 'ant-design-vue';
|
|||||||
import { deleteRawMaterial, batchDeleteRawMaterials } from '@/api/all/generationWorkshop';
|
import { deleteRawMaterial, batchDeleteRawMaterials } from '@/api/all/generationWorkshop';
|
||||||
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||||
|
|
||||||
const update = inject('update');
|
// const update = inject('update');
|
||||||
|
|
||||||
|
const emits = defineEmits(['update', 'batchUpdate']);
|
||||||
|
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const fileId = ref(null);
|
const fileId = ref(null);
|
||||||
|
|||||||
@ -33,8 +33,13 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="column.dataIndex === 'name'" #customRender="{ record }">
|
<template v-if="column.dataIndex === 'name'" #customRender="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<HoverImagePreview :src="record.cover">
|
<HoverImagePreview :src="record.type === RawMaterialType.Text ? icon2 : record.cover">
|
||||||
<ImgLazyLoad :width="64" :height="64" :src="record.cover" class="!rounded-6px mr-16px" />
|
<ImgLazyLoad
|
||||||
|
:height="64"
|
||||||
|
:src="record.type === RawMaterialType.Text ? icon2 : record.cover"
|
||||||
|
:width="64"
|
||||||
|
class="!rounded-6px mr-16px"
|
||||||
|
/>
|
||||||
</HoverImagePreview>
|
</HoverImagePreview>
|
||||||
<div class="flex-1 flex flex-col overflow-hidden">
|
<div class="flex-1 flex flex-col overflow-hidden">
|
||||||
<TextOverTips :context="record.name" :line="1" class="cts mb-4px regular" />
|
<TextOverTips :context="record.name" :line="1" class="cts mb-4px regular" />
|
||||||
@ -45,6 +50,17 @@
|
|||||||
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
||||||
{{ TABS_LIST.find((item) => item.value === record.type)?.label ?? '-' }}
|
{{ TABS_LIST.find((item) => item.value === record.type)?.label ?? '-' }}
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'tags'" #customRender="{ record }">
|
||||||
|
<div v-if="record.tags.length > 0" class="flex flex-wrap gap-4px">
|
||||||
|
<Tag v-for="tag in record.tags" :key="tag.id" class="mr-0 rounded-4px bg-#F2F3F5 px-8px">
|
||||||
|
<Tooltip v-if="tag.name.length > 5" :title="tag.name">
|
||||||
|
<span class="cts !color-#55585F !lh-20px !text-12px"> {{ `${tag.name.slice(0, 5)}...` }} </span>
|
||||||
|
</Tooltip>
|
||||||
|
<span v-else class="cts !color-#55585F !lh-20px !text-12px"> {{ tag.name }} </span>
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
<template v-else> -</template>
|
||||||
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'size'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'size'" #customRender="{ record }">
|
||||||
<span class="cts num">{{ formatFileSize(record.size) }}</span>
|
<span class="cts num">{{ formatFileSize(record.size) }}</span>
|
||||||
</template>
|
</template>
|
||||||
@ -60,7 +76,10 @@
|
|||||||
<template v-else-if="column.dataIndex === 'operation'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'operation'" #customRender="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img class="mr-8px cursor-pointer" :src="icon1" width="14" height="14" @click="onDelete(record)" />
|
<img class="mr-8px cursor-pointer" :src="icon1" width="14" height="14" @click="onDelete(record)" />
|
||||||
<Button type="primary" ghost size="small" @click="onDownload(record)">下载</Button>
|
<Button class="mr-8px !h-24px !px-12px" ghost size="small" type="primary" @click="onEdit(record)"
|
||||||
|
>编辑
|
||||||
|
</Button>
|
||||||
|
<Button class="!h-24px !px-12px" ghost size="small" type="primary" @click="onDownload(record)">下载</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else #customRender="{ record }">
|
<template v-else #customRender="{ record }">
|
||||||
@ -72,11 +91,11 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
import { Button, Tooltip, Table, Tag } from 'ant-design-vue';
|
||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
import { formatTableField, exactFormatTime, formatFileSize, downloadByUrl } from '@/utils/tools';
|
import { formatTableField, exactFormatTime, formatFileSize, downloadByUrl } from '@/utils/tools';
|
||||||
import { slsWithCatch } from '@/utils/stroage.ts';
|
// import { slsWithCatch } from '@/utils/stroage.ts';
|
||||||
import { TABS_LIST, ORIGIN_LIST } from '../../constants';
|
import { TABS_LIST, ORIGIN_LIST, RawMaterialType } from '../../constants';
|
||||||
|
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
// import ShareModal from '@/views/material-center/components/finished-products/manuscript/components/share-manuscript-modal/share-modal.vue';
|
// import ShareModal from '@/views/material-center/components/finished-products/manuscript/components/share-manuscript-modal/share-modal.vue';
|
||||||
@ -84,11 +103,9 @@ import HoverImagePreview from '@/components/hover-image-preview';
|
|||||||
import ImgLazyLoad from '@/components/img-lazy-load';
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
|
|
||||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||||
// import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
import icon2 from '../../img/icon-no-text.png';
|
||||||
// import icon3 from '@/assets/img/creative-generation-workshop/icon-video.png';
|
|
||||||
// import icon4 from '@/assets/img/error-img.png';
|
|
||||||
|
|
||||||
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll']);
|
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll', 'edit']);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -129,6 +146,9 @@ const onDelete = (item) => {
|
|||||||
const onDownload = (item) => {
|
const onDownload = (item) => {
|
||||||
downloadByUrl(item.file);
|
downloadByUrl(item.file);
|
||||||
};
|
};
|
||||||
|
const onEdit = (item) => {
|
||||||
|
emits('edit', item);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="visible"
|
||||||
|
:title="isEdit ? '编辑标签' : '添加新标签'"
|
||||||
|
centered
|
||||||
|
width="400px"
|
||||||
|
@cancel="onClose"
|
||||||
|
>
|
||||||
|
<Form ref="formRef" :model="form" :rules="rules" auto-label-width layout="horizontal">
|
||||||
|
<FormItem :label="isEdit ? '标签名称' : '新标签名称'" name="name" required>
|
||||||
|
<Input v-model:value="form.name" placeholder="请输入…" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="onClose">取消</Button>
|
||||||
|
<Button class="ml-16px" type="primary" @click="onSubmit">确认</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, nextTick } from 'vue';
|
||||||
|
import { Button, Modal, Form, FormItem, Input, message } from 'ant-design-vue';
|
||||||
|
import { posRawMaterialTags, putRawMaterialTag } from '@/api/all/generationWorkshop';
|
||||||
|
|
||||||
|
const emits = defineEmits(['success', 'close']);
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const isEdit = ref(false);
|
||||||
|
const formRef = ref();
|
||||||
|
const form = ref({ name: '' });
|
||||||
|
const tagId = ref('');
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: [{ required: true, message: '请输入标签名称' }],
|
||||||
|
};
|
||||||
|
|
||||||
|
function resetForm() {
|
||||||
|
nextTick(() => {
|
||||||
|
formRef.value?.clearValidate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
visible.value = false;
|
||||||
|
form.value.name = '';
|
||||||
|
tagId.value = '';
|
||||||
|
isEdit.value = false;
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (record = {}) => {
|
||||||
|
const { id = '', name = '' } = record;
|
||||||
|
tagId.value = id;
|
||||||
|
isEdit.value = !!id;
|
||||||
|
form.value.name = name;
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function onSubmit() {
|
||||||
|
formRef.value.validate().then(async () => {
|
||||||
|
const _fn = isEdit.value ? putRawMaterialTag : posRawMaterialTags;
|
||||||
|
const _params = isEdit.value ? { id: tagId.value, ...form.value } : form.value;
|
||||||
|
const { code } = await _fn(_params);
|
||||||
|
if (code === 200) {
|
||||||
|
message.success(isEdit.value ? '编辑成功' : '添加成功');
|
||||||
|
emits('success');
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
</script>
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: RenXiaoDong
|
||||||
|
* @Date: 2025-06-26 17:23:52
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<Modal v-model:open="visible" centered title="删除标签" width="400px" @cancel="onClose">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<img :src="icon1" class="mr-12px" height="20" width="20" />
|
||||||
|
<span>确认删除 "{{ tagName }}" 这个标签吗?</span>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<Button size="large" @click="onClose">取消</Button>
|
||||||
|
<Button class="ml-16px" danger size="large" type="primary" @click="onSubmit">确认删除</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Button, message, Modal } from 'ant-design-vue';
|
||||||
|
import { deleteRawMaterialTag } from '@/api/all/generationWorkshop';
|
||||||
|
|
||||||
|
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||||
|
|
||||||
|
const emits = defineEmits(['success', 'close']);
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const tagId = ref('');
|
||||||
|
const tagName = ref('');
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
visible.value = false;
|
||||||
|
tagId.value = '';
|
||||||
|
tagName.value = '';
|
||||||
|
emits('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = (record) => {
|
||||||
|
const { id = '', name = '' } = record;
|
||||||
|
tagId.value = id;
|
||||||
|
tagName.value = name;
|
||||||
|
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
const { code } = await deleteRawMaterialTag(tagId.value);
|
||||||
|
if (code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
emits('success');
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
</script>
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: RenXiaoDong
|
||||||
|
* @Date: 2025-06-25 17:58:28
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="visible"
|
||||||
|
:footer="null"
|
||||||
|
:maskClosable="false"
|
||||||
|
centered
|
||||||
|
title="标签管理"
|
||||||
|
width="800px"
|
||||||
|
wrapClassName="raw-material-tags-manage-modal"
|
||||||
|
@cancel="close"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between mb-16px">
|
||||||
|
<div class="filter-row-item flex items-center">
|
||||||
|
<span class="s1 !color-#211F24 mr-12px">标签名称</span>
|
||||||
|
<Input
|
||||||
|
v-model:value="query.name"
|
||||||
|
allowClear
|
||||||
|
class="w-240px"
|
||||||
|
placeholder="请输入..."
|
||||||
|
size="medium"
|
||||||
|
@change="handleSearch"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<icon-search />
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" @click="openAdd">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus class="mr-8px" size="16" />
|
||||||
|
</template>
|
||||||
|
<template #default>添加新标签</template>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="h-300px">
|
||||||
|
<div v-if="showDataSource.length" class="tag-list">
|
||||||
|
<Tooltip v-for="tag in showDataSource" :key="tag.id" placement="bottom" title="双击修改标签名">
|
||||||
|
<div class="tag-item cursor-pointer" @dblclick="openEdit(tag)">
|
||||||
|
<span>{{ tag.name }}</span>
|
||||||
|
<img :src="iconDelete" class="delete-icon" @click="openDelete(tag)" />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<NoData>
|
||||||
|
<span class="s1 mb-32px mt-8px">暂无标签</span>
|
||||||
|
<Button size="large" type="primary" @click="openAdd">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus class="mr-8px" size="16" />
|
||||||
|
</template>
|
||||||
|
<template #default>去添加</template>
|
||||||
|
</Button>
|
||||||
|
</NoData>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AddTag ref="addTagRef" @success="update" />
|
||||||
|
<DeleteTag ref="deleteTagRef" @success="update" />
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Button, Modal, Input, Tooltip } from 'ant-design-vue';
|
||||||
|
import { getRawMaterialTagsList } from '@/api/all/generationWorkshop';
|
||||||
|
import AddTag from './add-tag.vue';
|
||||||
|
import DeleteTag from './delete-tag.vue';
|
||||||
|
|
||||||
|
import iconDelete from '@/assets/img/media-account/icon-delete-1.png';
|
||||||
|
|
||||||
|
const emit = defineEmits(['update']);
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const allDataSource = ref([]);
|
||||||
|
const showDataSource = ref([]);
|
||||||
|
const addTagRef = ref(null);
|
||||||
|
const deleteTagRef = ref(null);
|
||||||
|
const query = ref({
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const { code, data } = await getRawMaterialTagsList();
|
||||||
|
if (code === 200) {
|
||||||
|
allDataSource.value = data ?? [];
|
||||||
|
showDataSource.value = allDataSource.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
showDataSource.value = allDataSource.value.filter((item) => item.name.includes(query.value.name));
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
visible.value = true;
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
const close = () => {
|
||||||
|
showDataSource.value = [];
|
||||||
|
allDataSource.value = [];
|
||||||
|
query.value.name = '';
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
const openAdd = () => {
|
||||||
|
// 打开新增标签弹窗
|
||||||
|
addTagRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
function openEdit(record) {
|
||||||
|
addTagRef.value.open(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDelete(record) {
|
||||||
|
deleteTagRef.value.open(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
getData();
|
||||||
|
emit('update');
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
.raw-material-tags-manage-modal {
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.ant-modal-body {
|
||||||
|
// padding: 24px 24px 44px !important;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.arcanto-btn {
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
.ant-btn-icon {
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.tag-item {
|
||||||
|
height: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.delete-icon {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: -6px;
|
||||||
|
right: -6px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.delete-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,10 @@ export enum RawMaterialType {
|
|||||||
Text = 2,
|
Text = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'];
|
||||||
|
export const videoExtensions = ['.mp4', '.mov', '.avi', '.flv', '.wmv', '.m4v'];
|
||||||
|
export const documentExtensions = ['.txt', '.doc', '.docx', '.pdf', '.xls', '.xlsx'];
|
||||||
|
|
||||||
export const TABS_LIST = [
|
export const TABS_LIST = [
|
||||||
{
|
{
|
||||||
label: '全部',
|
label: '全部',
|
||||||
@ -37,9 +41,10 @@ export const ORIGIN_LIST = [
|
|||||||
|
|
||||||
export const INITIAL_QUERY = {
|
export const INITIAL_QUERY = {
|
||||||
name: '',
|
name: '',
|
||||||
uid: '',
|
// uid: '',
|
||||||
type: RawMaterialType.All,
|
type: RawMaterialType.All,
|
||||||
created_at: [],
|
created_at: [],
|
||||||
|
tag_ids: [],
|
||||||
sort_column: undefined,
|
sort_column: undefined,
|
||||||
sort_order: undefined,
|
sort_order: undefined,
|
||||||
};
|
};
|
||||||
@ -55,6 +60,11 @@ export const TABLE_COLUMNS = [
|
|||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '标签',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
width: 190,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '来源',
|
title: '来源',
|
||||||
dataIndex: 'origin',
|
dataIndex: 'origin',
|
||||||
@ -81,7 +91,7 @@ export const TABLE_COLUMNS = [
|
|||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
width: 100,
|
width: 180,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@ -1,14 +1,20 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { provide } from 'vue';
|
import { provide, ref } from 'vue';
|
||||||
import { Tabs, TabPane, Button, Pagination } from 'ant-design-vue';
|
|
||||||
import { TABS_LIST, RawMaterialType, INITIAL_QUERY, TABLE_COLUMNS } from './constants';
|
import { TABS_LIST, RawMaterialType, INITIAL_QUERY, TABLE_COLUMNS } from './constants';
|
||||||
|
|
||||||
|
import { Tabs, TabPane, Button, Pagination } from 'ant-design-vue';
|
||||||
import FilterBlock from './components/filter-block/index.vue';
|
import FilterBlock from './components/filter-block/index.vue';
|
||||||
import RawMaterialTable from './components/table/index.vue';
|
import RawMaterialTable from './components/table/index.vue';
|
||||||
import DeleteRawMaterialModal from './components/table/delete-file-modal.vue';
|
import DeleteRawMaterialModal from './components/table/delete-file-modal.vue';
|
||||||
|
import TagsManageModal from './components/tags-manage-modal';
|
||||||
|
import AddRawMaterialDrawer from './components/add-raw-material-drawer';
|
||||||
|
import EditRawMaterialDrawer from './components/edit-raw-material-modal';
|
||||||
|
|
||||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||||
import { getRawMaterialsPage } from '@/api/all/generationWorkshop';
|
import { getRawMaterialsPage } from '@/api/all/generationWorkshop';
|
||||||
|
|
||||||
|
import icon3 from '@/assets/img/media-account/icon-tag.png';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup(_, { attrs, slots, expose }) {
|
setup(_, { attrs, slots, expose }) {
|
||||||
const {
|
const {
|
||||||
@ -27,6 +33,10 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const deleteRawMaterialModalRef = ref(null);
|
const deleteRawMaterialModalRef = ref(null);
|
||||||
|
const tagsManageModalRef = ref(null);
|
||||||
|
const addRawMaterialDrawerRef = ref(null);
|
||||||
|
const editRawMaterialDrawerRef = ref(null);
|
||||||
|
|
||||||
const query = ref(cloneDeep(INITIAL_QUERY));
|
const query = ref(cloneDeep(INITIAL_QUERY));
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
getData();
|
getData();
|
||||||
@ -70,6 +80,10 @@ export default defineComponent({
|
|||||||
deleteRawMaterialModalRef.value?.open({ id, name: `“${name}”` });
|
deleteRawMaterialModalRef.value?.open({ id, name: `“${name}”` });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEdit = (item) => {
|
||||||
|
editRawMaterialDrawerRef.value?.open(item.id);
|
||||||
|
};
|
||||||
|
|
||||||
const handleTabClick = (key) => {
|
const handleTabClick = (key) => {
|
||||||
query.value.type = key;
|
query.value.type = key;
|
||||||
reload();
|
reload();
|
||||||
@ -81,6 +95,13 @@ export default defineComponent({
|
|||||||
getData();
|
getData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOpenTagsModal = () => {
|
||||||
|
tagsManageModalRef.value?.open();
|
||||||
|
};
|
||||||
|
const handleAddMaterial = () => {
|
||||||
|
addRawMaterialDrawerRef.value?.open();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getData();
|
getData();
|
||||||
});
|
});
|
||||||
@ -88,7 +109,37 @@ export default defineComponent({
|
|||||||
return () => (
|
return () => (
|
||||||
<div class="raw-material-wrap h-full flex flex-col">
|
<div class="raw-material-wrap h-full flex flex-col">
|
||||||
<div class="bg-white rounded-t-8px">
|
<div class="bg-white rounded-t-8px">
|
||||||
<Tabs v-model:activeKey={query.value.type} onTabClick={handleTabClick}>
|
<Tabs
|
||||||
|
v-model:activeKey={query.value.type}
|
||||||
|
onTabClick={handleTabClick}
|
||||||
|
v-slots={{
|
||||||
|
rightExtra: () => (
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
ghost
|
||||||
|
size="medium"
|
||||||
|
onClick={handleOpenTagsModal}
|
||||||
|
v-slots={{
|
||||||
|
icon: () => <img src={icon3} width="16" height="16" class="mr-8px" />,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
标签管理
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
size="medium"
|
||||||
|
class="ml-12px"
|
||||||
|
onClick={handleAddMaterial}
|
||||||
|
v-slots={{
|
||||||
|
icon: () => <icon-plus size="16" class="mr-8px" />,
|
||||||
|
default: () => '上传原料',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
{TABS_LIST.map((item) => (
|
{TABS_LIST.map((item) => (
|
||||||
<TabPane key={item.value} tab={item.label}>
|
<TabPane key={item.value} tab={item.label}>
|
||||||
{item.label}
|
{item.label}
|
||||||
@ -121,6 +172,7 @@ export default defineComponent({
|
|||||||
onDelete={handleDelete}
|
onDelete={handleDelete}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
onSelectAll={handleSelectAll}
|
onSelectAll={handleSelectAll}
|
||||||
|
onEdit={handleEdit}
|
||||||
/>
|
/>
|
||||||
{pageInfo.value.total > 0 && (
|
{pageInfo.value.total > 0 && (
|
||||||
<div class="pagination-row">
|
<div class="pagination-row">
|
||||||
@ -137,6 +189,10 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<TagsManageModal ref={tagsManageModalRef} />
|
||||||
|
<AddRawMaterialDrawer ref={addRawMaterialDrawerRef} onUpdate={getData} />
|
||||||
|
<EditRawMaterialDrawer ref={editRawMaterialDrawerRef} onUpdate={getData} />
|
||||||
<DeleteRawMaterialModal ref={deleteRawMaterialModalRef} onBatchUpdate={onBatchSuccess} onUpdate={getData} />
|
<DeleteRawMaterialModal ref={deleteRawMaterialModalRef} onBatchUpdate={onBatchSuccess} onUpdate={getData} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -15,10 +15,10 @@
|
|||||||
>
|
>
|
||||||
<div class="flex items-center justify-between mb-16px">
|
<div class="flex items-center justify-between mb-16px">
|
||||||
<div class="filter-row-item flex items-center">
|
<div class="filter-row-item flex items-center">
|
||||||
<span class="s1 !color-#211F24 mr-12px">分组名称</span>
|
<span class="s1 !color-#211F24 mr-12px">标签名称</span>
|
||||||
<Input
|
<Input
|
||||||
v-model:value="query.name"
|
v-model:value="query.name"
|
||||||
placeholder="请搜索..."
|
placeholder="请输入..."
|
||||||
class="w-240px"
|
class="w-240px"
|
||||||
size="medium"
|
size="medium"
|
||||||
allowClear
|
allowClear
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout.Header>
|
</Layout.Header>
|
||||||
<Layout class="flex trial-content items-center">
|
<Layout class="flex trial-content items-center mt-24px">
|
||||||
<div class="w-800px">
|
<div class="w-800px">
|
||||||
<!-- 未建联 -->
|
<!-- 未建联 -->
|
||||||
<section class="w-full" v-if="!primary_enterprise">
|
<section class="w-full" v-if="!primary_enterprise">
|
||||||
|
|||||||
@ -12,6 +12,10 @@
|
|||||||
:deep(.ant-steps) {
|
:deep(.ant-steps) {
|
||||||
.ant-steps-item {
|
.ant-steps-item {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
|
||||||
|
.ant-steps-item-container {
|
||||||
|
cursor: text;
|
||||||
|
|
||||||
.ant-steps-item-icon {
|
.ant-steps-item-icon {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
@ -19,7 +23,7 @@
|
|||||||
.ant-steps-item-content {
|
.ant-steps-item-content {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
.ant-steps-item-title {
|
.ant-steps-item-title {
|
||||||
color: var(--Text-1, #211f24);
|
color: var(--Text-1, #211f24) !important;
|
||||||
font-family: $font-family-regular;
|
font-family: $font-family-regular;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -27,7 +31,7 @@
|
|||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
.ant-steps-item-description {
|
.ant-steps-item-description {
|
||||||
color: var(--Text-3, #737478);
|
color: var(--Text-3, #737478) !important;
|
||||||
font-family: $font-family-regular;
|
font-family: $font-family-regular;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -35,6 +39,16 @@
|
|||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-steps-item-tail {
|
||||||
|
top: 4px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
height: 1px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.ant-steps-item-wait {
|
&.ant-steps-item-wait {
|
||||||
.ant-steps-icon {
|
.ant-steps-icon {
|
||||||
.ant-steps-icon-dot {
|
.ant-steps-icon-dot {
|
||||||
|
|||||||
@ -23,23 +23,23 @@
|
|||||||
</Input>
|
</Input>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-row-item">
|
<!-- <div class="filter-row-item">-->
|
||||||
<span class="label">序号</span>
|
<!-- <span class="label">序号</span>-->
|
||||||
<Space size="medium">
|
<!-- <Space size="medium">-->
|
||||||
<Input
|
<!-- <Input-->
|
||||||
v-model:value="query.uid"
|
<!-- v-model:value="query.uid"-->
|
||||||
class="!w-160px"
|
<!-- class="!w-160px"-->
|
||||||
placeholder="请输入序号"
|
<!-- placeholder="请输入序号"-->
|
||||||
size="middle"
|
<!-- size="middle"-->
|
||||||
allowClear
|
<!-- allowClear-->
|
||||||
@change="handleSearch"
|
<!-- @change="handleSearch"-->
|
||||||
>
|
<!-- >-->
|
||||||
<template #prefix>
|
<!-- <template #prefix>-->
|
||||||
<icon-search />
|
<!-- <icon-search />-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</Input>
|
<!-- </Input>-->
|
||||||
</Space>
|
<!-- </Space>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="filter-row-item" v-if="query.audit_status === AuditStatus.Pending">
|
<div class="filter-row-item" v-if="query.audit_status === AuditStatus.Pending">
|
||||||
<span class="label">上传时间</span>
|
<span class="label">上传时间</span>
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
|
|||||||
@ -62,6 +62,9 @@
|
|||||||
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
||||||
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'origin'" #customRender="{ record }">
|
||||||
|
{{ ORIGIN_LIST.find((item) => item.value === record.origin)?.label ?? '-' }}
|
||||||
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'type'" #customRender="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img :src="record.type === EnumManuscriptType.Image ? icon2 : icon3" width="16" height="16" class="mr-4px" />
|
<img :src="record.type === EnumManuscriptType.Image ? icon2 : icon3" width="16" height="16" class="mr-4px" />
|
||||||
@ -109,6 +112,8 @@
|
|||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
|
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||||
import { EnumManuscriptType } from '@/views/writer-material-center/components/finished-products/manuscript/list/constants';
|
import { EnumManuscriptType } from '@/views/writer-material-center/components/finished-products/manuscript/list/constants';
|
||||||
import { patchWorkAuditsAuditWriter } from '@/api/all/generationWorkshop-writer.ts';
|
import { patchWorkAuditsAuditWriter } from '@/api/all/generationWorkshop-writer.ts';
|
||||||
@ -122,11 +127,12 @@ import { slsWithCatch } from '@/utils/stroage.ts';
|
|||||||
|
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
import HoverImagePreview from '@/components/hover-image-preview';
|
import HoverImagePreview from '@/components/hover-image-preview';
|
||||||
import ImgLazyLoad from "@/components/img-lazy-load";
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
|
|
||||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||||
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
||||||
import icon3 from '@/assets/img/creative-generation-workshop/icon-video.png';
|
import icon3 from '@/assets/img/creative-generation-workshop/icon-video.png';
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
// import icon4 from '@/assets/img/error-img.png';
|
// import icon4 from '@/assets/img/error-img.png';
|
||||||
|
|
||||||
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll']);
|
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll']);
|
||||||
|
|||||||
@ -20,6 +20,11 @@ export const TABLE_COLUMNS1 = [
|
|||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
width: 300,
|
width: 300,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'origin',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// title: '客户意见',
|
// title: '客户意见',
|
||||||
// dataIndex: 'customer_opinion',
|
// dataIndex: 'customer_opinion',
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
<script src="../../../../../../material-center/components/finished-products/manuscript/check-list/constants.ts"></script>
|
||||||
<script lang="jsx">
|
<script lang="jsx">
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Button, Form, FormItem, Input, message, Upload } from 'ant-design-vue';
|
import { Button, Form, FormItem, Input, message, Upload } from 'ant-design-vue';
|
||||||
@ -309,7 +310,7 @@ export default {
|
|||||||
placeholder="请输入标题"
|
placeholder="请输入标题"
|
||||||
size="large"
|
size="large"
|
||||||
class="!w-500px"
|
class="!w-500px"
|
||||||
maxlength={30}
|
maxlength={20}
|
||||||
showCount
|
showCount
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -26,23 +26,23 @@
|
|||||||
@change="handleSearch"
|
@change="handleSearch"
|
||||||
/>
|
/>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="filter-row-item">
|
<!-- <div class="filter-row-item">-->
|
||||||
<span class="label">序号</span>
|
<!-- <span class="label">序号</span>-->
|
||||||
<Space size="medium">
|
<!-- <Space size="medium">-->
|
||||||
<Input
|
<!-- <Input-->
|
||||||
v-model:value="query.uid"
|
<!-- v-model:value="query.uid"-->
|
||||||
class="!w-160px"
|
<!-- class="!w-160px"-->
|
||||||
placeholder="请输入序号"
|
<!-- placeholder="请输入序号"-->
|
||||||
size="middle"
|
<!-- size="middle"-->
|
||||||
allowClear
|
<!-- allowClear-->
|
||||||
@change="handleSearch"
|
<!-- @change="handleSearch"-->
|
||||||
>
|
<!-- >-->
|
||||||
<template #prefix>
|
<!-- <template #prefix>-->
|
||||||
<icon-search />
|
<!-- <icon-search />-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</Input>
|
<!-- </Input>-->
|
||||||
</Space>
|
<!-- </Space>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="filter-row-item">
|
<div class="filter-row-item">
|
||||||
<span class="label">审核状态</span>
|
<span class="label">审核状态</span>
|
||||||
<CommonSelect
|
<CommonSelect
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export const TABLE_COLUMNS = [
|
|||||||
dataIndex: 'audit_status',
|
dataIndex: 'audit_status',
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'origin',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '上传时间',
|
title: '上传时间',
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
@ -63,6 +68,6 @@ export const TABLE_COLUMNS = [
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
width: 200,
|
width: 200,
|
||||||
fixed: 'right'
|
fixed: 'right',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -39,6 +39,9 @@
|
|||||||
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'title'" #customRender="{ record }">
|
||||||
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
<TextOverTips :context="record.title" :line="3" class="title" @click="onDetail(record)" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'origin'" #customRender="{ record }">
|
||||||
|
{{ ORIGIN_LIST.find((item) => item.value === record.origin)?.label ?? '-' }}
|
||||||
|
</template>
|
||||||
<template v-else-if="column.dataIndex === 'audit_status'" #customRender="{ record }">
|
<template v-else-if="column.dataIndex === 'audit_status'" #customRender="{ record }">
|
||||||
<div
|
<div
|
||||||
class="flex items-center w-fit h-28px px-8px rounded-2px"
|
class="flex items-center w-fit h-28px px-8px rounded-2px"
|
||||||
@ -88,6 +91,7 @@ import { Button, Tooltip, Table, Image } from 'ant-design-vue';
|
|||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||||
import { TABLE_COLUMNS } from './constants';
|
import { TABLE_COLUMNS } from './constants';
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
import {
|
import {
|
||||||
CHECK_STATUS,
|
CHECK_STATUS,
|
||||||
EnumManuscriptType,
|
EnumManuscriptType,
|
||||||
@ -95,11 +99,12 @@ import {
|
|||||||
|
|
||||||
import TextOverTips from '@/components/text-over-tips';
|
import TextOverTips from '@/components/text-over-tips';
|
||||||
import HoverImagePreview from '@/components/hover-image-preview';
|
import HoverImagePreview from '@/components/hover-image-preview';
|
||||||
import ImgLazyLoad from "@/components/img-lazy-load";
|
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||||
|
|
||||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||||
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
import icon2 from '@/assets/img/creative-generation-workshop/icon-photo.png';
|
||||||
import icon3 from '@/assets/img/creative-generation-workshop/icon-video.png';
|
import icon3 from '@/assets/img/creative-generation-workshop/icon-video.png';
|
||||||
|
import { ORIGIN_LIST } from '@/views/material-center/components/raw-material/constants';
|
||||||
// import icon4 from '@/assets/img/error-img.png';
|
// import icon4 from '@/assets/img/error-img.png';
|
||||||
|
|
||||||
const emits = defineEmits(['edit', 'sorterChange', 'delete']);
|
const emits = defineEmits(['edit', 'sorterChange', 'delete']);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
export const INITIAL_QUERY = {
|
export const INITIAL_QUERY = {
|
||||||
title: '',
|
title: '',
|
||||||
// project_ids: [],
|
// project_ids: [],
|
||||||
uid: '',
|
// uid: '',
|
||||||
audit_status: '',
|
audit_status: '',
|
||||||
created_at: [],
|
created_at: [],
|
||||||
sort_column: undefined,
|
sort_column: undefined,
|
||||||
|
|||||||
Reference in New Issue
Block a user