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,
&.ant-input-focus,
&.ant-textarea-focus {
background-color: var(--color-bg-2) !important;
background-color: #fff !important;
border-color: $color-primary !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-title {
font-family: $font-family-medium;
font-weight: 500;
color: #211F24;
font-size: 16px;
font-style: normal;
line-height: 24px;
.anticon {
font-size: 24px;
}

View File

@ -27,13 +27,28 @@
.ant-select-arrow {
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,
&-focused {
.ant-select-selector {
background-color: var(--color-bg-2) !important;
border-color: rgb(var(--primary-6)) !important;
background-color: #fff !important;
border-color: $color-primary !important;
box-shadow: 0 0 0 0 var(--color-primary-light-2) !important;
}
}
@ -44,7 +59,7 @@
&:not(.ant-select-disabled) {
&:hover {
.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 {

View File

@ -62,20 +62,40 @@
}
.ant-table-bordered {
.ant-table-container {
.ant-table-content {
> table {
border-top: none !important;
.ant-table-thead {
.ant-table-cell {
border-inline-end: none !important ;
border-inline-end: none !important;
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-row {
.ant-table-cell {
border-inline-end: none !important;
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) {
&:hover {
.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';
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));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];

View File

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

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 {
height: 58px;
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 {
padding: 0;
display: flex;
@ -54,7 +81,7 @@
.ant-progress-outer {
position: relative;
width: 100%;
width: 100px !important;
height: 6px !important;
margin: 0;
padding: 0;
@ -64,21 +91,18 @@
top: 50%;
left: 0;
transform: translateY(-50%);
width: 100px;
height: 6px !important;
background: var(--BG-200, #F2F3F5);
background: var(--BG-200, #f2f3f5);
.ant-progress-bg {
height: 6px !important;
background-color: #6D4CFE;
}
background-color: #6d4cfe;
}
}
}
.ant-progress-text {
color: var(--Text-1, #211F24);
color: var(--Text-1, #211f24);
font-family: $font-family-regular;
font-size: 12px;
font-style: normal;
@ -87,18 +111,17 @@
.anticon {
font-size: 16px;
}
}
&.ant-progress-status-success {
.ant-progress-outer {
.ant-progress-bg {
background-color: #25C883;
background-color: #25c883;
}
}
.ant-progress-text {
color: #25C883;
color: #25c883;
}
}
}
@ -107,4 +130,5 @@
.footer {
}
}
}
}

View File

@ -126,8 +126,8 @@ export default {
return;
}
if (form.value.tag_ids.length >= 5) {
message.warning('最多选择5个');
if (form.value.tag_ids.length === 5) {
// message.warning('最多选择5个');
return;
}
@ -141,7 +141,8 @@ export default {
});
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) {
message.error('添加标签失败');
@ -203,7 +204,7 @@ export default {
<FormItem label="标签" name="tag_ids" v-model:value={form.value.tag_ids}>
<Select
value={form.value.tag_ids}
mode="multiple"
mode="tags"
size="large"
placeholder="请选择标签"
allowClear

View File

@ -6,7 +6,7 @@
</div>
<template #footer>
<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>
</Modal>
</template>
@ -24,12 +24,14 @@ const emits = defineEmits(['update', 'batchUpdate']);
const visible = ref(false);
const fileId = ref(null);
const fileName = ref('');
const loading = ref(false);
const isBatch = computed(() => Array.isArray(fileId.value));
function onClose() {
visible.value = false;
fileId.value = null;
loading.value = false;
fileName.value = '';
}
@ -42,6 +44,8 @@ const open = (record) => {
};
async function onDelete() {
try {
loading.value = true;
const _fn = isBatch.value ? batchDeleteRawMaterials : deleteRawMaterial;
const _params = isBatch.value ? { ids: fileId.value } : fileId.value;
const { code } = await _fn(_params);
@ -51,6 +55,9 @@ async function onDelete() {
onClose();
}
} finally {
loading.value = false;
}
}
defineExpose({ open });

View File

@ -33,12 +33,12 @@
</template>
<template v-if="column.dataIndex === 'name'" #customRender="{ record }">
<div class="flex items-center">
<HoverImagePreview :src="record.type === RawMaterialType.Text ? icon2 : record.cover">
<HoverImagePreview :src="record.type === RawMaterialType.Text ? '' : record.cover">
<ImgLazyLoad
:height="64"
:src="record.type === RawMaterialType.Text ? icon2 : record.cover"
:width="64"
class="!rounded-6px mr-16px"
class="!rounded-8px mr-16px"
/>
</HoverImagePreview>
<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">
<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>
<span class="cts !color-#55585F !lh-20px !text-12px regular"> {{ `${tag.name.slice(0, 5)}...` }} </span>
</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>
</div>
<template v-else> -</template>
@ -75,7 +75,7 @@
</template>
<template v-else-if="column.dataIndex === 'operation'" #customRender="{ record }">
<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>
@ -102,7 +102,7 @@ import TextOverTips from '@/components/text-over-tips';
import HoverImagePreview from '@/components/hover-image-preview';
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';
const emits = defineEmits(['sorterChange', 'delete', 'select', 'selectAll', 'edit']);