Merge remote-tracking branch 'origin/feature/0915_素材中心新增手动上传' into feature/0918_账号管理新增视图_rxd

This commit is contained in:
rd
2025-09-22 14:38:58 +08:00
11 changed files with 237 additions and 151 deletions

View File

@ -27,7 +27,7 @@
&:focus-within, &:focus-within,
&.ant-input-focus, &.ant-input-focus,
&.ant-textarea-focus { &.ant-textarea-focus {
background-color: var(--color-bg-2) !important; background-color: #fff !important;
border-color: $color-primary !important; border-color: $color-primary !important;
box-shadow: 0 0 0 0 var(--color-primary-light-2) !important; box-shadow: 0 0 0 0 var(--color-primary-light-2) !important;
} }

View File

@ -41,6 +41,12 @@
.ant-modal-confirm-body-wrapper { .ant-modal-confirm-body-wrapper {
.ant-modal-confirm-title { .ant-modal-confirm-title {
font-family: $font-family-medium;
font-weight: 500;
color: #211F24;
font-size: 16px;
font-style: normal;
line-height: 24px;
.anticon { .anticon {
font-size: 24px; font-size: 24px;
} }

View File

@ -27,13 +27,28 @@
.ant-select-arrow { .ant-select-arrow {
color: #737478; color: #737478;
//font-size: 14px;
.anticon {
&.anticon-down {
color: #737478;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14' fill='none'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11.9629 5.5L11.1379 4.67504L7.01314 8.79983L2.88835 4.67504L2.0634 5.5L6.60063 10.0372C6.60063 10.0372 6.60066 10.0373 7.01314 9.62479L6.60063 10.0372L7.01314 10.4497L11.9629 5.5Z' fill='%23737478'/%3E%3C/svg%3E");
background-size: 14px;
width: 14px;
height: 14px;
background-repeat: no-repeat;
background-position: center right;
> svg {
display: none;
}
}
}
} }
&:focus, &:focus,
&-focused { &-focused {
.ant-select-selector { .ant-select-selector {
background-color: var(--color-bg-2) !important; background-color: #fff !important;
border-color: rgb(var(--primary-6)) !important; border-color: $color-primary !important;
box-shadow: 0 0 0 0 var(--color-primary-light-2) !important; box-shadow: 0 0 0 0 var(--color-primary-light-2) !important;
} }
} }
@ -44,7 +59,7 @@
&:not(.ant-select-disabled) { &:not(.ant-select-disabled) {
&:hover { &:hover {
.ant-select-selector { .ant-select-selector {
border-color: rgb(var(--primary-6)) !important; border-color: $color-primary !important;
} }
} }
} }
@ -55,6 +70,16 @@
} }
} }
&.ant-select-open {
.ant-select-arrow {
.anticon {
&.anticon-down {
transform: rotate(180deg);
}
}
}
}
} }
.ant-select { .ant-select {

View File

@ -62,20 +62,40 @@
} }
.ant-table-bordered { .ant-table-bordered {
.ant-table-container { .ant-table-container {
.ant-table-content {
> table {
border-top: none !important;
.ant-table-thead { .ant-table-thead {
.ant-table-cell { .ant-table-cell {
border-inline-end: none !important; border-inline-end: none !important;
border-bottom: 1px solid var(--Border-1, #d7d7d9); border-bottom: 1px solid var(--Border-1, #d7d7d9);
} }
.ant-table-cell-fix-right-first {
&::after {
border-inline-end: none !important;
} }
}
}
.ant-table-tbody { .ant-table-tbody {
.ant-table-row { .ant-table-row {
.ant-table-cell { .ant-table-cell {
border-inline-end: none !important; border-inline-end: none !important;
border-bottom: 1px solid var(--Border-1, #e6e6e8); border-bottom: 1px solid var(--Border-1, #e6e6e8);
} }
.ant-table-cell-fix-right-first {
&::after {
border-inline-end: none !important;
} }
} }
} }
} }
} }
}
}
}
}

View File

@ -6,7 +6,7 @@
&:not(.ant-input-textarea-disabled) { &:not(.ant-input-textarea-disabled) {
&:hover { &:hover {
.ant-input { .ant-input {
border-color: rgb(var(--primary-6)) !important; border-color: $color-primary !important;
} }
} }
} }

View File

@ -120,7 +120,7 @@ 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];

View File

@ -19,7 +19,7 @@ import {
documentExtensions, documentExtensions,
} from '@/views/material-center/components/raw-material/constants'; } from '@/views/material-center/components/raw-material/constants';
import icon1 from '@/assets/img/media-account/icon-delete.png'; // import icon1 from '@/assets/img/media-account/icon-delete.png';
import icon2 from '../../img/icon-no-text.png'; import icon2 from '../../img/icon-no-text.png';
enum EnumUploadStatus { enum EnumUploadStatus {
@ -71,6 +71,7 @@ export default defineComponent({
}; };
const handleTagChange = (value, option, record) => { const handleTagChange = (value, option, record) => {
// console.log('handleTagChange', value);
if (value.length < 6) { if (value.length < 6) {
record.tag_ids = value; record.tag_ids = value;
} else { } else {
@ -88,8 +89,8 @@ export default defineComponent({
return; return;
} }
if (record.tag_ids.length >= 5) { if (record.tag_ids.length === 5) {
message.warning('最多选择5个'); // message.warning('最多选择5个');
return; return;
} }
@ -103,7 +104,8 @@ export default defineComponent({
}); });
e.target.value = ''; e.target.value = '';
record.tag_ids = [...record.tag_ids, data.id]; record.tag_ids = record.tag_ids.filter((item) => item !== inputValue);
record.tag_ids.push(data.id);
} }
} catch (error) { } catch (error) {
message.error('添加标签失败'); message.error('添加标签失败');
@ -186,7 +188,7 @@ export default defineComponent({
const currentData = { const currentData = {
uid, uid,
name, name: name.slice(0, 20),
// type, // type,
type: fileType, type: fileType,
uploadStatus: statusText ? EnumUploadStatus.error : EnumUploadStatus.uploading, uploadStatus: statusText ? EnumUploadStatus.error : EnumUploadStatus.uploading,
@ -259,17 +261,19 @@ export default defineComponent({
}; };
const onConfirm = async () => { const onConfirm = async () => {
try {
const hasUploading = uploadData.value.some((item) => item.uploadStatus === EnumUploadStatus.uploading); const hasUploading = uploadData.value.some((item) => item.uploadStatus === EnumUploadStatus.uploading);
if (hasUploading) { if (hasUploading) {
modalRef.value = Modal.warning({ modalRef.value = Modal.warning({
title: '上传未完成', title: '上传未完成',
content: <p class="h-22px">当前原料正在上传中关闭弹窗将导致上传失败请等待上传完成后再点击确定</p>, content: <p>当前原料正在上传中关闭弹窗将导致上传失败请等待上传完成后再点击确定</p>,
okText: '我知道了', okText: '我知道了',
centered: true, centered: true,
}); });
return; return;
} }
submitLoading.value = true;
const raw_materials = uploadData.value.filter((item) => item.uploadStatus !== EnumUploadStatus.error); const raw_materials = uploadData.value.filter((item) => item.uploadStatus !== EnumUploadStatus.error);
const { code } = await postBatchRawMaterial({ raw_materials }); const { code } = await postBatchRawMaterial({ raw_materials });
if (code === 200) { if (code === 200) {
@ -277,6 +281,9 @@ export default defineComponent({
emit('update'); emit('update');
onClose(); onClose();
} }
} finally {
submitLoading.value = false;
}
}; };
const openDeleteModal = (file) => { const openDeleteModal = (file) => {
modalRef.value = Modal.warning({ modalRef.value = Modal.warning({
@ -312,7 +319,7 @@ export default defineComponent({
const renderUploadStatus = (record) => { const renderUploadStatus = (record) => {
if (record.uploadStatus === EnumUploadStatus.error) { if (record.uploadStatus === EnumUploadStatus.error) {
return ( return (
<div> <div class="w-100px">
<p class="upload-text">上传失败</p> <p class="upload-text">上传失败</p>
<p class="upload-text !color-#F64B31">{record.statusText}</p> <p class="upload-text !color-#F64B31">{record.statusText}</p>
</div> </div>
@ -320,9 +327,7 @@ export default defineComponent({
} }
return ( return (
<div> <div>
<span class="upload-text ml-26px"> <p class="upload-text w-100px">{record.uploadStatus === EnumUploadStatus.done ? '上传成功' : '上传中'}</p>
{record.uploadStatus === EnumUploadStatus.done ? '上传成功' : '上传中'}
</span>
<Progress percent={record.percent} class="m-0 p-0 " /> <Progress percent={record.percent} class="m-0 p-0 " />
</div> </div>
); );
@ -340,7 +345,7 @@ export default defineComponent({
ref="tableRef" ref="tableRef"
dataSource={uploadData.value} dataSource={uploadData.value}
pagination={false} pagination={false}
class="w-100% flex-1" class="w-100% flex-1 overflow-hidden"
scroll={{ y: '100%' }} scroll={{ y: '100%' }}
> >
<Column <Column
@ -352,15 +357,16 @@ export default defineComponent({
customRender={({ text, record }) => { customRender={({ text, record }) => {
return ( return (
<div class="flex items-center justify-end"> <div class="flex items-center justify-end">
<ImgLazyLoad width={64} height={64} src={record.cover} class="!rounded-6px mr-16px flex-shrink-0" /> <ImgLazyLoad width={64} height={64} src={record.cover} class="!rounded-8px mr-16px flex-shrink-0" />
<TextArea <TextArea
v-model:value={record.name} v-model:value={record.name}
placeholder="请输入文件名称" placeholder="请输入文件名称"
size="large" size="large"
class="w-full !h-72px" class="w-full !h-72px no-resize"
showCount showCount
maxlength={20} maxlength={20}
autoSize={false}
/> />
</div> </div>
); );
@ -383,7 +389,7 @@ export default defineComponent({
<Select <Select
disabled={record.uploadStatus === EnumUploadStatus.uploading} disabled={record.uploadStatus === EnumUploadStatus.uploading}
value={record.tag_ids} value={record.tag_ids}
mode="multiple" mode="tags"
size="middle" size="middle"
placeholder="请选择标签" placeholder="请选择标签"
allowClear allowClear
@ -406,7 +412,7 @@ export default defineComponent({
v-slots={{ v-slots={{
tagRender: (val) => { tagRender: (val) => {
const { label, value } = val; const { label, value } = val;
if (label.length > 5) { if (label.length > 4) {
return ( return (
<div class="my-2px"> <div class="my-2px">
<Tooltip title={label}> <Tooltip title={label}>
@ -415,7 +421,7 @@ export default defineComponent({
onClose={() => (record.tag_ids = record.tag_ids.filter((item) => item !== value))} onClose={() => (record.tag_ids = record.tag_ids.filter((item) => item !== value))}
class="mr-0 !color-#55585F h-20px !lh-20px !text-12px" class="mr-0 !color-#55585F h-20px !lh-20px !text-12px"
> >
{label.slice(0, 5) + '...'} {label.slice(0, 3) + '...'}
</Tag> </Tag>
</Tooltip> </Tooltip>
</div> </div>
@ -458,12 +464,9 @@ export default defineComponent({
customRender={({ text, record }) => { customRender={({ text, record }) => {
return ( return (
<div class="flex items-center justify-end"> <div class="flex items-center justify-end">
<img <icon-delete
alt="" class="mr-8px color-#737478 cursor-pointer"
class="cursor-pointer" size="14"
src={icon1}
width="14"
height="14"
onClick={() => openDeleteModal(record)} onClick={() => openDeleteModal(record)}
/> />
</div> </div>
@ -482,7 +485,7 @@ export default defineComponent({
<Drawer <Drawer
width={1100} width={1100}
title="上传到原料库" title="上传到原料库"
rootClassName="xt-add-raw-material-modal" rootClassName="xt-add-raw-material-drawer"
v-model:open={visible.value} v-model:open={visible.value}
onClose={onClose} onClose={onClose}
maskClosable={false} maskClosable={false}
@ -510,7 +513,7 @@ export default defineComponent({
<span class="cts">点击或拖拽文件到此处上传</span> <span class="cts">点击或拖拽文件到此处上传</span>
</div> </div>
</Upload> </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">{`视频格式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="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> <p class="cts !color-#939499 !text-12px !lh-20px">{`文本格式TXT、DOC、DOCX、PDF大小<20MB`}</p>
</div> </div>

View File

@ -1,4 +1,7 @@
.xt-add-raw-material-modal { .xt-add-raw-material-drawer {
.ant-drawer-content {
border-radius: 16px 0 0 16px;
.ant-drawer-header { .ant-drawer-header {
height: 58px; height: 58px;
border-bottom: none; border-bottom: none;
@ -14,6 +17,30 @@
//} //}
} }
.ant-table {
.ant-table-container {
display: flex;
flex-direction: column;
}
.ant-table-header {
flex-shrink: 0;
.ant-table-cell {
&::before {
display: none;
}
}
}
}
.ant-input-textarea {
&.no-resize {
textarea {
resize: none;
}
}
}
.ant-drawer-body { .ant-drawer-body {
padding: 0; padding: 0;
display: flex; display: flex;
@ -54,7 +81,7 @@
.ant-progress-outer { .ant-progress-outer {
position: relative; position: relative;
width: 100%; width: 100px !important;
height: 6px !important; height: 6px !important;
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -64,21 +91,18 @@
top: 50%; top: 50%;
left: 0; left: 0;
transform: translateY(-50%); transform: translateY(-50%);
width: 100px;
height: 6px !important; height: 6px !important;
background: var(--BG-200, #F2F3F5); background: var(--BG-200, #f2f3f5);
.ant-progress-bg { .ant-progress-bg {
height: 6px !important; height: 6px !important;
background-color: #6D4CFE; background-color: #6d4cfe;
} }
} }
} }
.ant-progress-text { .ant-progress-text {
color: var(--Text-1, #211F24); color: var(--Text-1, #211f24);
font-family: $font-family-regular; font-family: $font-family-regular;
font-size: 12px; font-size: 12px;
font-style: normal; font-style: normal;
@ -87,18 +111,17 @@
.anticon { .anticon {
font-size: 16px; font-size: 16px;
} }
} }
&.ant-progress-status-success { &.ant-progress-status-success {
.ant-progress-outer { .ant-progress-outer {
.ant-progress-bg { .ant-progress-bg {
background-color: #25C883; background-color: #25c883;
} }
} }
.ant-progress-text { .ant-progress-text {
color: #25C883; color: #25c883;
} }
} }
} }
@ -108,3 +131,4 @@
} }
} }
} }
}

View File

@ -126,8 +126,8 @@ export default {
return; return;
} }
if (form.value.tag_ids.length >= 5) { if (form.value.tag_ids.length === 5) {
message.warning('最多选择5个'); // message.warning('最多选择5个');
return; return;
} }
@ -141,7 +141,8 @@ export default {
}); });
e.target.value = ''; e.target.value = '';
form.value.tag_ids = [...form.value.tag_ids, data.id]; form.value.tag_ids = form.value.tag_ids.filter((item) => item !== inputValue);
form.value.tag_ids.push(data.id);
} }
} catch (error) { } catch (error) {
message.error('添加标签失败'); message.error('添加标签失败');
@ -203,7 +204,7 @@ export default {
<FormItem label="标签" name="tag_ids" v-model:value={form.value.tag_ids}> <FormItem label="标签" name="tag_ids" v-model:value={form.value.tag_ids}>
<Select <Select
value={form.value.tag_ids} value={form.value.tag_ids}
mode="multiple" mode="tags"
size="large" size="large"
placeholder="请选择标签" placeholder="请选择标签"
allowClear allowClear

View File

@ -6,7 +6,7 @@
</div> </div>
<template #footer> <template #footer>
<Button size="medium" @click="onClose">取消</Button> <Button size="medium" @click="onClose">取消</Button>
<Button type="primary" class="ml-16px" danger size="medium" @click="onDelete">确认删除</Button> <Button :loading="loading" class="ml-16px" danger size="medium" type="primary" @click="onDelete">确认删除</Button>
</template> </template>
</Modal> </Modal>
</template> </template>
@ -24,12 +24,14 @@ const emits = defineEmits(['update', 'batchUpdate']);
const visible = ref(false); const visible = ref(false);
const fileId = ref(null); const fileId = ref(null);
const fileName = ref(''); const fileName = ref('');
const loading = ref(false);
const isBatch = computed(() => Array.isArray(fileId.value)); const isBatch = computed(() => Array.isArray(fileId.value));
function onClose() { function onClose() {
visible.value = false; visible.value = false;
fileId.value = null; fileId.value = null;
loading.value = false;
fileName.value = ''; fileName.value = '';
} }
@ -42,6 +44,8 @@ const open = (record) => {
}; };
async function onDelete() { async function onDelete() {
try {
loading.value = true;
const _fn = isBatch.value ? batchDeleteRawMaterials : deleteRawMaterial; const _fn = isBatch.value ? batchDeleteRawMaterials : deleteRawMaterial;
const _params = isBatch.value ? { ids: fileId.value } : fileId.value; const _params = isBatch.value ? { ids: fileId.value } : fileId.value;
const { code } = await _fn(_params); const { code } = await _fn(_params);
@ -51,6 +55,9 @@ async function onDelete() {
onClose(); onClose();
} }
} finally {
loading.value = false;
}
} }
defineExpose({ open }); defineExpose({ open });

View File

@ -33,12 +33,12 @@
</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.type === RawMaterialType.Text ? icon2 : record.cover"> <HoverImagePreview :src="record.type === RawMaterialType.Text ? '' : record.cover">
<ImgLazyLoad <ImgLazyLoad
:height="64" :height="64"
:src="record.type === RawMaterialType.Text ? icon2 : record.cover" :src="record.type === RawMaterialType.Text ? icon2 : record.cover"
:width="64" :width="64"
class="!rounded-6px mr-16px" class="!rounded-8px mr-16px"
/> />
</HoverImagePreview> </HoverImagePreview>
<div class="flex-1 flex flex-col overflow-hidden"> <div class="flex-1 flex flex-col overflow-hidden">
@ -54,9 +54,9 @@
<div v-if="record.tags.length > 0" class="flex flex-wrap gap-4px"> <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"> <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"> <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> <span class="cts !color-#55585F !lh-20px !text-12px regular"> {{ `${tag.name.slice(0, 5)}...` }} </span>
</Tooltip> </Tooltip>
<span v-else class="cts !color-#55585F !lh-20px !text-12px"> {{ tag.name }} </span> <span v-else class="cts !color-#55585F !lh-20px !text-12px regular"> {{ tag.name }} </span>
</Tag> </Tag>
</div> </div>
<template v-else> -</template> <template v-else> -</template>
@ -75,7 +75,7 @@
</template> </template>
<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)" /> <icon-delete class="mr-8px color-#737478 cursor-pointer" size="14" @click="onDelete(record)" />
<Button class="mr-8px !h-24px !px-12px" ghost size="small" type="primary" @click="onEdit(record)" <Button class="mr-8px !h-24px !px-12px" ghost size="small" type="primary" @click="onEdit(record)"
>编辑 >编辑
</Button> </Button>
@ -102,7 +102,7 @@ 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 '../../img/icon-no-text.png'; import icon2 from '../../img/icon-no-text.png';
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll', 'edit']); const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll', 'edit']);