update
This commit is contained in:
parent
77e94d2f3d
commit
c5265e7fc2
@ -1,4 +1,4 @@
|
||||
import request from '@/utils/request';
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 登录接口
|
||||
export const Login = data => {
|
||||
@ -6,13 +6,13 @@ export const Login = data => {
|
||||
url: '/api/login',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
// 获取登录用户信息
|
||||
export const GetUserinfo = () => {
|
||||
return request({
|
||||
url: '/api/userinfo',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import request from '@/utils/request';
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取菜单
|
||||
export const GetMenus = () => {
|
||||
return request({
|
||||
url: '/api/menus',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, reactive, toRefs, onBeforeMount } from 'vue';
|
||||
import { defineComponent, reactive, toRefs, onBeforeMount } from 'vue'
|
||||
const formatDate = (date, format) => {
|
||||
var obj = {
|
||||
'M+': date.getMonth() + 1,
|
||||
@ -222,12 +222,12 @@ const formatDate = (date, format) => {
|
||||
's+': date.getSeconds(),
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3),
|
||||
'S+': date.getMilliseconds(),
|
||||
};
|
||||
}
|
||||
if (/(y+)/i.test(format)) {
|
||||
format = format.replace(
|
||||
RegExp.$1,
|
||||
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
|
||||
);
|
||||
)
|
||||
}
|
||||
for (var k in obj) {
|
||||
if (new RegExp('(' + k + ')').test(format)) {
|
||||
@ -236,25 +236,25 @@ const formatDate = (date, format) => {
|
||||
RegExp.$1.length == 1
|
||||
? obj[k]
|
||||
: ('00' + obj[k]).substr(('' + obj[k]).length)
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
return format;
|
||||
};
|
||||
return format
|
||||
}
|
||||
const getSearchModel = search => {
|
||||
const searchModel = {};
|
||||
const searchModel = {}
|
||||
if (search && search.fields) {
|
||||
search.fields.forEach(item => {
|
||||
switch (item.type) {
|
||||
case 'checkbox':
|
||||
case 'checkbox-button':
|
||||
searchModel[item.name] = [];
|
||||
break;
|
||||
searchModel[item.name] = []
|
||||
break
|
||||
default:
|
||||
break;
|
||||
break
|
||||
}
|
||||
if (item.defaultValue !== undefined) {
|
||||
searchModel[item.name] = item.defaultValue;
|
||||
searchModel[item.name] = item.defaultValue
|
||||
// 日期范围和时间范围真实变量默认值
|
||||
if (
|
||||
(item.type === 'daterange' || item.type === 'datetimerange') &&
|
||||
@ -262,14 +262,14 @@ const getSearchModel = search => {
|
||||
Array.isArray(item.defaultValue)
|
||||
) {
|
||||
item.defaultValue.forEach((val, index) => {
|
||||
searchModel[item.trueNames[index]] = val;
|
||||
});
|
||||
searchModel[item.trueNames[index]] = val
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
return searchModel;
|
||||
};
|
||||
return searchModel
|
||||
}
|
||||
export default defineComponent({
|
||||
props: {
|
||||
// 请求数据的方法
|
||||
@ -316,43 +316,43 @@ export default defineComponent({
|
||||
// 1、如果搜索配置有transform处理函数,执行transform
|
||||
// 2、删除日期范围默认的name字段
|
||||
const optimizeFields = search => {
|
||||
const searchModel = JSON.parse(JSON.stringify(state.searchModel));
|
||||
const searchModel = JSON.parse(JSON.stringify(state.searchModel))
|
||||
if (search && search.fields) {
|
||||
search.fields.forEach(item => {
|
||||
if (!searchModel.hasOwnProperty(item.name)) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (item.transform) {
|
||||
searchModel[item.name] = item.transform(searchModel[item.name]);
|
||||
searchModel[item.name] = item.transform(searchModel[item.name])
|
||||
}
|
||||
if (
|
||||
(item.type === 'daterange' || item.type === 'datetimerange') &&
|
||||
!!item.trueNames
|
||||
) {
|
||||
delete searchModel[item.name];
|
||||
delete searchModel[item.name]
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
return searchModel;
|
||||
};
|
||||
return searchModel
|
||||
}
|
||||
|
||||
// 请求列表数据
|
||||
const getTableData = async () => {
|
||||
state.loading = true;
|
||||
const searchModel = optimizeFields(props.search);
|
||||
state.loading = true
|
||||
const searchModel = optimizeFields(props.search)
|
||||
const { data, total } = await props.request({
|
||||
pageNum: state.pageNum,
|
||||
pageSize: state.pageSize,
|
||||
...searchModel,
|
||||
});
|
||||
state.loading = false;
|
||||
state.tableData = data;
|
||||
state.total = total;
|
||||
};
|
||||
})
|
||||
state.loading = false
|
||||
state.tableData = data
|
||||
state.total = total
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
getTableData();
|
||||
});
|
||||
getTableData()
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
searchModel: getSearchModel(props.search),
|
||||
@ -366,80 +366,80 @@ export default defineComponent({
|
||||
},
|
||||
// 搜索
|
||||
handleSearch() {
|
||||
state.pageNum = 1;
|
||||
getTableData();
|
||||
state.pageNum = 1
|
||||
getTableData()
|
||||
},
|
||||
// 重置函数
|
||||
handleReset() {
|
||||
if (JSON.stringify(state.searchModel) === '{}') {
|
||||
return;
|
||||
return
|
||||
}
|
||||
state.pageNum = 1;
|
||||
state.searchModel = getSearchModel(props.search);
|
||||
getTableData();
|
||||
state.pageNum = 1
|
||||
state.searchModel = getSearchModel(props.search)
|
||||
getTableData()
|
||||
},
|
||||
// 刷新
|
||||
refresh() {
|
||||
getTableData();
|
||||
getTableData()
|
||||
},
|
||||
|
||||
// 当前页变化
|
||||
handleCurrentChange() {
|
||||
getTableData();
|
||||
getTableData()
|
||||
},
|
||||
// 改变每页size数量
|
||||
handleSizeChange() {
|
||||
state.pageNum = 1;
|
||||
getTableData();
|
||||
state.pageNum = 1
|
||||
getTableData()
|
||||
},
|
||||
// 全选
|
||||
handleSelectionChange(arr) {
|
||||
emit('selectionChange', arr);
|
||||
emit('selectionChange', arr)
|
||||
},
|
||||
// 过滤方法
|
||||
filterHandler(value, row, column) {
|
||||
const property = column['property'];
|
||||
return row[property] === value;
|
||||
const property = column['property']
|
||||
return row[property] === value
|
||||
},
|
||||
// 日期范围
|
||||
handleDateChange(date, item, format) {
|
||||
state.searchModel[item.name] = date ? formatDate(date, format) : '';
|
||||
state.searchModel[item.name] = date ? formatDate(date, format) : ''
|
||||
},
|
||||
handleRangeChange(date, item, format) {
|
||||
const arr = !!date && date.map(d => formatDate(d, format));
|
||||
state.searchModel[item.name] = arr ? arr : [];
|
||||
const arr = !!date && date.map(d => formatDate(d, format))
|
||||
state.searchModel[item.name] = arr ? arr : []
|
||||
|
||||
if (!item.trueNames) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if (arr) {
|
||||
arr.forEach((val, index) => {
|
||||
state.searchModel[item.trueNames[index]] = val;
|
||||
});
|
||||
state.searchModel[item.trueNames[index]] = val
|
||||
})
|
||||
} else {
|
||||
item.trueNames.forEach(key => {
|
||||
delete state.searchModel[key];
|
||||
});
|
||||
delete state.searchModel[key]
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
if (typeof props.pagination === 'object') {
|
||||
const { layout, pageSizes, style } = props.pagination;
|
||||
const { layout, pageSizes, style } = props.pagination
|
||||
state.paginationConfig = {
|
||||
show: true,
|
||||
layout: layout || 'total, sizes, prev, pager, next, jumper',
|
||||
pageSizes: pageSizes || [10, 20, 30, 40, 50, 100],
|
||||
style: style || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.page-box {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { defineComponent, computed } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SvgIcon',
|
||||
@ -20,10 +20,10 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const symbolId = computed(() => `#${props.prefix}-${props.name}`);
|
||||
return { symbolId };
|
||||
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
|
||||
return { symbolId }
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export { default as SvgIcon } from '@/components/SvgIcon/index.vue';
|
||||
export { default as ProTable } from '@/components/ProTable/index.vue';
|
||||
export { default as SvgIcon } from '@/components/SvgIcon/index.vue'
|
||||
export { default as ProTable } from '@/components/ProTable/index.vue'
|
||||
|
||||
@ -6,21 +6,21 @@
|
||||
</router-view>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const cacheList = computed(() => store.state.tags.cacheList);
|
||||
const key = computed(() => route.fullPath);
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const cacheList = computed(() => store.state.tags.cacheList)
|
||||
const key = computed(() => route.fullPath)
|
||||
|
||||
return {
|
||||
cacheList,
|
||||
key,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -5,18 +5,18 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { computed, defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: ['title', 'icon'],
|
||||
setup({ icon }) {
|
||||
const isElementIcon = computed(() => icon && icon.startsWith('el-icon'));
|
||||
const isElementIcon = computed(() => icon && icon.startsWith('el-icon'))
|
||||
|
||||
return {
|
||||
isElementIcon,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.icon {
|
||||
|
||||
@ -5,18 +5,18 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { defineComponent } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const router = useRouter()
|
||||
const goHome = () => {
|
||||
router.push('/');
|
||||
};
|
||||
return { goHome };
|
||||
router.push('/')
|
||||
}
|
||||
return { goHome }
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.brand {
|
||||
|
||||
@ -15,11 +15,11 @@
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import Submenu from './Submenu.vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRoute } from 'vue-router';
|
||||
import config from './config/menu.module.scss';
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import Submenu from './Submenu.vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute } from 'vue-router'
|
||||
import config from './config/menu.module.scss'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -32,20 +32,20 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
store.dispatch(
|
||||
'menu/generateMenus',
|
||||
store.state.account.userinfo && store.state.account.userinfo.role
|
||||
);
|
||||
)
|
||||
|
||||
return {
|
||||
menus: computed(() => store.state.menu.menus),
|
||||
activePath: computed(() => route.path),
|
||||
variables: computed(() => config),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// menu hover
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
</el-submenu>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import Item from './Item.vue';
|
||||
import { defineComponent } from 'vue'
|
||||
import Item from './Item.vue'
|
||||
export default defineComponent({
|
||||
name: 'Submenu',
|
||||
components: {
|
||||
@ -32,5 +32,5 @@ export default defineComponent({
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import Logo from './Logo.vue';
|
||||
import Menus from './Menus.vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import Logo from './Logo.vue'
|
||||
import Menus from './Menus.vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -21,21 +21,21 @@ export default defineComponent({
|
||||
Menus,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse);
|
||||
const device = computed(() => store.state.app.device);
|
||||
const store = useStore()
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse)
|
||||
const device = computed(() => store.state.app.device)
|
||||
|
||||
const closeSidebar = () => {
|
||||
store.commit('app/setCollapse', 1);
|
||||
};
|
||||
store.commit('app/setCollapse', 1)
|
||||
}
|
||||
|
||||
return {
|
||||
collapse,
|
||||
device,
|
||||
closeSidebar,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { onMounted, onBeforeUnmount, reactive, toRefs, nextTick } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { isAffix } from './useTags';
|
||||
import { onMounted, onBeforeUnmount, reactive, toRefs, nextTick } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { isAffix } from './useTags'
|
||||
|
||||
export const useContextMenu = tagList => {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
@ -14,89 +14,89 @@ export const useContextMenu = tagList => {
|
||||
left: 0,
|
||||
selectedTag: {},
|
||||
openMenu(tag, e) {
|
||||
state.visible = true;
|
||||
state.left = e.clientX;
|
||||
state.top = e.clientY;
|
||||
state.selectedTag = tag;
|
||||
state.visible = true
|
||||
state.left = e.clientX
|
||||
state.top = e.clientY
|
||||
state.selectedTag = tag
|
||||
},
|
||||
closeMenu() {
|
||||
state.visible = false;
|
||||
state.visible = false
|
||||
},
|
||||
refreshSelectedTag(tag) {
|
||||
store.dispatch('tags/delCacheList', tag);
|
||||
const { fullPath } = tag;
|
||||
store.dispatch('tags/delCacheList', tag)
|
||||
const { fullPath } = tag
|
||||
nextTick(() => {
|
||||
router.replace({
|
||||
path: '/redirect' + fullPath,
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
},
|
||||
closeTag(tag) {
|
||||
if (isAffix(tag)) return;
|
||||
if (isAffix(tag)) return
|
||||
|
||||
const closedTagIndex = tagList.value.findIndex(
|
||||
item => item.fullPath === tag.fullPath
|
||||
);
|
||||
store.dispatch('tags/delTag', tag);
|
||||
)
|
||||
store.dispatch('tags/delTag', tag)
|
||||
if (isActive(tag)) {
|
||||
toLastTag(closedTagIndex - 1);
|
||||
toLastTag(closedTagIndex - 1)
|
||||
}
|
||||
},
|
||||
closeOtherTags() {
|
||||
store.dispatch('tags/delOtherTags', state.selectedTag);
|
||||
router.push(state.selectedTag);
|
||||
store.dispatch('tags/delOtherTags', state.selectedTag)
|
||||
router.push(state.selectedTag)
|
||||
},
|
||||
closeLeftTags() {
|
||||
state.closeSomeTags('left');
|
||||
state.closeSomeTags('left')
|
||||
},
|
||||
closeRightTags() {
|
||||
state.closeSomeTags('right');
|
||||
state.closeSomeTags('right')
|
||||
},
|
||||
closeSomeTags(direction) {
|
||||
const index = tagList.value.findIndex(
|
||||
item => item.fullPath === state.selectedTag.fullPath
|
||||
);
|
||||
)
|
||||
|
||||
if (
|
||||
(direction === 'left' && index <= 0) ||
|
||||
(direction === 'right' && index >= tagList.value.length - 1)
|
||||
) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const needToClose =
|
||||
direction === 'left'
|
||||
? tagList.value.slice(0, index)
|
||||
: tagList.value.slice(index + 1);
|
||||
store.dispatch('tags/delSomeTags', needToClose);
|
||||
router.push(state.selectedTag);
|
||||
: tagList.value.slice(index + 1)
|
||||
store.dispatch('tags/delSomeTags', needToClose)
|
||||
router.push(state.selectedTag)
|
||||
},
|
||||
closeAllTags() {
|
||||
store.dispatch('tags/delAllTags');
|
||||
router.push('/');
|
||||
store.dispatch('tags/delAllTags')
|
||||
router.push('/')
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const isActive = tag => {
|
||||
return tag.fullPath === route.fullPath;
|
||||
};
|
||||
return tag.fullPath === route.fullPath
|
||||
}
|
||||
|
||||
const toLastTag = lastTagIndex => {
|
||||
const lastTag = tagList.value[lastTagIndex];
|
||||
const lastTag = tagList.value[lastTagIndex]
|
||||
if (lastTag) {
|
||||
router.push(lastTag.fullPath);
|
||||
router.push(lastTag.fullPath)
|
||||
} else {
|
||||
router.push('/');
|
||||
router.push('/')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('click', state.closeMenu);
|
||||
});
|
||||
document.addEventListener('click', state.closeMenu)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('click', state.closeMenu);
|
||||
});
|
||||
document.removeEventListener('click', state.closeMenu)
|
||||
})
|
||||
|
||||
return toRefs(state);
|
||||
};
|
||||
return toRefs(state)
|
||||
}
|
||||
|
||||
@ -1,41 +1,41 @@
|
||||
import { ref } from 'vue';
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useScrollbar = tagsItem => {
|
||||
const scrollContainer = ref(null);
|
||||
const scrollContainer = ref(null)
|
||||
|
||||
const handleScroll = e => {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY;
|
||||
scrollContainer.value.wrap.scrollLeft -= eventDelta / 4;
|
||||
};
|
||||
const eventDelta = e.wheelDelta || -e.deltaY
|
||||
scrollContainer.value.wrap.scrollLeft -= eventDelta / 4
|
||||
}
|
||||
|
||||
const moveToTarget = currentTag => {
|
||||
const containerWidth = scrollContainer.value.scrollbar.offsetWidth;
|
||||
const scrollWrapper = scrollContainer.value.wrap;
|
||||
const tagList = tagsItem.value;
|
||||
const containerWidth = scrollContainer.value.scrollbar.offsetWidth
|
||||
const scrollWrapper = scrollContainer.value.wrap
|
||||
const tagList = tagsItem.value
|
||||
|
||||
let firstTag = null;
|
||||
let lastTag = null;
|
||||
let firstTag = null
|
||||
let lastTag = null
|
||||
|
||||
if (tagList.length > 0) {
|
||||
firstTag = tagList[0];
|
||||
lastTag = tagList[tagList.length - 1];
|
||||
firstTag = tagList[0]
|
||||
lastTag = tagList[tagList.length - 1]
|
||||
}
|
||||
if (firstTag === currentTag) {
|
||||
scrollWrapper.scrollLeft = 0;
|
||||
scrollWrapper.scrollLeft = 0
|
||||
} else if (lastTag === currentTag) {
|
||||
scrollWrapper.scrollLeft = scrollWrapper.scrollWidth - containerWidth;
|
||||
scrollWrapper.scrollLeft = scrollWrapper.scrollWidth - containerWidth
|
||||
} else {
|
||||
const el = currentTag.$el.nextElementSibling;
|
||||
const el = currentTag.$el.nextElementSibling
|
||||
scrollWrapper.scrollLeft =
|
||||
el.offsetLeft + el.offsetWidth > containerWidth
|
||||
? el.offsetLeft - el.offsetWidth
|
||||
: 0;
|
||||
: 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
scrollContainer,
|
||||
handleScroll,
|
||||
moveToTarget,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,94 +1,94 @@
|
||||
import { useScrollbar } from './useScrollbar';
|
||||
import { watch, computed, ref, nextTick, onBeforeMount } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { useScrollbar } from './useScrollbar'
|
||||
import { watch, computed, ref, nextTick, onBeforeMount } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export const isAffix = tag => {
|
||||
return !!tag.meta && !!tag.meta.affix;
|
||||
};
|
||||
return !!tag.meta && !!tag.meta.affix
|
||||
}
|
||||
|
||||
export const useTags = () => {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = router.currentRoute;
|
||||
const routes = computed(() => router.getRoutes());
|
||||
const tagList = computed(() => store.state.tags.tagList);
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = router.currentRoute
|
||||
const routes = computed(() => router.getRoutes())
|
||||
const tagList = computed(() => store.state.tags.tagList)
|
||||
|
||||
const tagsItem = ref([]);
|
||||
const tagsItem = ref([])
|
||||
|
||||
const setItemRef = (i, el) => {
|
||||
tagsItem.value[i] = el;
|
||||
};
|
||||
tagsItem.value[i] = el
|
||||
}
|
||||
|
||||
const scrollbar = useScrollbar(tagsItem);
|
||||
const scrollbar = useScrollbar(tagsItem)
|
||||
|
||||
watch(
|
||||
() => tagList.value.length,
|
||||
() => {
|
||||
tagsItem.value = [];
|
||||
tagsItem.value = []
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
const filterAffixTags = routes => {
|
||||
return routes.filter(route => isAffix(route));
|
||||
};
|
||||
return routes.filter(route => isAffix(route))
|
||||
}
|
||||
|
||||
const initTags = () => {
|
||||
const affixTags = filterAffixTags(routes.value);
|
||||
const affixTags = filterAffixTags(routes.value)
|
||||
|
||||
for (const tag of affixTags) {
|
||||
if (tag.name) {
|
||||
store.dispatch('tags/addTagList', tag);
|
||||
store.dispatch('tags/addTagList', tag)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const addTag = () => {
|
||||
const tag = route.value;
|
||||
const tag = route.value
|
||||
if (!!tag.name && tag.matched[0].components.default.name === 'layout') {
|
||||
store.dispatch('tags/addTag', tag);
|
||||
store.dispatch('tags/addTag', tag)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const saveActivePosition = tag => {
|
||||
const index = tagList.value.findIndex(
|
||||
item => item.fullPath === tag.fullPath
|
||||
);
|
||||
)
|
||||
|
||||
store.dispatch('tags/saveActivePosition', Math.max(0, index));
|
||||
};
|
||||
store.dispatch('tags/saveActivePosition', Math.max(0, index))
|
||||
}
|
||||
|
||||
const moveToCurrentTag = () => {
|
||||
nextTick(() => {
|
||||
for (const tag of tagsItem.value) {
|
||||
if (!!tag && tag.to.path === route.value.path) {
|
||||
scrollbar.moveToTarget(tag);
|
||||
scrollbar.moveToTarget(tag)
|
||||
|
||||
if (tag.to.fullPath !== route.value.fullPath) {
|
||||
store.dispatch('tags/updateTagList', route.value);
|
||||
store.dispatch('tags/updateTagList', route.value)
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
initTags();
|
||||
addTag();
|
||||
moveToCurrentTag();
|
||||
});
|
||||
initTags()
|
||||
addTag()
|
||||
moveToCurrentTag()
|
||||
})
|
||||
|
||||
watch(route, (newRoute, oldRoute) => {
|
||||
saveActivePosition(oldRoute); // 保存标签的位置
|
||||
addTag();
|
||||
moveToCurrentTag();
|
||||
});
|
||||
saveActivePosition(oldRoute) // 保存标签的位置
|
||||
addTag()
|
||||
moveToCurrentTag()
|
||||
})
|
||||
|
||||
return {
|
||||
tagList,
|
||||
setItemRef,
|
||||
isAffix,
|
||||
...scrollbar,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,28 +46,28 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { useTags } from './hooks/useTags';
|
||||
import { useContextMenu } from './hooks/useContextMenu';
|
||||
import { defineComponent } from 'vue'
|
||||
import { useTags } from './hooks/useTags'
|
||||
import { useContextMenu } from './hooks/useContextMenu'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Tagsbar',
|
||||
setup() {
|
||||
const tags = useTags();
|
||||
const contextMenu = useContextMenu(tags.tagList);
|
||||
const tags = useTags()
|
||||
const contextMenu = useContextMenu(tags.tagList)
|
||||
|
||||
const onScroll = e => {
|
||||
tags.handleScroll(e);
|
||||
contextMenu.closeMenu.value();
|
||||
};
|
||||
tags.handleScroll(e)
|
||||
contextMenu.closeMenu.value()
|
||||
}
|
||||
|
||||
return {
|
||||
onScroll,
|
||||
...tags,
|
||||
...contextMenu,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -15,45 +15,45 @@
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed, ref, onBeforeMount, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { defineComponent, computed, ref, onBeforeMount, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const device = computed(() => store.state.app.device);
|
||||
const router = useRouter();
|
||||
const route = router.currentRoute; // 这里不使用useRoute获取当前路由,否则下面watch监听路由的时候会有警告
|
||||
const breadcrumbs = ref([]);
|
||||
const store = useStore()
|
||||
const device = computed(() => store.state.app.device)
|
||||
const router = useRouter()
|
||||
const route = router.currentRoute // 这里不使用useRoute获取当前路由,否则下面watch监听路由的时候会有警告
|
||||
const breadcrumbs = ref([])
|
||||
|
||||
const getBreadcrumbs = route => {
|
||||
const home = [{ path: '/', meta: { title: '首页' } }];
|
||||
const home = [{ path: '/', meta: { title: '首页' } }]
|
||||
if (route.name === 'home') {
|
||||
return home;
|
||||
return home
|
||||
} else {
|
||||
const matched = route.matched.filter(
|
||||
item => !!item.meta && !!item.meta.title
|
||||
);
|
||||
)
|
||||
|
||||
return [...home, ...matched];
|
||||
return [...home, ...matched]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
breadcrumbs.value = getBreadcrumbs(route.value);
|
||||
});
|
||||
breadcrumbs.value = getBreadcrumbs(route.value)
|
||||
})
|
||||
|
||||
watch(route, newRoute => {
|
||||
breadcrumbs.value = getBreadcrumbs(newRoute);
|
||||
});
|
||||
breadcrumbs.value = getBreadcrumbs(newRoute)
|
||||
})
|
||||
|
||||
return {
|
||||
device,
|
||||
breadcrumbs,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -6,22 +6,22 @@
|
||||
></i>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse);
|
||||
const store = useStore()
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse)
|
||||
const handleToggleMenu = () => {
|
||||
store.commit('app/setCollapse', +!collapse.value);
|
||||
};
|
||||
store.commit('app/setCollapse', +!collapse.value)
|
||||
}
|
||||
return {
|
||||
collapse,
|
||||
handleToggleMenu,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.fold-btn {
|
||||
|
||||
@ -21,26 +21,26 @@
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter } from 'vue-router'
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const userinfo = computed(() => store.state.account.userinfo);
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const userinfo = computed(() => store.state.account.userinfo)
|
||||
const logout = () => {
|
||||
store.commit('app/clearToken');
|
||||
store.commit('account/clearUserinfo');
|
||||
store.dispatch('tags/delAllTags');
|
||||
router.push('/login');
|
||||
};
|
||||
store.commit('app/clearToken')
|
||||
store.commit('account/clearUserinfo')
|
||||
store.dispatch('tags/delAllTags')
|
||||
router.push('/login')
|
||||
}
|
||||
return {
|
||||
userinfo,
|
||||
logout,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -11,12 +11,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import Logo from '@/layout/components/Sidebar/Logo.vue';
|
||||
import Hamburger from './Hamburger.vue';
|
||||
import Breadcrumbs from './Breadcrumbs.vue';
|
||||
import Userinfo from './Userinfo.vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import Logo from '@/layout/components/Sidebar/Logo.vue'
|
||||
import Hamburger from './Hamburger.vue'
|
||||
import Breadcrumbs from './Breadcrumbs.vue'
|
||||
import Userinfo from './Userinfo.vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -26,14 +26,14 @@ export default defineComponent({
|
||||
Userinfo,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const device = computed(() => store.state.app.device);
|
||||
const store = useStore()
|
||||
const device = computed(() => store.state.app.device)
|
||||
|
||||
return {
|
||||
device,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
import { onBeforeMount, onBeforeUnmount /*watch*/ } from 'vue';
|
||||
import { onBeforeMount, onBeforeUnmount /*watch*/ } from 'vue'
|
||||
// import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
const WIDTH = 768;
|
||||
const WIDTH = 768
|
||||
export const useResizeHandler = () => {
|
||||
const store = useStore();
|
||||
const store = useStore()
|
||||
// const router = useRouter();
|
||||
// const route = router.currentRoute;
|
||||
|
||||
const isMobile = () => {
|
||||
return window.innerWidth < WIDTH;
|
||||
};
|
||||
return window.innerWidth < WIDTH
|
||||
}
|
||||
|
||||
const resizeHandler = () => {
|
||||
if (isMobile()) {
|
||||
store.commit('app/setDevice', 'mobile');
|
||||
store.commit('app/setCollapse', 1);
|
||||
store.commit('app/setDevice', 'mobile')
|
||||
store.commit('app/setCollapse', 1)
|
||||
} else {
|
||||
store.commit('app/setDevice', 'desktop');
|
||||
store.commit('app/setCollapse', 0);
|
||||
store.commit('app/setDevice', 'desktop')
|
||||
store.commit('app/setCollapse', 0)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (isMobile()) {
|
||||
store.commit('app/setDevice', 'mobile');
|
||||
store.commit('app/setCollapse', 1);
|
||||
store.commit('app/setDevice', 'mobile')
|
||||
store.commit('app/setCollapse', 1)
|
||||
}
|
||||
window.addEventListener('resize', resizeHandler);
|
||||
});
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeHandler);
|
||||
});
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
})
|
||||
|
||||
// // 监听路由的时候不能使用useRoute获取路由,否则会有警告
|
||||
// watch(route, () => {
|
||||
@ -40,4 +40,4 @@ export const useResizeHandler = () => {
|
||||
// store.commit('app/setCollapse', 1)
|
||||
// }
|
||||
// })
|
||||
};
|
||||
}
|
||||
|
||||
@ -13,12 +13,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import Sidebar from './components/Sidebar/index.vue';
|
||||
import Topbar from './components/Topbar/index.vue';
|
||||
import Tagsbar from './components/Tagsbar/index.vue';
|
||||
import Content from './components/Content/index.vue';
|
||||
import { useResizeHandler } from './hooks/useResizeHandler';
|
||||
import { defineComponent } from 'vue'
|
||||
import Sidebar from './components/Sidebar/index.vue'
|
||||
import Topbar from './components/Topbar/index.vue'
|
||||
import Tagsbar from './components/Tagsbar/index.vue'
|
||||
import Content from './components/Content/index.vue'
|
||||
import { useResizeHandler } from './hooks/useResizeHandler'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layout',
|
||||
@ -29,9 +29,9 @@ export default defineComponent({
|
||||
Content,
|
||||
},
|
||||
setup() {
|
||||
useResizeHandler();
|
||||
useResizeHandler()
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
30
src/main.js
30
src/main.js
@ -1,35 +1,35 @@
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App);
|
||||
const app = createApp(App)
|
||||
|
||||
// 引入element-plus
|
||||
import ElementPlus from 'element-plus';
|
||||
import './assets/style/element-variables.scss';
|
||||
import ElementPlus from 'element-plus'
|
||||
import './assets/style/element-variables.scss'
|
||||
// 引入中文语言包
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import locale from 'element-plus/lib/locale/lang/zh-cn';
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import locale from 'element-plus/lib/locale/lang/zh-cn'
|
||||
|
||||
// 引入路由
|
||||
import router from './router';
|
||||
import router from './router'
|
||||
|
||||
// 引入store
|
||||
import store from './store';
|
||||
import store from './store'
|
||||
|
||||
// 权限控制
|
||||
import './permission';
|
||||
import './permission'
|
||||
|
||||
// 引入svg图标注册脚本
|
||||
import 'vite-plugin-svg-icons/register';
|
||||
import 'vite-plugin-svg-icons/register'
|
||||
|
||||
// 注册全局组件
|
||||
import * as Components from './global-components';
|
||||
import * as Components from './global-components'
|
||||
Object.entries(Components).forEach(([key, component]) => {
|
||||
app.component(key, component);
|
||||
});
|
||||
app.component(key, component)
|
||||
})
|
||||
|
||||
app
|
||||
.use(ElementPlus, { locale })
|
||||
.use(store)
|
||||
.use(router)
|
||||
.mount('#app');
|
||||
.mount('#app')
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import router from '@/router';
|
||||
import store from '@/store';
|
||||
import { TOKEN } from '@/store/modules/app'; // TOKEN变量名
|
||||
import router from '@/router'
|
||||
import store from '@/store'
|
||||
import { TOKEN } from '@/store/modules/app' // TOKEN变量名
|
||||
|
||||
const getPageTitle = title => {
|
||||
const appTitle = store.state.app.title;
|
||||
const appTitle = store.state.app.title
|
||||
if (title) {
|
||||
return `${title} - ${appTitle}`;
|
||||
return `${title} - ${appTitle}`
|
||||
}
|
||||
return appTitle;
|
||||
};
|
||||
return appTitle
|
||||
}
|
||||
|
||||
// 白名单,里面是路由对象的name
|
||||
const WhiteList = ['login', 'forbidden', 'server-error', 'not-found'];
|
||||
const WhiteList = ['login', 'forbidden', 'server-error', 'not-found']
|
||||
|
||||
// vue-router4的路由守卫不再是通过next放行,而是通过return返回true或false或者一个路由地址
|
||||
router.beforeEach(async to => {
|
||||
document.title = getPageTitle(!!to.meta && to.meta.title);
|
||||
document.title = getPageTitle(!!to.meta && to.meta.title)
|
||||
|
||||
if (WhiteList.includes(to.name)) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
if (!window.localStorage[TOKEN]) {
|
||||
return {
|
||||
@ -27,15 +27,15 @@ router.beforeEach(async to => {
|
||||
redirect: to.path, // redirect是指登录之后可以跳回到redirect指定的页面
|
||||
},
|
||||
replace: true,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
let userinfo = store.state.account.userinfo;
|
||||
let userinfo = store.state.account.userinfo
|
||||
if (!userinfo) {
|
||||
try {
|
||||
// 获取用户信息
|
||||
userinfo = await store.dispatch('account/getUserinfo');
|
||||
userinfo = await store.dispatch('account/getUserinfo')
|
||||
} catch (err) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
// 如果没有权限,跳转到403页面
|
||||
@ -44,7 +44,7 @@ router.beforeEach(async to => {
|
||||
!!to.meta.roles &&
|
||||
!to.meta.roles.includes(userinfo.role)
|
||||
) {
|
||||
return { path: '/403', replace: true };
|
||||
return { path: '/403', replace: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
// index.js
|
||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
import redirect from './modules/redirect';
|
||||
import error from './modules/error';
|
||||
import login from './modules/login';
|
||||
import home from './modules/home';
|
||||
import test from './modules/test';
|
||||
import redirect from './modules/redirect'
|
||||
import error from './modules/error'
|
||||
import login from './modules/login'
|
||||
import home from './modules/home'
|
||||
import test from './modules/test'
|
||||
|
||||
// 左侧菜单
|
||||
export const allMenus = [...home, ...test];
|
||||
export const allMenus = [...home, ...test]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
@ -24,11 +24,11 @@ const router = createRouter({
|
||||
],
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition;
|
||||
return savedPosition
|
||||
} else {
|
||||
return { left: 0, top: 0 };
|
||||
return { left: 0, top: 0 }
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default router;
|
||||
export default router
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import store from '@/store';
|
||||
import store from '@/store'
|
||||
|
||||
const checkUserinfo = code => {
|
||||
const userinfo = store.state.account.userinfo;
|
||||
const userinfo = store.state.account.userinfo
|
||||
if (userinfo) {
|
||||
return `/error/${code}`;
|
||||
return `/error/${code}`
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return true
|
||||
}
|
||||
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Error = () => import('@/views/error/index.vue');
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Error = () => import('@/views/error/index.vue')
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -53,7 +53,7 @@ export default [
|
||||
error: '403',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('403');
|
||||
return checkUserinfo('403')
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -64,7 +64,7 @@ export default [
|
||||
error: '500',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('500');
|
||||
return checkUserinfo('500')
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -75,7 +75,7 @@ export default [
|
||||
error: '404',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('404');
|
||||
return checkUserinfo('404')
|
||||
},
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// home.js
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Home = () => import('@/views/home/index.vue');
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Home = () => import('@/views/home/index.vue')
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -23,4 +23,4 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// login.js
|
||||
const Login = () => import('@/views/login/index.vue');
|
||||
const Login = () => import('@/views/login/index.vue')
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -7,4 +7,4 @@ export default [
|
||||
name: 'login',
|
||||
component: Login,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Redirect = () => import('@/views/redirect/index.vue');
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Redirect = () => import('@/views/redirect/index.vue')
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -12,4 +12,4 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const List = () => import('@/views/test/index.vue');
|
||||
const Add = () => import('@/views/test/Add.vue');
|
||||
const Auth = () => import('@/views/test/Auth.vue');
|
||||
const NoAuth = () => import('@/views/test/NoAuth.vue');
|
||||
const Nest = () => import('@/views/test/Nest.vue');
|
||||
const NestPage1 = () => import('@/views/test/nest/Page1.vue');
|
||||
const NestPage2 = () => import('@/views/test/nest/Page2.vue');
|
||||
const Iscache = () => import('@/views/test/Cache.vue');
|
||||
const Nocache = () => import('@/views/test/Nocache.vue');
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const List = () => import('@/views/test/index.vue')
|
||||
const Add = () => import('@/views/test/Add.vue')
|
||||
const Auth = () => import('@/views/test/Auth.vue')
|
||||
const NoAuth = () => import('@/views/test/NoAuth.vue')
|
||||
const Nest = () => import('@/views/test/Nest.vue')
|
||||
const NestPage1 = () => import('@/views/test/nest/Page1.vue')
|
||||
const NestPage2 = () => import('@/views/test/nest/Page2.vue')
|
||||
const Iscache = () => import('@/views/test/Cache.vue')
|
||||
const Nocache = () => import('@/views/test/Nocache.vue')
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -109,4 +109,4 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
//index.js
|
||||
import { createStore } from 'vuex';
|
||||
import app from './modules/app';
|
||||
import account from './modules/account';
|
||||
import menu from './modules/menu';
|
||||
import tags from './modules/tags';
|
||||
import { createStore } from 'vuex'
|
||||
import app from './modules/app'
|
||||
import account from './modules/account'
|
||||
import menu from './modules/menu'
|
||||
import tags from './modules/tags'
|
||||
|
||||
export default createStore({
|
||||
modules: {
|
||||
@ -12,4 +12,4 @@ export default createStore({
|
||||
menu,
|
||||
tags,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { GetUserinfo } from '@/api/login';
|
||||
import { GetUserinfo } from '@/api/login'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
@ -8,21 +8,21 @@ export default {
|
||||
mutations: {
|
||||
// 保存用户信息
|
||||
setUserinfo(state, data) {
|
||||
state.userinfo = data;
|
||||
state.userinfo = data
|
||||
},
|
||||
// 清除用户信息
|
||||
clearUserinfo(state) {
|
||||
state.userinfo = null;
|
||||
state.userinfo = null
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
// 获取用户信息
|
||||
async getUserinfo({ commit }) {
|
||||
const { code, data } = await GetUserinfo();
|
||||
const { code, data } = await GetUserinfo()
|
||||
if (+code === 200) {
|
||||
commit('setUserinfo', data);
|
||||
return Promise.resolve(data);
|
||||
commit('setUserinfo', data)
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage'; //getItem和setItem是封装的操作localStorage的方法
|
||||
export const TOKEN = 'VEA-TOKEN';
|
||||
const COLLAPSE = 'VEA-COLLAPSE';
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
export const TOKEN = 'VEA-TOKEN'
|
||||
const COLLAPSE = 'VEA-COLLAPSE'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
@ -14,28 +14,28 @@ export default {
|
||||
},
|
||||
mutations: {
|
||||
setToken(state, data) {
|
||||
state.authorization = data;
|
||||
state.authorization = data
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, data);
|
||||
setItem(TOKEN, data)
|
||||
},
|
||||
clearToken(state) {
|
||||
state.authorization = '';
|
||||
state.authorization = ''
|
||||
|
||||
removeItem(TOKEN);
|
||||
removeItem(TOKEN)
|
||||
},
|
||||
setCollapse(state, data) {
|
||||
state.sidebar.collapse = data;
|
||||
state.sidebar.collapse = data
|
||||
// 保存到localStorage
|
||||
setItem(COLLAPSE, data);
|
||||
setItem(COLLAPSE, data)
|
||||
},
|
||||
clearCollapse(state) {
|
||||
state.sidebar.collapse = '';
|
||||
state.sidebar.collapse = ''
|
||||
|
||||
removeItem(COLLAPSE);
|
||||
removeItem(COLLAPSE)
|
||||
},
|
||||
setDevice(state, device) {
|
||||
state.device = device;
|
||||
state.device = device
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import { allMenus } from '@/router';
|
||||
import { allMenus } from '@/router'
|
||||
// import { GetMenus } from '@/api/menu';
|
||||
|
||||
const hasPermission = (role, route) => {
|
||||
if (!!route.meta && !!route.meta.roles && !route.meta.roles.includes(role)) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return true
|
||||
}
|
||||
|
||||
const generateUrl = (path, parentPath) => {
|
||||
return path.startsWith('/')
|
||||
? path
|
||||
: path
|
||||
? `${parentPath}/${path}`
|
||||
: parentPath;
|
||||
};
|
||||
: parentPath
|
||||
}
|
||||
|
||||
const getFilterMenus = (arr, role, parentPath = '') => {
|
||||
const menus = [];
|
||||
const menus = []
|
||||
|
||||
arr.forEach(item => {
|
||||
if (hasPermission(role, item) && !item.hidden) {
|
||||
@ -25,20 +25,20 @@ const getFilterMenus = (arr, role, parentPath = '') => {
|
||||
url: generateUrl(item.path, parentPath),
|
||||
title: item.meta.title,
|
||||
icon: item.icon,
|
||||
};
|
||||
}
|
||||
if (item.children) {
|
||||
if (item.children.length === 1) {
|
||||
menu.url = generateUrl(item.children[0].path, menu.url);
|
||||
menu.url = generateUrl(item.children[0].path, menu.url)
|
||||
} else {
|
||||
menu.children = getFilterMenus(item.children, role, menu.url);
|
||||
menu.children = getFilterMenus(item.children, role, menu.url)
|
||||
}
|
||||
}
|
||||
menus.push(menu);
|
||||
menus.push(menu)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return menus;
|
||||
};
|
||||
return menus
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
@ -47,14 +47,14 @@ export default {
|
||||
},
|
||||
mutations: {
|
||||
SET_MENUS(state, data) {
|
||||
state.menus = data;
|
||||
state.menus = data
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async generateMenus({ commit }, role) {
|
||||
// 方式一:根据角色生成菜单
|
||||
const menus = getFilterMenus(allMenus, role);
|
||||
commit('SET_MENUS', menus);
|
||||
const menus = getFilterMenus(allMenus, role)
|
||||
commit('SET_MENUS', menus)
|
||||
|
||||
// // 方式二:从后台获取菜单
|
||||
// const { code, data } = await GetMenus();
|
||||
@ -63,4 +63,4 @@ export default {
|
||||
// }
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage'; //getItem和setItem是封装的操作localStorage的方法
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
|
||||
const TAGLIST = 'VEA-TAGLIST';
|
||||
const TAGLIST = 'VEA-TAGLIST'
|
||||
|
||||
const state = {
|
||||
tagList: getItem(TAGLIST) || [],
|
||||
cacheList: [],
|
||||
activePosition: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
ADD_TAG_LIST: (state, { path, fullPath, name, meta }) => {
|
||||
if (state.tagList.some(v => v.path === path)) return false;
|
||||
if (state.tagList.some(v => v.path === path)) return false
|
||||
|
||||
state.tagList.splice(
|
||||
state.activePosition + 1,
|
||||
@ -23,136 +23,136 @@ const mutations = {
|
||||
fullPath: fullPath || path,
|
||||
}
|
||||
)
|
||||
);
|
||||
)
|
||||
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
ADD_CACHE_LIST: (state, tag) => {
|
||||
if (state.cacheList.includes(tag.name)) return;
|
||||
if (state.cacheList.includes(tag.name)) return
|
||||
if (!tag.meta.noCache) {
|
||||
state.cacheList.push(tag.name);
|
||||
state.cacheList.push(tag.name)
|
||||
}
|
||||
},
|
||||
|
||||
DEL_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(v => v.path !== tag.path);
|
||||
state.tagList = state.tagList.filter(v => v.path !== tag.path)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
DEL_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v !== tag.name);
|
||||
state.cacheList = state.cacheList.filter(v => v !== tag.name)
|
||||
},
|
||||
|
||||
DEL_OTHER_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || v.path === tag.path
|
||||
);
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
DEL_OTHER_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v === tag.name);
|
||||
state.cacheList = state.cacheList.filter(v => v === tag.name)
|
||||
},
|
||||
|
||||
DEL_SOME_TAG_LIST: (state, tags) => {
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || tags.every(tag => tag.path !== v.path)
|
||||
);
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
|
||||
DEL_SOME_CACHE_LIST: (state, tags) => {
|
||||
state.cacheList = state.cacheList.filter(v =>
|
||||
tags.every(tag => tag.name !== v)
|
||||
);
|
||||
)
|
||||
},
|
||||
|
||||
DEL_ALL_TAG_LIST: state => {
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix);
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix)
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST);
|
||||
removeItem(TAGLIST)
|
||||
},
|
||||
DEL_ALL_CACHE_LIST: state => {
|
||||
state.cacheList = [];
|
||||
state.cacheList = []
|
||||
},
|
||||
|
||||
UPDATE_TAG_LIST: (state, tag) => {
|
||||
const index = state.tagList.findIndex(v => v.path === tag.path);
|
||||
const index = state.tagList.findIndex(v => v.path === tag.path)
|
||||
if (index > -1) {
|
||||
state.tagList[index] = Object.assign({}, state.tagList[index], tag);
|
||||
state.tagList[index] = Object.assign({}, state.tagList[index], tag)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
setItem(TAGLIST, state.tagList)
|
||||
}
|
||||
},
|
||||
|
||||
SAVE_ACTIVE_POSITION: (state, index) => {
|
||||
state.activePosition = index;
|
||||
state.activePosition = index
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const actions = {
|
||||
saveActivePosition({ commit }, index) {
|
||||
commit('SAVE_ACTIVE_POSITION', index);
|
||||
commit('SAVE_ACTIVE_POSITION', index)
|
||||
},
|
||||
addTag({ dispatch }, tag) {
|
||||
dispatch('addTagList', tag);
|
||||
dispatch('addCacheList', tag);
|
||||
dispatch('addTagList', tag)
|
||||
dispatch('addCacheList', tag)
|
||||
},
|
||||
addTagList({ commit }, tag) {
|
||||
commit('ADD_TAG_LIST', tag);
|
||||
commit('ADD_TAG_LIST', tag)
|
||||
},
|
||||
addCacheList({ commit }, tag) {
|
||||
commit('ADD_CACHE_LIST', tag);
|
||||
commit('ADD_CACHE_LIST', tag)
|
||||
},
|
||||
|
||||
delTag({ dispatch }, tag) {
|
||||
dispatch('delTagList', tag);
|
||||
dispatch('delCacheList', tag);
|
||||
dispatch('delTagList', tag)
|
||||
dispatch('delCacheList', tag)
|
||||
},
|
||||
delTagList({ commit }, tag) {
|
||||
commit('DEL_TAG_LIST', tag);
|
||||
commit('DEL_TAG_LIST', tag)
|
||||
},
|
||||
delCacheList({ commit }, tag) {
|
||||
commit('DEL_CACHE_LIST', tag);
|
||||
commit('DEL_CACHE_LIST', tag)
|
||||
},
|
||||
|
||||
delOtherTags({ dispatch }, tag) {
|
||||
dispatch('delOtherTagList', tag);
|
||||
dispatch('delOtherCacheList', tag);
|
||||
dispatch('delOtherTagList', tag)
|
||||
dispatch('delOtherCacheList', tag)
|
||||
},
|
||||
delOtherTagList({ commit }, tag) {
|
||||
commit('DEL_OTHER_TAG_LIST', tag);
|
||||
commit('DEL_OTHER_TAG_LIST', tag)
|
||||
},
|
||||
delOtherCacheList({ commit }, tag) {
|
||||
commit('DEL_OTHER_CACHE_LIST', tag);
|
||||
commit('DEL_OTHER_CACHE_LIST', tag)
|
||||
},
|
||||
|
||||
delSomeTags({ commit }, tags) {
|
||||
commit('DEL_SOME_TAG_LIST', tags);
|
||||
commit('DEL_SOME_CACHE_LIST', tags);
|
||||
commit('DEL_SOME_TAG_LIST', tags)
|
||||
commit('DEL_SOME_CACHE_LIST', tags)
|
||||
},
|
||||
|
||||
delAllTags({ dispatch }) {
|
||||
dispatch('delAllTagList');
|
||||
dispatch('delAllCacheList');
|
||||
dispatch('delAllTagList')
|
||||
dispatch('delAllCacheList')
|
||||
},
|
||||
delAllTagList({ commit }) {
|
||||
commit('DEL_ALL_TAG_LIST');
|
||||
commit('DEL_ALL_TAG_LIST')
|
||||
},
|
||||
delAllCacheList({ commit }) {
|
||||
commit('DEL_ALL_CACHE_LIST');
|
||||
commit('DEL_ALL_CACHE_LIST')
|
||||
},
|
||||
|
||||
updateTagList({ commit }, tag) {
|
||||
commit('UPDATE_TAG_LIST', tag);
|
||||
commit('UPDATE_TAG_LIST', tag)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
import axios from 'axios';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import store from '@/store';
|
||||
import router from '@/router';
|
||||
import axios from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: '/',
|
||||
timeout: 10000,
|
||||
withCredentials: true,
|
||||
});
|
||||
})
|
||||
|
||||
// 拦截请求
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
const { authorization } = store.state.app;
|
||||
const { authorization } = store.state.app
|
||||
if (authorization) {
|
||||
config.headers.Authorization = `Bearer ${authorization.token}`;
|
||||
config.headers.Authorization = `Bearer ${authorization.token}`
|
||||
}
|
||||
return config;
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// console.log(error);
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(error)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
// 拦截响应
|
||||
service.interceptors.response.use(
|
||||
// 响应成功进入第1个函数,该函数的参数是响应对象
|
||||
response => {
|
||||
return response.data;
|
||||
return response.data
|
||||
},
|
||||
// 响应失败进入第2个函数,该函数的参数是错误对象
|
||||
async error => {
|
||||
@ -36,12 +36,12 @@ service.interceptors.response.use(
|
||||
// 响应拦截器中的 error 就是那个响应的错误对象
|
||||
if (error.response && error.response.status === 401) {
|
||||
// 校验是否有 refresh_token
|
||||
const { authorization } = store.state.app;
|
||||
const { authorization } = store.state.app
|
||||
if (!authorization || !authorization.refresh_token) {
|
||||
router.push('/login');
|
||||
router.push('/login')
|
||||
|
||||
// 代码不要往后执行了
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(error)
|
||||
}
|
||||
// 如果有refresh_token,则请求获取新的 token
|
||||
try {
|
||||
@ -52,32 +52,32 @@ service.interceptors.response.use(
|
||||
headers: {
|
||||
Authorization: `Bearer ${authorization.refresh_token}`,
|
||||
},
|
||||
});
|
||||
})
|
||||
// 如果获取成功,则把新的 token 更新到容器中
|
||||
// console.log('刷新 token 成功', res)
|
||||
store.commit('app/setToken', {
|
||||
token: res.data.data.token, // 最新获取的可用 token
|
||||
refresh_token: authorization.refresh_token, // 还是原来的 refresh_token
|
||||
});
|
||||
})
|
||||
// 把之前失败的用户请求继续发出去
|
||||
// config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有
|
||||
// return 把 request 的请求结果继续返回给发请求的具体位置
|
||||
return service(error.config);
|
||||
return service(error.config)
|
||||
} catch (err) {
|
||||
// 如果获取失败,直接跳转 登录页
|
||||
// console.log('请求刷新 token 失败', err)
|
||||
router.push('/login');
|
||||
router.push('/login')
|
||||
// 清除token
|
||||
store.commit('app/clearToken');
|
||||
return Promise.reject(error);
|
||||
store.commit('app/clearToken')
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
// console.dir(error) // 可在此进行错误上报
|
||||
ElMessage.error(error.message);
|
||||
ElMessage.error(error.message)
|
||||
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(error)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
export default service;
|
||||
export default service
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
export const getItem = name => {
|
||||
const data = window.localStorage.getItem(name);
|
||||
const data = window.localStorage.getItem(name)
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
return JSON.parse(data)
|
||||
} catch (err) {
|
||||
return data;
|
||||
return data
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const setItem = (name, value) => {
|
||||
if (typeof value === 'object') {
|
||||
value = JSON.stringify(value);
|
||||
value = JSON.stringify(value)
|
||||
}
|
||||
|
||||
window.localStorage.setItem(name, value);
|
||||
};
|
||||
window.localStorage.setItem(name, value)
|
||||
}
|
||||
|
||||
export const removeItem = name => {
|
||||
window.localStorage.removeItem(name);
|
||||
};
|
||||
window.localStorage.removeItem(name)
|
||||
}
|
||||
|
||||
@ -21,11 +21,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: ['error'],
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'home',
|
||||
setup() {},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -43,17 +43,17 @@ import {
|
||||
toRefs,
|
||||
ref,
|
||||
computed,
|
||||
} from 'vue';
|
||||
import { Login } from '@/api/login';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
} from 'vue'
|
||||
import { Login } from '@/api/login'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
export default defineComponent({
|
||||
name: 'login',
|
||||
setup() {
|
||||
const { ctx } = getCurrentInstance(); // 可以把ctx当成vue2中的this
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { ctx } = getCurrentInstance() // 可以把ctx当成vue2中的this
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const state = reactive({
|
||||
model: {
|
||||
userName: 'admin',
|
||||
@ -78,34 +78,34 @@ export default defineComponent({
|
||||
loginForm: ref(null),
|
||||
submit: () => {
|
||||
if (state.loading) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
state.loginForm.validate(async valid => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
const { code, data, message } = await Login(state.model);
|
||||
state.loading = true
|
||||
const { code, data, message } = await Login(state.model)
|
||||
if (+code === 200) {
|
||||
ctx.$message.success({
|
||||
message: '登录成功',
|
||||
duration: 1000,
|
||||
});
|
||||
const targetPath = route.query.redirect;
|
||||
router.push(targetPath ? targetPath : '/');
|
||||
store.commit('app/setToken', data);
|
||||
})
|
||||
const targetPath = route.query.redirect
|
||||
router.push(targetPath ? targetPath : '/')
|
||||
store.commit('app/setToken', data)
|
||||
} else {
|
||||
ctx.$message.error(message);
|
||||
ctx.$message.error(message)
|
||||
}
|
||||
state.loading = false;
|
||||
state.loading = false
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<script>
|
||||
import { h } from 'vue';
|
||||
import { h } from 'vue'
|
||||
export default {
|
||||
created() {
|
||||
this.$router.replace(this.$route.fullPath.replace(/^\/redirect/, ''));
|
||||
this.$router.replace(this.$route.fullPath.replace(/^\/redirect/, ''))
|
||||
},
|
||||
render() {
|
||||
return h('div');
|
||||
return h('div')
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -6,15 +6,15 @@
|
||||
</dl>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, onActivated } from 'vue';
|
||||
import { defineComponent, onActivated } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'test-cache', // 该name必须跟路由配置的name一致
|
||||
setup() {
|
||||
console.log('cache');
|
||||
console.log('cache')
|
||||
onActivated(() => {
|
||||
console.log('onActivated');
|
||||
});
|
||||
console.log('onActivated')
|
||||
})
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
</dl>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'test-no-cache', // 该name必须跟路由配置的name一致,不一致或者不设置name则不缓存
|
||||
setup() {
|
||||
console.log('nocache');
|
||||
console.log('nocache')
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, ref, toRefs } from 'vue';
|
||||
import { defineComponent, reactive, ref, toRefs } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'testList',
|
||||
@ -210,15 +210,15 @@ export default defineComponent({
|
||||
},
|
||||
selectedItems: [],
|
||||
batchDelete() {
|
||||
console.log(state.selectedItems);
|
||||
console.log(state.selectedItems)
|
||||
},
|
||||
// 选择
|
||||
handleSelectionChange(arr) {
|
||||
state.selectedItems = arr;
|
||||
state.selectedItems = arr
|
||||
},
|
||||
// 请求函数
|
||||
async getList(params) {
|
||||
console.log(params);
|
||||
console.log(params)
|
||||
// params是从组件接收的,包含分页和搜索字段。
|
||||
const { data } = await new Promise(rs => {
|
||||
setTimeout(() => {
|
||||
@ -239,23 +239,23 @@ export default defineComponent({
|
||||
],
|
||||
total: 100,
|
||||
},
|
||||
});
|
||||
}, 3000);
|
||||
});
|
||||
})
|
||||
}, 3000)
|
||||
})
|
||||
|
||||
// 必须要返回一个对象,包含data数组和total总数
|
||||
return {
|
||||
data: data.list,
|
||||
total: +data.total,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
const table = ref(null);
|
||||
})
|
||||
const table = ref(null)
|
||||
const refresh = () => {
|
||||
table.value.refresh();
|
||||
};
|
||||
table.value.refresh()
|
||||
}
|
||||
|
||||
return { ...toRefs(state), refresh, table };
|
||||
return { ...toRefs(state), refresh, table }
|
||||
},
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user