1.上传附件接口联调

sws 2024-08-15
v1.0.0
sws 2024-08-15 14:57:00 +08:00
parent f5b08ef7b5
commit b3e948aeea
10 changed files with 296 additions and 236 deletions

View File

@ -32,6 +32,39 @@ class UploadAPI {
data,
});
}
// 附件列表
static getAttachmentList(data: any) {
return request({
url: `diyapi/attachmentlist`,
method: 'post',
data,
});
}
// 附件名称修改
static saveAttachmentName(data: any) {
return request({
url: `diyapi/attachmentsave`,
method: 'post',
data,
});
}
// 附件删除
static delAttachment(data: any) {
return request({
url: `diyapi/attachmentdelete`,
method: 'post',
data,
});
}
// 附件上传
static uploadAttachment(data: any) {
return request({
url: `diyapi/attachmentupload`,
method: 'post',
data,
});
}
}
export default UploadAPI;

View File

@ -0,0 +1,28 @@
<template>
<div class="flex-col align-c jc-c w h bg-f" :style="container_style">
<img :style="style" :src="noData_image" />
<p class="size-14 cr-c mt-12">暂无数据</p>
</div>
</template>
<script setup lang="ts">
interface Props {
imgWidth?: string;
height?: string;
}
const props = withDefaults(defineProps<Props>(), {
imgWidth: '100',
height: '200',
});
const noData_image = ref(new URL(`../../../assets/images/noData.png`, import.meta.url).href);
const style = computed(() => {
return {
width: props.imgWidth.search('px') > -1 ? props.imgWidth : props.imgWidth + 'px',
};
});
const container_style = computed(() => {
return {
height: props.height.search('px') > -1 ? props.height : props.height + 'px',
};
});
</script>

View File

@ -1,16 +0,0 @@
<template>
<div class="flex-col align-c jc-c w h bg-f">
<img :style="{'width': props.imgWidth + 'rem'}" :src="noData_image" />
<p class="size-14 cr-c mt-12">暂无数据</p>
</div>
</template>
<script setup lang="ts">
interface Props {
imgWidth?: number;
}
const props = withDefaults(defineProps<Props>(), {
imgWidth: 10,
});
const noData_image = ref(new URL(`../../../assets/images/noData.png`, import.meta.url).href);
</script>

View File

@ -17,7 +17,7 @@
<el-input v-model="form.sort" placeholder="请输入排序"></el-input>
</el-form-item>
<el-form-item label="是否启用">
<!-- <el-switch v-model="form.is_enable"></el-switch> -->
<el-switch v-model="form.is_enable" :active-value="typeof form.is_enable == 'string' ? '1' : 1" :inactive-value="typeof form.is_enable == 'string' ? '0' : 0"></el-switch>
</el-form-item>
</el-form>
</div>

View File

@ -11,6 +11,11 @@
color: $cr-primary;
}
}
.disabled {
position: relative;
cursor: not-allowed;
height: 100%;
}
}
.right-content {
position: relative;

View File

@ -22,14 +22,20 @@
<icon name="add" size="18" class="c-pointer" @click="add_type"></icon>
</div>
<el-scrollbar height="490px">
<el-tree ref="treeRef" class="filter-tree" :data="type_data" node-key="id" highlight-current :expand-on-click-node="false" :props="defaultProps" empty-text="" default-expand-all :filter-node-method="filter_node" @node-click="tree_node_event">
<el-tree ref="treeRef" class="filter-tree" :data="type_data" node-key="id" highlight-current :props="defaultProps" empty-text="" default-expand-all :filter-node-method="filter_node" @node-click="tree_node_event">
<template #default="{ node, data }">
<div class="custom-tree-node flex-row jc-sb gap-10 align-c w pr-10">
<div class="custom-tree-node flex-row jc-sb gap-10 align-c w pr-10" :class="data.is_enable == 0 || node.parent.data.is_enable == 0 ? 'disabled bg-red' : ''">
<div class="flex-1 flex-width text-line-1 block">{{ data.name }}</div>
<div class="flex-row gap-10 cr-9 category-oprate">
<icon v-if="data.pid == 0" class="icon" name="add" size="12" @click="append_type_event(data)"></icon>
<icon class="icon" name="edit" size="12" @click="edit_type_event(data)"></icon>
<icon class="icon" name="del" size="12" @click="remove_type_event(node, data)"></icon>
<div v-if="data.id" class="flex-row gap-10 cr-9 category-oprate c-pointer">
<div v-if="data.pid == 0" @click.stop="append_type_event(data)">
<icon class="icon" name="add" size="12"></icon>
</div>
<div @click.stop="edit_type_event(data)">
<icon class="icon" name="edit" size="12"></icon>
</div>
<div @click.stop="remove_type_event(node, data)">
<icon class="icon" name="del" size="12"></icon>
</div>
</div>
</div>
</template>
@ -47,7 +53,7 @@
</div>
</div>
<div class="right-search">
<el-input v-model="search_name" :placeholder="'请输入' + upload_type_name + '名称'" @input="get_list">
<el-input v-model="search_name" :placeholder="'请输入' + upload_type_name + '名称'" @input="get_attachment_list('1')">
<template #suffix>
<icon name="search" size="18"></icon>
</template>
@ -57,7 +63,7 @@
<div class="img-content pr">
<!-- 574px -->
<el-scrollbar height="440px">
<div class="flex-row flex-wrap align-c gap-y-15 gap-x-10 pa-10">
<div v-if="upload_list.length > 0" class="flex-row flex-wrap align-c gap-y-15 gap-x-10 pa-10">
<div v-for="(item, index) in upload_list" :key="index" class="item" @click="check_img_event(item)">
<el-badge :value="view_list_value.findIndex((i) => i.id === item.id) == -1 ? '' : view_list_value.findIndex((i) => i.id === item.id) + 1" class="badge flex-col gap-5 w" :hidden="view_list_value.findIndex((i) => i.id === item.id) == -1">
<div class="item-content re br-f5 radius">
@ -100,7 +106,7 @@
</div>
<div class="text-line-1 name">
<template v-if="edit_index !== -1 && edit_index === index">
<el-input v-model="item.original" type="text" placeholder="请输入内容" size="small" @change="edit_input_change" @blur="edit_input_blur" />
<el-input v-model="item.original" type="text" placeholder="请输入内容" size="small" @change="edit_input_change" />
</template>
<template v-else>
<div class="ptb-1 plr-7">
@ -111,6 +117,9 @@
</el-badge>
</div>
</div>
<div v-else>
<no-data height="440"></no-data>
</div>
</el-scrollbar>
<div v-if="preview_switch_video && upload_type == 'video'">
<div class="middle clickable-area" :class="preview_url ? '' : 'hide'">
@ -120,7 +129,7 @@
</div>
</div>
<div class="mt-10 flex-row jc-e">
<el-pagination :current-page="page" :page-size="21" :pager-count="5" layout="prev, pager, next" :total="data_total" @current-change="get_list" />
<el-pagination :current-page="page" :page-size="21" :pager-count="5" layout="prev, pager, next" :total="data_total" @current-change="current_page_change" />
</div>
</div>
</div>
@ -176,7 +185,6 @@
<form-upload-category v-model="upload_category_model_visible" :value="upload_category_model" :type="upload_category_type" :category-id="upload_category_id" :category-pid="upload_category_pid" @confirm="upload_category_confirm"></form-upload-category>
</template>
<script lang="ts" setup>
import { get_math } from '@/utils/index';
import UploadAPI, { Tree } from '@/api/upload';
import { uploadrStore } from '@/store';
const upload_store = uploadrStore();
@ -241,6 +249,7 @@ watch(
(val) => {
if (val) {
type_data.value = upload_store.category;
get_attachment_list();
}
}
);
@ -311,127 +320,11 @@ const upload_type_name = computed(() => {
const upload_type_change = (type: any) => {
view_list_value.value = [];
};
//
const search_name = ref('');
//
// const page_total = ref(0);
//
const page = ref(1);
//
const data_total = ref(0);
//
const upload_list = ref<uploadList[]>([
{ id: 1, url: '/src/assets/images/layout/main/phone.png', original: '头像1', title: '头像1', ext: '.png', type: 'img' },
{ id: 2, url: '/src/assets/images/components/model-user-info/avatar.png', original: '头像2', ext: '.jpeg', type: 'img' },
{ id: 3, url: '/src/assets/images/components/model-hot/test-1.png', original: '头像3', title: '头像3', ext: '.png', type: 'img' },
{ id: 4, url: '/src/assets/images/components/model-hot/test-2.png', original: '头像4', ext: '.jpeg', type: 'img' },
{ id: 5, url: '/src/assets/movie.mp4', original: '头像5', title: '头像5', ext: '.mp4', type: 'video' },
{ id: 6, url: '/src/assets/movie.mp4', original: '头像6', title: '头像6', ext: '.docx', type: '.docx' },
]);
const check_img_ids = ref('');
//
const check_img_event = (item: any) => {
const item_id = item.id;
const index = view_list_value.value.findIndex((item: any) => item.id === item_id);
if (index !== -1) {
view_list_value.value.splice(index, 1);
} else {
if (is_replace.value) {
view_list_value.value = [item];
} else {
if (props.limit == 1) {
view_list_value.value = [item];
} else {
view_list_value.value.push(item);
}
}
}
check_img_ids.value = view_list_value.value.map((item: any) => item.id).join(',');
};
//
const preview_switch_img = ref(false);
const preview_switch_video = ref(false);
//
const preview_url = ref('');
const edit_index = ref(-1);
//
onMounted(() => {
document.addEventListener('click', video_show);
});
//
onUnmounted(() => {
document.removeEventListener('click', video_show);
});
//
const video_show = (event: any) => {
if (!preview_switch_video.value) return;
if (!event.target.closest('.clickable-area')) {
preview_switch_video.value = false;
preview_url.value = '';
}
};
// //
const edit_event = (item: any, index: number) => {
edit_index.value = index;
};
//
const edit_input_change = (val: string) => {
edit_index.value = -1;
};
//
const edit_input_blur = () => {
edit_index.value = -1;
};
// /
const preview_event = (item: any, index: number) => {
preview_url.value = item.url;
if (upload_type.value == 'img') {
preview_switch_img.value = true;
} else if (upload_type.value == 'video') {
preview_switch_video.value = true;
}
};
//
const preview_close = () => {
preview_switch_img.value = false;
};
// //
const del_event = (item: uploadList) => {
app?.appContext.config.globalProperties.$common.message_box('删除后不可恢复,确定继续吗?', 'warning').then(() => {
ElMessage({
type: 'success',
message: '删除成功!',
});
//
});
};
//
const upload_model_open = () => {
upload_model_visible.value = true;
};
//
const mult_del_event = () => {
app?.appContext.config.globalProperties.$common.message_box('删除后不可恢复,确定继续吗?', 'warning').then(() => {
ElMessage({
type: 'success',
message: '删除成功!',
});
// console.log(' = ', view_list_value.value);
//
});
};
//
const search_data = ref({
page: page.value,
type: '',
name: search_name.value,
});
//
const get_list = () => {
console.log('查询接口', search_data);
};
//#region ----------------------------------------------------------start
const treeRef = ref();
const defaultProps = {
@ -448,18 +341,20 @@ const filter_node = (value: string, data: any): boolean => {
return data.name.indexOf(value) !== -1;
};
const type_data = ref<Tree[]>([]);
onMounted(() => {
if (!upload_store.is_category) {
upload_store.set_is_category(true);
get_tree();
} else {
type_data.value = upload_store.category;
}
});
//
const get_tree = () => {
UploadAPI.getTree().then((res) => {
type_data.value = res.data.category_list;
const all_tree = {
id: '',
pid: '',
name: '全部',
path: '',
is_enable: 1,
sort: '',
};
// all_treeres.data.category_listtype_data.value,all_tree
type_data.value = [all_tree, ...res.data.category_list];
upload_store.set_category(type_data.value);
});
};
@ -489,10 +384,13 @@ const add_type = () => {
const upload_category_confirm = () => {
get_tree();
};
const category_id = ref('');
//
const tree_node_event = (data: any) => {
// search_filter.value = data.id;
get_list();
//
// if (data.is_enable == 0) return;
category_id.value = data.id;
get_attachment_list();
};
const upload_category_id = ref<number | string>('');
const upload_category_pid = ref<number | string>('');
@ -528,6 +426,130 @@ const remove_type_event = (node: any, data: Tree) => {
};
//#endregion ----------------------------------------------------------end
//#region ----------------------------------------------------------start
//
// const page_total = ref(0);
//
const page = ref(1);
//
const data_total = ref(0);
//
const search_name = ref('');
//
const upload_list = ref<uploadList[]>([]);
//
const get_attachment_list = (type?: string) => {
const new_data = {
page: type ? 1 : page.value,
type: upload_type.value == 'img' ? 'image' : upload_type.value == 'video' ? 'video' : upload_type.value == 'file' ? 'file' : '',
keywords: search_name.value,
category_id: category_id.value,
};
UploadAPI.getAttachmentList(new_data).then((res) => {
const data = res.data;
data_total.value = data.data_total;
upload_list.value = data.data_list;
});
};
//
const current_page_change = (val: number) => {
page.value = val;
get_attachment_list();
};
const check_img_ids = ref('');
//
const check_img_event = (item: any) => {
const item_id = item.id;
const index = view_list_value.value.findIndex((item: any) => item.id === item_id);
if (index !== -1) {
view_list_value.value.splice(index, 1);
} else {
if (is_replace.value) {
view_list_value.value = [item];
} else {
if (props.limit == 1) {
view_list_value.value = [item];
} else {
view_list_value.value.push(item);
}
}
}
check_img_ids.value = view_list_value.value.map((item: any) => item.id).join(',');
};
//
const preview_switch_img = ref(false);
const preview_switch_video = ref(false);
//
const preview_url = ref('');
//
const video_show = (event: any) => {
if (!preview_switch_video.value) return;
if (!event.target.closest('.clickable-area')) {
preview_switch_video.value = false;
preview_url.value = '';
}
};
// /
const preview_event = (item: any, index: number) => {
preview_url.value = item.url;
if (upload_type.value == 'img') {
preview_switch_img.value = true;
} else if (upload_type.value == 'video') {
preview_switch_video.value = true;
}
};
//
const preview_close = () => {
preview_switch_img.value = false;
};
const edit_index = ref(-1);
const edit_id = ref('');
// //
const edit_event = (item: any, index: number) => {
edit_index.value = index;
edit_id.value = item.id;
};
//
const edit_input_change = (val: string) => {
edit_index.value = -1;
UploadAPI.saveAttachmentName({ id: edit_id.value, original: val }).then((res) => {
ElMessage.success('修改成功!');
});
};
// //
const del_event = (item: uploadList) => {
app?.appContext.config.globalProperties.$common.message_box('删除后不可恢复,确定继续吗?', 'warning').then(() => {
//
UploadAPI.delAttachment({ ids: item.id }).then((res) => {
ElMessage.success('删除成功!');
//
get_attachment_list();
});
});
};
//
const mult_del_event = () => {
if (check_img_ids.value) {
app?.appContext.config.globalProperties.$common.message_box('删除后不可恢复,确定继续吗?', 'warning').then(() => {
//
UploadAPI.delAttachment({ ids: check_img_ids.value }).then((res) => {
ElMessage.success('删除成功!');
//
get_attachment_list();
});
});
} else {
ElMessage.warning('请先选择图片!');
}
};
//#endregion ----------------------------------------------------------end
//
const confirm_event = () => {
dialog_visible.value = false;
@ -603,6 +625,20 @@ const close_upload_model = (data: any) => {
}
};
//#endregion -----------------------------------------------end
onMounted(() => {
//
document.addEventListener('click', video_show);
if (!upload_store.is_upload_api) {
upload_store.set_is_upload_api(true);
get_tree();
} else {
type_data.value = upload_store.category;
}
});
onUnmounted(() => {
//
document.removeEventListener('click', video_show);
});
</script>
<style lang="scss" scoped>
@import 'index.scss';

View File

@ -17,7 +17,7 @@
</el-form-item>
<el-form-item label="上传至分组" prop="group">
<div class="form-item-width">
<el-cascader v-model="form.group" class="w" :options="classify" placeholder="请选择" :show-all-levels="false" @change="group_change"></el-cascader>
<el-cascader v-model="form.group" class="w" :options="cascader_data" placeholder="请选择" :show-all-levels="false" @change="group_change"></el-cascader>
</div>
</el-form-item>
<template v-if="form.type == 'loc'">
@ -125,8 +125,11 @@
</el-dialog>
</template>
<script lang="ts" setup>
import UploadAPI, { Tree } from '@/api/upload';
import { uploadrStore } from '@/store';
const upload_store = uploadrStore();
import type { UploadFile, UploadFiles, UploadUserFile } from 'element-plus';
import { annex_size_to_unit, ext_name, get_math } from '@/utils';
import { annex_size_to_unit, ext_name } from '@/utils';
/**
* @description: 图片执行上传弹窗
* @param close{String} 默认值
@ -151,8 +154,6 @@ const props = defineProps({
},
});
const dialogVisible = defineModel({ type: Boolean, default: false });
// const v_model = defineModel({ type: Array, default: [] });
// const dialogVisible = ref(false);
//
const upload_type = ref(props.type);
// name
@ -206,49 +207,17 @@ const group_change = (val: any) => {
}
};
// //
const classify = [
{
value: 'resource',
label: 'Resource',
},
{
value: 'resource',
label: 'Resource',
children: [
{
value: 'axure',
label: 'Axure Components',
},
],
},
{
value: 'guide',
label: 'Guide',
children: [
{
value: 'disciplines',
label: 'Disciplines',
children: [
{
value: 'consistency',
label: 'Consistency',
},
],
},
{
value: 'navigation',
label: 'Navigation',
children: [
{
value: 'side nav',
label: 'Side Navigation',
},
],
},
],
},
];
// 使 // //
const cascader_data = computed(() => {
return upload_store.category.map((tree: Tree) => ({
value: tree.id,
label: tree.name,
children: tree.items?.map((item: Tree) => ({
value: item.id,
label: item.name,
})),
}));
});
//#region -----------------------------------------------start

View File

@ -25,7 +25,7 @@
<div v-if="!isEmpty(diy_data)" class="flex-row flex-wrap gap-10">
<div v-for="(item, index) in diy_data" :key="index" class="item flex jc-sb align-c size-14 cr-3" :class="{ 'item-active': item.show_tabs }" @click="on_choose(index, item.show_tabs)">{{ item.name }}<icon name="close" color="3" size="10" class="c-pointer" @click="del(index)"></icon></div>
</div>
<NoData v-else :img-width="10"></NoData>
<no-data v-else></no-data>
</div>
</card-container>
</div>
@ -249,27 +249,31 @@ const drag_area_height = computed(() => center_height.value + 'px');
const draggable_container = ref(true);
let data = reactive<diy_content[]>([]);
watch(() => center_height.value, () => {
data = diy_data.value;
// DOM
draggable_container.value = false;
nextTick(() => {
// DOM
draggable_container.value = true;
diy_data.value = data.map((item) => ({
...item,
location: {
x: item.location.x,
y: item.location.staging_y,
staging_y: item.location.staging_y,
},
com_data: {
...item.com_data,
com_height: item.com_data.staging_height,
}
}));
});
},{ immediate: true, deep: true });
watch(
() => center_height.value,
() => {
data = diy_data.value;
// DOM
draggable_container.value = false;
nextTick(() => {
// DOM
draggable_container.value = true;
diy_data.value = data.map((item) => ({
...item,
location: {
x: item.location.x,
y: item.location.staging_y,
staging_y: item.location.staging_y,
},
com_data: {
...item.com_data,
com_height: item.com_data.staging_height,
},
}));
});
},
{ immediate: true, deep: true }
);
//#endregion
//#region
let draggedItem = ref<any>({});
@ -384,7 +388,8 @@ defineExpose({
overflow: hidden;
:deep(.el-collapse) {
border: 0;
.el-collapse-item__wrap, .el-collapse-item__header {
.el-collapse-item__wrap,
.el-collapse-item__header {
border: 0;
}
.el-collapse-item__content {

View File

@ -26,7 +26,7 @@
<model-lines-style :key="key" v-model:height="center_height" :value="diy_data"></model-lines-style>
</template>
<template v-else>
<NoData :img-width="10"></NoData>
<no-data></no-data>
</template>
</div>
</div>

View File

@ -2,24 +2,24 @@ import { ref, computed } from 'vue';
import { defineStore } from 'pinia';
export const uploadrStore = defineStore('upload', () => {
// 上传是否需要调接口判断
const is_upload_api = ref(false);
// 上传分类列表
const category = ref<any[]>([]);
// 上传分类是否有数据的判断
const is_category = ref(false);
// 存储上传分类列表
function set_category(data: any[]) {
const set_category = (data: any[]) => {
category.value = data;
is_category.value = true;
}
is_upload_api.value = true;
};
// 如果为false 则转为true
function set_is_category(bool: boolean) {
is_category.value = bool;
}
const set_is_upload_api = (bool: boolean) => {
is_upload_api.value = bool;
};
return {
category,
is_category,
is_upload_api,
set_category,
set_is_category,
set_is_upload_api,
};
});