Browse Source

feat: 导入、导出、删除

text-draggable
xuesinan 3 years ago
parent
commit
e251753eac
  1. 46
      package-lock.json
  2. 2
      package.json
  3. 27
      src/apis/index.js
  4. 59
      src/components/tall/center/nested.vue
  5. 124
      src/components/tall/left/Index.vue
  6. 240
      src/components/tall/left/Projects.vue
  7. 19
      yarn.lock

46
package-lock.json

@ -19,7 +19,9 @@
"vite-plugin-compression": "^0.3.5",
"vite-plugin-windicss": "^1.4.11",
"vue": "^3.2.16",
"vue-draggable-next": "^2.1.1",
"vue-router": "^4.0.12",
"vuedraggable": "^4.1.0",
"vuex": "^4.0.2",
"windicss": "^3.1.9"
},
@ -7829,6 +7831,11 @@
"node": ">=10"
}
},
"node_modules/sortablejs": {
"version": "1.14.0",
"resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
@ -8819,6 +8826,15 @@
"@vue/shared": "3.2.20"
}
},
"node_modules/vue-draggable-next": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz",
"integrity": "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA==",
"peerDependencies": {
"sortablejs": "^1.14.0",
"vue": "^3.2.2"
}
},
"node_modules/vue-eslint-parser": {
"version": "7.11.0",
"resolved": "https://registry.npmmirror.com/vue-eslint-parser/download/vue-eslint-parser-7.11.0.tgz?cache=0&sync_timestamp=1634602895439&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.11.0.tgz",
@ -8898,6 +8914,17 @@
"vue": "^3.0.0"
}
},
"node_modules/vuedraggable": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
"dependencies": {
"sortablejs": "1.14.0"
},
"peerDependencies": {
"vue": "^3.0.1"
}
},
"node_modules/vuex": {
"version": "4.0.2",
"resolved": "https://registry.nlark.com/vuex/download/vuex-4.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvuex%2Fdownload%2Fvuex-4.0.2.tgz",
@ -15196,6 +15223,11 @@
"is-fullwidth-code-point": "^3.0.0"
}
},
"sortablejs": {
"version": "1.14.0",
"resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
@ -15946,6 +15978,12 @@
"@vue/shared": "3.2.20"
}
},
"vue-draggable-next": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz",
"integrity": "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA==",
"requires": {}
},
"vue-eslint-parser": {
"version": "7.11.0",
"resolved": "https://registry.npmmirror.com/vue-eslint-parser/download/vue-eslint-parser-7.11.0.tgz?cache=0&sync_timestamp=1634602895439&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.11.0.tgz",
@ -16002,6 +16040,14 @@
"is-plain-object": "3.0.1"
}
},
"vuedraggable": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
"requires": {
"sortablejs": "1.14.0"
}
},
"vuex": {
"version": "4.0.2",
"resolved": "https://registry.nlark.com/vuex/download/vuex-4.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvuex%2Fdownload%2Fvuex-4.0.2.tgz",

2
package.json

@ -25,7 +25,9 @@
"vite-plugin-compression": "^0.3.5",
"vite-plugin-windicss": "^1.4.11",
"vue": "^3.2.16",
"vue-draggable-next": "^2.1.1",
"vue-router": "^4.0.12",
"vuedraggable": "^4.1.0",
"vuex": "^4.0.2",
"windicss": "^3.1.9"
},

27
src/apis/index.js

@ -49,6 +49,12 @@ export const getConfigInfo = params => http.post(`${apiUrl}/ptostall/business/by
// 获取项目列表
export const getProjects = (startTime, endTime) => http.post(`${tall}/project/query`, { param: { startTime, endTime } });
// 项目排序
export const setProjectSort = params => http.post(`${tall}/project/drag`, params);
// 服务列表
export const getBusinessList = params => http.post(`${tall}/business/import/query`, { params });
// 根据id获取项目信息
export const findProjectById = (projectId, url) => http.post(`${url}/tall/project/findProjectById`, { param: { projectId } });
@ -122,14 +128,19 @@ export const getFinanceByTask = (params, url) => http.post(`${url}/finance/getBy
* 导入wbs
* @param {object} e
*/
export const importWbs = async e => {
const file = e.target.files[0];
const param = new FormData();
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const result = await http.post(`${experiment}/wbs`, param, config);
return result;
};
export const importWbs = (url, formData, config, parentId) => http.post(`${url}/tall/project/wbs?parentId=${parentId}`, formData, config);
// 导出
export const exportWbs = (params, url) => http.post(`${url}/tall/project/exportWbs`, params);
// export const importWbs = async e => {
// const file = e.target.files[0];
// const param = new FormData();
// param.append('file', file);
// const config = { headers: { 'Content-Type': 'multipart/form-data' } };
// const result = await http.post(`${experiment}/wbs`, param, config);
// return result;
// };
// 上传文件
export const uploadImg = `${baseUrl}/filedeal/file/upload/multiple`;

59
src/components/tall/center/nested.vue

@ -0,0 +1,59 @@
<template>
<draggable class="dragArea" tag="ul" :list="proList" :group="{ name: 'g1' }" item-key="name" :move="checkMove" @end="onEnd">
<template #item="{ element }">
<li>
<p :data-id="element.id">{{ element.name }}</p>
<nested :lists="element.sonProjectList || []" @changeData="handleChangeData" />
</li>
</template>
</draggable>
</template>
<script>
import { defineComponent, ref } from 'vue';
import draggable from 'vuedraggable';
export default defineComponent({
name: 'nested',
props: {
lists: {
type: Array,
default: () => [],
},
},
components: { draggable },
emit: ['changeData'],
setup(props, context) {
const proList = ref(props.lists);
const moveProjectId = ref('');
const businessCode = ref('');
const checkMove = e => {
moveProjectId.value = e.draggedContext.element.id;
businessCode.value = e.draggedContext.element.businessCode;
};
const onEnd = e => {
console.log('Check', e, proList.value);
const param = {
moveProjectId: moveProjectId.value,
businessCode: businessCode.value,
};
context.emit('changeData', param);
};
const handleChangeData = data => {
context.emit('changeData', data);
};
return { proList, checkMove, onEnd, handleChangeData };
},
});
</script>
<style scoped>
.dragArea {
min-height: 5px;
/* outline: 1px dashed; */
}
</style>

124
src/components/tall/left/Index.vue

@ -2,68 +2,88 @@
<div class="relative">
<Calendar @changeTime="changeTime" />
<PlusCircleFilled class="upload-btn absolute cursor-pointer" :style="{ fontSize: 42 + 'px', color: '#1890FF' }" @click="showModal" />
<PlusCircleFilled class="upload-btn absolute cursor-pointer" :style="{ fontSize: 42 + 'px', color: '#1890FF' }" @click="showDrawer" />
<a-modal v-model:visible="visible" title="新建课题" @ok="handleOk">
<p>是否新建课题</p>
</a-modal>
<a-drawer v-model:visible="visible" class="custom-class" :closable="false" placement="right">
<div class="business-box">
<input class="import-project hidden" type="file" @change="toUpload" />
<div class="business-wrap cursor-pointer" v-for="(item, index) in list" :key="index">
<div class="business-info">
<div class="name" @click="importProject(item)">{{ item.name }}</div>
</div>
<div class="mwbs-list" v-if="item.mwbsList && item.mwbsList.length > 0">
<div class="mwbs-item" v-for="(val, key) in item.mwbsList" :key="key">
<input type="file" @click="toUpload(val.url)" />
<div class="name">{{ val.projectName }}</div>
</div>
</div>
</div>
</div>
</a-drawer>
<Projects />
<!-- ref="projectsRef" -->
</div>
</template>
<script setup>
import { ref } from 'vue';
import { ref, computed } from 'vue';
import { useStore } from 'vuex';
// import dayjs from 'dayjs';
import { PlusCircleFilled } from '@ant-design/icons-vue';
// import { create } from 'apis';
// import { message } from 'ant-design-vue';
// import Calendar from './Calendar.vue';
// import Projects from './Projects.vue';
// import { importWbs } from 'apis';
import { getBusinessList, importWbs } from 'apis';
import { message } from 'ant-design-vue';
const store = useStore();
const visible = ref(false);
// const projectsRef = ref(null);
const showModal = () => {
const list = ref([]); //
const refreshProjects = computed(() => store.state.layout.refreshProjects);
const currUrl = ref(null);
getList();
const showDrawer = () => {
visible.value = true;
};
const handleOk = async () => {
//
async function getList() {
try {
const res = await getBusinessList();
list.value = res;
} catch (error) {
message.info(error);
}
}
//
async function importProject(item) {
visible.value = false;
// await createExperiment();
};
currUrl.value = item.url;
document.querySelector('.import-project').click();
}
//
// async function createExperiment() {
// try {
// const data = await create();
// const obj = {
// id: data.projectId,
// name: data.projectName,
// };
// store.commit('projects/setProject', obj);
// // store.commit('task/setTaskDetail', null);
// store.commit('layout/setRefreshProjects');
// return data;
// } catch (error) {
// message.info(error);
// throw new Error(error);
// }
// }
async function toUpload(e) {
try {
const file = e.target.files[0];
const param = new FormData();
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const res = await importWbs(currUrl.value, param, config, '');
store.commit('layout/setRefreshProjects', !refreshProjects.value);
} catch (error) {
message.info(error || '导入失败');
}
}
function changeTime(data) {
store.commit('layout/setSelectTime', data);
}
</script>
<script>
export default { name: 'LeftIndex' };
</script>
<style scoped>
.upload-btn {
left: 250px;
@ -111,4 +131,32 @@ export default { name: 'LeftIndex' };
border-radius: 6px;
font-size: 16px;
}
.business-wrap {
width: 100%;
box-sizing: border-box;
}
.business-wrap .business-info,
.business-wrap .mwbs-item {
padding: 10px;
border-bottom: 1px solid #eeeeee;
}
.business-wrap .name {
line-height: 36px;
}
.business-wrap .desc {
font-size: 12px;
color: #999;
}
.business-wrap .mwbs-list {
padding-left: 16px;
}
.business-wrap .mwbs-list .mwbs-item:last-child {
border-bottom: none;
}
</style>

240
src/components/tall/left/Projects.vue

@ -2,61 +2,95 @@
<a-divider />
<div class="list-flex">
<div class="item-box" v-for="(item, index) in projects" :key="index">
<div class="one-level h-70 cursor-pointer flex items-center" @click="toDetail(item)">
<div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': item.businessCode !== 'ZERO' }">
<div class="name truncate">{{ item.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
<div class="one-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(item)">导入</p>
<p class="cursor-pointer" @click="exportProject(item.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(item)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="w-full flex items-center justify-between" @click="toDetail(item)">
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': item.businessCode !== 'ZERO' }">
<div class="name truncate">{{ item.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
</div>
<div class="time" v-if="item.businessCode !== 'ZERO'">
{{ dayjs(Number(item.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(item.endTime)).format('MM-DD HH:mm') }}
<div class="time" v-if="item.businessCode !== 'ZERO'">
{{ dayjs(Number(item.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(item.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
</div>
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="item.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(item)">
工作台
</a-button>
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="item.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(item)">
工作台
</a-button>
<RightOutlined v-if="!item.show" @click="changeShow(item)" />
<DownOutlined v-else @click="changeShow(item)" />
<RightOutlined v-if="!item.show" @click="changeShow(item)" />
<DownOutlined v-else @click="changeShow(item)" />
</div>
</div>
</div>
<div class="two-box" v-if="item.show">
<div class="two-flex" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-level h-70 cursor-pointer flex items-center" @click="toDetail(sonItem)">
<div class="icon" @click.stop="showActionCard(sonItem)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p>
<p class="cursor-pointer" @click="exportProject(sonItem.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(sonItem)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(sonItem)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
</div>
<div class="time">
{{ dayjs(Number(sonItem.startTime)).format('MM-DD HH:mm') }} {{ dayjs(Number(sonItem.endTime)).format('MM-DD HH:mm') }}
<div class="time">
{{ dayjs(Number(sonItem.startTime)).format('MM-DD HH:mm') }} {{ dayjs(Number(sonItem.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!sonItem.show" @click="changeShow(sonItem)" />
<DownOutlined v-else @click="changeShow(sonItem)" />
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!sonItem.show" @click="changeShow(sonItem)" />
<DownOutlined v-else @click="changeShow(sonItem)" />
</div>
</div>
</div>
</div>
</div>
</div>
<input class="import-wbs hidden" type="file" @change="toImport" />
<a-modal v-model:visible="importVisible" title="导入" @ok="handleImport">
<p>确定要导入到{{ importParent }}</p>
</a-modal>
<a-modal v-model:visible="visible" title="删除" @ok="handleOk">
<p>确定要删除吗</p>
</a-modal>
<nested v-if="projects.length > 0" :lists="projects" @changeData="handleChangeData"></nested>
</div>
</template>
@ -65,13 +99,19 @@ import { ref, watch, computed } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import dayjs from 'dayjs';
import { getProjects, delProject } from 'apis';
import { getProjects, delProject, setProjectSort, exportWbs, importWbs } from 'apis';
import { RightOutlined, DownOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import draggable from 'vuedraggable';
import nested from 'components/tall/Center/nested.vue';
const store = useStore();
const router = useRouter();
const visible = ref(false); //
const importVisible = ref(false); //
const importParent = ref(null); //
const importParentId = ref(null); // ID
const currUrl = ref(null); // url
const deleteId = ref(null); // id
const sessionProject = sessionStorage.getItem('project'); //
const projectInfo = computed(() => store.state.projects.project); //
@ -101,12 +141,6 @@ watch([startTime, endTime, refreshProjects], () => {
getProjectsList();
});
//
const showActionCard = item => {
visible.value = true;
deleteId.value = item.id;
};
//
async function getProjectsList() {
try {
@ -141,7 +175,44 @@ function changeShow(item) {
item.show = !item.show;
}
//
const showImportCard = item => {
importVisible.value = true;
importParent.value = item.name;
importParentId.value = item.id;
currUrl.value = item.url;
};
//
async function handleImport() {
importVisible.value = false;
await importProject();
getProjectsList();
}
//
async function importProject() {
document.querySelector('.import-wbs').click();
}
async function toImport(e) {
try {
const file = e.target.files[0];
const param = new FormData();
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const res = await importWbs(currUrl.value, param, config, importParentId.value);
} catch (error) {
message.info(error || '导入失败');
}
}
//
const showDelCard = item => {
visible.value = true;
deleteId.value = item.id;
};
//
async function handleOk() {
visible.value = false;
@ -159,12 +230,28 @@ async function deleteProject(param) {
}
}
//
async function exportProject(id) {
try {
const params = { param: { projectId: id } };
const { url } = store.state.projects.project;
const data = await exportWbs(params, url);
window.open(data.url, '_blank');
} catch (error) {
message.info(error);
throw new Error(error);
}
}
//
function clearRolesData() {
store.commit('role/setInvisibleRoles', []);
store.commit('role/setVisibleRoles', []);
store.commit('role/setRoleId', '');
}
//
function clearTasksData() {
//
store.commit('task/setPermanents', []);
@ -177,10 +264,81 @@ function clearTasksData() {
store.commit('task/setDownNextPage', 1);
}
//
function toWorkbench(item) {
toDetail(item);
store.commit('task/setTaskDetailShow', 'workbench'); //
}
//
//
//
// function checkMove(e) {
// console.log('', e, projects.value);
// moveProjectId.value = e.draggedContext.element.id;
// moveBusinessCode.value = e.draggedContext.element.businessCode;
// }
//
// function onEnd() {
// console.log('onEnd', projects.value);
// targetProjectId.value = '';
// projects.value.forEach(item => {
// if (item.sonProjectList) {
// item.sonProjectList.forEach(pro => {
// if (pro.id === moveProjectId.value) {
// targetProjectId.value = item.id;
// }
// });
// }
// });
// const param = {
// moveProjectId: moveProjectId.value,
// targetProjectId: targetProjectId.value,
// businessCode: moveBusinessCode.value,
// };
// handleSort(param);
// }
//
function handleChangeData(data) {
console.log('子组件传参', projects.value);
let targetProjectId = '';
projects.value.forEach(item => {
if (item.sonProjectList) {
item.sonProjectList.forEach(pro => {
if (pro.id === data.moveProjectId) {
targetProjectId = item.id;
}
});
}
});
const param = {
moveProjectId: data.moveProjectId,
targetProjectId,
businessCode: data.businessCode,
};
console.log('param', param);
handleSort(param);
}
//
async function handleSort(param) {
try {
const params = { param };
await setProjectSort(params);
message.info('层级关系修改成功');
} catch (error) {
message.info(error.msg || '层级关系修改失败');
throw new Error(error);
}
getProjectsList();
}
</script>
<style scoped>
@ -225,7 +383,7 @@ function toWorkbench(item) {
}
.detail {
width: calc(100% - 76px);
width: calc(100% - 46px);
}
.name {

19
yarn.lock

@ -4312,6 +4312,11 @@
"astral-regex" "^2.0.0"
"is-fullwidth-code-point" "^3.0.0"
"sortablejs@^1.14.0", "sortablejs@1.14.0":
"integrity" "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
"resolved" "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz"
"version" "1.14.0"
"source-map-js@^0.6.2":
"integrity" "sha1-C7XeYxtBz72mz7qL0FqA79/SOF4="
"resolved" "https://registry.npm.taobao.org/source-map-js/download/source-map-js-0.6.2.tgz"
@ -4872,6 +4877,11 @@
optionalDependencies:
"fsevents" "~2.3.2"
"vue-draggable-next@^2.1.1":
"integrity" "sha512-f5lmA7t6LMaL4viR7dU30zzvqJzaKQs0ymL0Jy9UDT9uiZ2tXF3MzPzEvpTH2UODXZJkT+SnjeV1fXHMsgXLYA=="
"resolved" "https://registry.npmmirror.com/vue-draggable-next/-/vue-draggable-next-2.1.1.tgz"
"version" "2.1.1"
"vue-eslint-parser@^7.10.0":
"integrity" "sha1-IUtd6pYQB/z/su5luJEjB2KNDa8="
"resolved" "https://registry.npmmirror.com/vue-eslint-parser/download/vue-eslint-parser-7.11.0.tgz?cache=0&sync_timestamp=1634602895439&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.11.0.tgz"
@ -4899,7 +4909,7 @@
dependencies:
"is-plain-object" "3.0.1"
"vue@^3.0.0", "vue@^3.0.2", "vue@^3.2.16", "vue@>=3.0.3", "vue@>=3.1.0", "vue@2 || 3", "vue@3.2.20":
"vue@^3.0.0", "vue@^3.0.1", "vue@^3.0.2", "vue@^3.2.16", "vue@^3.2.2", "vue@>=3.0.3", "vue@>=3.1.0", "vue@2 || 3", "vue@3.2.20":
"integrity" "sha1-lA+KqL8+O+eCQ8pYK61B/NRa4+Y="
"resolved" "https://registry.npmmirror.com/vue/download/vue-3.2.20.tgz?cache=0&sync_timestamp=1633712767060&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue%2Fdownload%2Fvue-3.2.20.tgz"
"version" "3.2.20"
@ -4910,6 +4920,13 @@
"@vue/server-renderer" "3.2.20"
"@vue/shared" "3.2.20"
"vuedraggable@^4.1.0":
"integrity" "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww=="
"resolved" "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz"
"version" "4.1.0"
dependencies:
"sortablejs" "1.14.0"
"vuex@^4.0.2":
"integrity" "sha1-+Jbb1b8qDpY/AMZ+m2EN50nMrMk="
"resolved" "https://registry.nlark.com/vuex/download/vuex-4.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvuex%2Fdownload%2Fvuex-4.0.2.tgz"

Loading…
Cancel
Save