feat: 添加原料库上传功能和相关组件
- 在 `raw-material` 组件中添加上传按钮和抽屉组件 - 新增 `add-raw-material-drawer` 组件及其样式文件 - 更新样式文件以支持新的上传界面 - 调整 Ant Select 和 Drawer 组件的样式
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@
|
||||
border-color: $color-error !important;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.ant-select {
|
||||
@ -103,20 +102,69 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-select-single {
|
||||
.ant-select-selector {
|
||||
height: 32px !important;
|
||||
}
|
||||
|
||||
&.ant-select-lg {
|
||||
.ant-select-selector {
|
||||
height: 36px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.ant-select-sm {
|
||||
.ant-select-selector {
|
||||
height: 28px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select.ant-select-single {
|
||||
.ant-select-selector {
|
||||
height: 32px !important;
|
||||
}
|
||||
&.ant-select-lg {
|
||||
.ant-select-selector {
|
||||
height: 36px !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;
|
||||
}
|
||||
}
|
||||
&.ant-select-sm {
|
||||
.ant-select-selector {
|
||||
height: 28px !important;
|
||||
|
||||
&: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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,4 +2,18 @@
|
||||
.ant-input {
|
||||
padding: 8px 12px 4px 12px;
|
||||
}
|
||||
|
||||
&.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-step.scss";
|
||||
@import "./ant-spin.scss";
|
||||
@import "./ant-drawer.scss";
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
export function toFixed(num: number | string, n: number): number {
|
||||
return parseFloat(parseFloat(num.toString()).toFixed(n));
|
||||
}
|
||||
|
||||
@ -43,12 +43,12 @@
|
||||
<img :src="visible ? icon2 : icon1" width="20" height="20" class="cursor-pointer" />
|
||||
</template>
|
||||
</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 }}
|
||||
</p>
|
||||
</FormItem>
|
||||
|
||||
<FormItem class="mt-52px">
|
||||
<FormItem class="mt-32px">
|
||||
<div class="text-12px flex justify-center items-center mb-16px">
|
||||
<Checkbox v-model:checked="hasCheck" class="mr-8px"></Checkbox>
|
||||
<span class="text-12px color-#737478 font-400 lh-20px font-family-regular"
|
||||
@ -67,14 +67,18 @@
|
||||
登录
|
||||
</Button>
|
||||
<div class="flex justify-between btn-row">
|
||||
<Button
|
||||
type="text"
|
||||
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
||||
size="small"
|
||||
@click="onForgetPassword"
|
||||
>
|
||||
忘记密码?
|
||||
</Button>
|
||||
<div>
|
||||
<Button
|
||||
v-show="!isCaptchaLogin"
|
||||
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
||||
size="small"
|
||||
type="text"
|
||||
@click="onForgetPassword"
|
||||
>
|
||||
忘记密码?
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="text"
|
||||
class="!color-#939499 !p-0 !h-22px hover:color-#6D4CFE"
|
||||
|
||||
@ -0,0 +1,244 @@
|
||||
<script lang="tsx">
|
||||
import { Drawer, Button, Upload, Table, Input } from 'ant-design-vue';
|
||||
|
||||
const { Column } = Table;
|
||||
const { TextArea } = Input;
|
||||
|
||||
import CommonSelect from '@/components/common-select';
|
||||
import ImgLazyLoad from '@/components/img-lazy-load';
|
||||
|
||||
import { formatFileSize, getVideoInfo, formatDuration, formatUploadSpeed } from '@/utils/tools';
|
||||
import { getRawMaterialTagsList } from '@/api/all/generationWorkshop';
|
||||
|
||||
import icon1 from '@/assets/img/media-account/icon-delete.png';
|
||||
|
||||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'];
|
||||
const videoExtensions = ['.mp4', '.mov', '.avi', '.flv', '.wmv', '.m4v'];
|
||||
const documentExtensions = ['.txt', '.doc', '.docx', '.pdf', '.xls', '.xlsx'];
|
||||
|
||||
export default defineComponent({
|
||||
setup(_, { attrs, slots, expose }) {
|
||||
const visible = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
const uploadData = ref([]);
|
||||
const tagData = ref([]);
|
||||
|
||||
const checkSuccessNum = computed(() => {
|
||||
return uploadData.value.filter((item) => item.status === 'success').length;
|
||||
});
|
||||
|
||||
const getTagData = async () => {
|
||||
const { code, data } = await getRawMaterialTagsList();
|
||||
if (code === 200) {
|
||||
tagData.value = data ?? [];
|
||||
}
|
||||
};
|
||||
|
||||
const open = () => {
|
||||
getTagData();
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
visible.value = false;
|
||||
|
||||
uploadData.value = [];
|
||||
tagData.value = [];
|
||||
submitLoading.value = false;
|
||||
};
|
||||
|
||||
const handleUpload = async (option) => {
|
||||
// console.log('handleUpload', option);
|
||||
};
|
||||
|
||||
const getFileType = (fileName) => {
|
||||
const ext = fileName.slice(fileName.lastIndexOf('.')).toLowerCase();
|
||||
|
||||
if (imageExtensions.includes(ext)) {
|
||||
return '图片';
|
||||
} else if (videoExtensions.includes(ext)) {
|
||||
return '视频';
|
||||
} else if (documentExtensions.includes(ext)) {
|
||||
return '文档';
|
||||
} else {
|
||||
return '其他';
|
||||
}
|
||||
};
|
||||
|
||||
const onConfirm = () => {
|
||||
console.log('onConfirm');
|
||||
};
|
||||
const handleDelete = (file) => {
|
||||
uploadData.value = uploadData.value.filter((item) => item.uid !== file.uid);
|
||||
};
|
||||
|
||||
const renderUploadList = (file, actions) => {
|
||||
if (!uploadData.value.length) return null;
|
||||
|
||||
console.log('renderUploadList', uploadData.value);
|
||||
|
||||
return (
|
||||
<>
|
||||
<p class="cts !color-#939499 mb-10px">
|
||||
已上传:<span class="!color-#211F24">{`${checkSuccessNum.value}/${uploadData.value.length}`}</span>
|
||||
</p>
|
||||
<Table ref="tableRef" dataSource={uploadData.value} pagination={false} class="manuscript-table w-100% flex-1">
|
||||
<Column
|
||||
title="文件名称"
|
||||
dataIndex="name"
|
||||
key="name"
|
||||
width={347}
|
||||
ellipsis={true}
|
||||
customRender={({ text, record }) => {
|
||||
return (
|
||||
<div class="flex items-center">
|
||||
<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="status"
|
||||
key="status"
|
||||
width={164}
|
||||
customRender={({ text, record }) => {
|
||||
if (record.status === 'done') {
|
||||
return <span class="upload-text">上传成功</span>;
|
||||
} else if (record.status === 'error') {
|
||||
return <span class="upload-text">上传失败</span>;
|
||||
} else {
|
||||
return <span class="upload-text">上传中</span>;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
title="标签"
|
||||
dataIndex="tags"
|
||||
key="tags"
|
||||
width={243}
|
||||
customRender={({ text, record }) => {
|
||||
return (
|
||||
<CommonSelect
|
||||
v-model={record.tags}
|
||||
class="w-full"
|
||||
multiple
|
||||
options={tagData}
|
||||
placeholder="请选择标签"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
title="类型"
|
||||
dataIndex="type"
|
||||
key="type"
|
||||
width={80}
|
||||
customRender={({ text, record }) => {
|
||||
const fileName = record.name || '';
|
||||
return <span>{getFileType(fileName)}</span>;
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
title="大小"
|
||||
dataIndex="size"
|
||||
key="size"
|
||||
width={100}
|
||||
customRender={({ text, record }) => formatFileSize(record.size)}
|
||||
/>
|
||||
<Column
|
||||
title="操作"
|
||||
key="action"
|
||||
width={118}
|
||||
fixed="right"
|
||||
customRender={({ text, record }) => {
|
||||
return (
|
||||
<div class="flex items-center">
|
||||
<Button type="text" class="!h-22px !p-0 mr-16px">
|
||||
取消生成
|
||||
</Button>
|
||||
<img
|
||||
class="cursor-pointer"
|
||||
src={icon1}
|
||||
width="14"
|
||||
height="14"
|
||||
onClick={() => handleDelete(record)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
expose({
|
||||
open,
|
||||
});
|
||||
return () => (
|
||||
<Drawer
|
||||
width={1100}
|
||||
title="上传到原料库"
|
||||
rootClassName="xt-add-raw-material-modal"
|
||||
v-model:open={visible.value}
|
||||
onClose={onClose}
|
||||
>
|
||||
<section class="content flex-1 pt-8px px-24px pb-24px">
|
||||
<div class=" rounded-16px bg-#F7F8FA p-16px flex flex-col items-center mb-24px">
|
||||
<Upload
|
||||
v-model:file-list={uploadData.value}
|
||||
action="/"
|
||||
multiple
|
||||
customRequest={handleUpload}
|
||||
class="w-full mb-16px"
|
||||
accept={[...imageExtensions, ...videoExtensions, ...documentExtensions].join(',')}
|
||||
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">
|
||||
<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={onClose} class="mr-12px">
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
size="large"
|
||||
type="primary"
|
||||
onClick={onConfirm}
|
||||
loading={submitLoading.value}
|
||||
disabled={!checkSuccessNum.value}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
</footer>
|
||||
</Drawer>
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './style.scss';
|
||||
</style>
|
||||
@ -0,0 +1,48 @@
|
||||
.xt-add-raw-material-modal {
|
||||
.ant-drawer-header {
|
||||
height: 58px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.ant-upload {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import FilterBlock from './components/filter-block/index.vue';
|
||||
import RawMaterialTable from './components/table/index.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 { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||
import { getRawMaterialsPage } from '@/api/all/generationWorkshop';
|
||||
@ -32,6 +33,7 @@ export default defineComponent({
|
||||
|
||||
const deleteRawMaterialModalRef = ref(null);
|
||||
const tagsManageModalRef = ref(null);
|
||||
const addRawMaterialDrawerRef = ref(null);
|
||||
|
||||
const query = ref(cloneDeep(INITIAL_QUERY));
|
||||
const handleSearch = () => {
|
||||
@ -91,7 +93,7 @@ export default defineComponent({
|
||||
tagsManageModalRef.value?.open();
|
||||
};
|
||||
const handleAddMaterial = () => {
|
||||
console.log('handleAddMaterial');
|
||||
addRawMaterialDrawerRef.value?.open();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@ -182,6 +184,7 @@ export default defineComponent({
|
||||
</div>
|
||||
|
||||
<TagsManageModal ref={tagsManageModalRef} />
|
||||
<AddRawMaterialDrawer ref={addRawMaterialDrawerRef} />
|
||||
<DeleteRawMaterialModal ref={deleteRawMaterialModalRef} onBatchUpdate={onBatchSuccess} onUpdate={getData} />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user