add advertising components
This commit is contained in:
parent
8dc03fe6ea
commit
500c1ddb15
5
.env
5
.env
|
|
@ -5,4 +5,7 @@ VITE_APP_TITLE = '智慧河长'
|
|||
VITE_PORT = 3000
|
||||
|
||||
|
||||
VITE_SERVER = "/"
|
||||
# VITE_SERVER = "/hhz/admin/api"
|
||||
VITE_SERVER = ""
|
||||
|
||||
VITE_PLATFORM = "tuoheng-hhz-admin"
|
||||
|
|
@ -9,3 +9,8 @@ VITE_PROXY = [["/api","http://192.168.11.11:9011/api"]]
|
|||
|
||||
# base api
|
||||
VITE_APP_GLOB_BASE_API = '/api'
|
||||
|
||||
VITE_AUTHORITY = 'http://192.168.11.11:8090'
|
||||
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
|
||||
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
|
||||
VITE_REDIRECT_URI = 'http://192.168.11.11:8086/login'
|
||||
|
|
@ -12,3 +12,8 @@ VITE_APP_GLOB_BASE_API = '/api-local'
|
|||
|
||||
# mock base api
|
||||
VITE_APP_GLOB_BASE_API_MOCK = '/api-mock'
|
||||
|
||||
VITE_AUTHORITY = 'http://192.168.11.11:8090'
|
||||
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
|
||||
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
|
||||
VITE_REDIRECT_URI = 'http://192.168.12.8:3000/login'
|
||||
|
|
@ -9,3 +9,8 @@ VITE_PROXY = [["/api","http://127.0.0.1:8002/api"]]
|
|||
|
||||
# base api
|
||||
VITE_APP_GLOB_BASE_API = '/api'
|
||||
|
||||
VITE_AUTHORITY = 'https://oidc.t-aaron.com'
|
||||
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
|
||||
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
|
||||
VITE_REDIRECT_URI = 'https://dsp-portal.t-aaron.com/login'
|
||||
|
|
@ -9,3 +9,8 @@ VITE_PROXY = [["/api","http://192.168.11.241:9011/api"]]
|
|||
|
||||
# base api
|
||||
VITE_APP_GLOB_BASE_API = '/api'
|
||||
|
||||
VITE_AUTHORITY = 'https://oidc.test.t-aaron.com'
|
||||
VITE_CLIENT_ID = 'tuoheng-hhz-admin'
|
||||
VITE_CLIENT_SECRET = 'qsPaU8a2YGFsZfIa7HoGSz=='
|
||||
VITE_REDIRECT_URI = 'http://192.168.11.241:8086/login'
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
"axios": "^0.26.1",
|
||||
"dayjs": "^1.11.2",
|
||||
"mockjs": "^1.1.0",
|
||||
"oidc-client": "^1.11.5",
|
||||
"pinia": "^2.0.13",
|
||||
"pinia-plugin-persist": "^1.0.0",
|
||||
"tinymce": "^5.10.2",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,40 @@ export const refreshToken = () => {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取menu和permission
|
||||
* @param {String} roleId 角色Id
|
||||
* @return {*}
|
||||
*/
|
||||
export const fetchPermission = (roleId) => {
|
||||
return request({
|
||||
url: `/permission/getRolePermission/${roleId}`,
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 测试接口one
|
||||
* @return {*}
|
||||
*/
|
||||
export const permissionOne = () => {
|
||||
return request({
|
||||
url: 'permission/getOne',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 测试接口two
|
||||
* @return {*}
|
||||
*/
|
||||
export const permissionTwo = (id) => {
|
||||
return request({
|
||||
url: 'permission/getTwo',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
export function getMenu() {
|
||||
return request({
|
||||
url: '/index/getMenuList',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { defAxios as request } from '@/utils/http'
|
||||
|
||||
/**
|
||||
* @description: 分页查询广告列表
|
||||
* @return {*}
|
||||
*/
|
||||
export function fetchAdList(params) {
|
||||
return request({
|
||||
url: '/ad/index',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description: 创建广告
|
||||
* @return {*}
|
||||
*/
|
||||
export function advertisingCreate(data) {
|
||||
return request({
|
||||
url: '/ad/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 更新广告信息
|
||||
* @return {*}
|
||||
*/
|
||||
export function advertisingUpdate(data) {
|
||||
return request({
|
||||
url: `/ad/edit`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 删除广告
|
||||
* @return {*}
|
||||
*/
|
||||
export function advertisingDelete(ids) {
|
||||
return request({
|
||||
url: `/ad/delete/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -8,13 +8,6 @@ export function getUsers(data = {}) {
|
|||
})
|
||||
}
|
||||
|
||||
export function getUser() {
|
||||
return request({
|
||||
url: '/index/getUserInfo',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function saveUser(data = {}, id) {
|
||||
if (id) {
|
||||
return request({
|
||||
|
|
|
|||
|
|
@ -76,9 +76,10 @@ export default defineComponent({
|
|||
/* 获取tags的属性 */
|
||||
const getProps = computed(() => {
|
||||
return {
|
||||
...unref(props.tags),
|
||||
closable: false,
|
||||
bordered: props.tags?.bordered || false
|
||||
bordered: false,
|
||||
color: { color: 'transparent' },
|
||||
...unref(props.tags)
|
||||
}
|
||||
})
|
||||
return {
|
||||
|
|
@ -93,7 +94,7 @@ export default defineComponent({
|
|||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
.n-tag{
|
||||
background: transparent;
|
||||
}
|
||||
// .n-tag{
|
||||
// background: transparent;
|
||||
// }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ export default {
|
|||
watch(
|
||||
() => props.modelValue,
|
||||
(value) => {
|
||||
console.log(value)
|
||||
content.value = value
|
||||
}
|
||||
)
|
||||
|
|
@ -162,7 +161,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.tox,.tox-tinymce-aux{
|
||||
z-index: 3000 !important;
|
||||
}
|
||||
// .tox,.tox-tinymce-aux{
|
||||
// z-index: 3000 !important;
|
||||
// }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { EditOutlined, LogoutOutlined } from '@vicons/antd'
|
|||
import { renderIcon } from '@/utils'
|
||||
import { useUserStore } from '@/store/modules/user.js'
|
||||
import { useSettingStore } from '@/store/modules/setting.js'
|
||||
import { signoutRedirect } from '@/utils/oidc/index.js'
|
||||
export default defineComponent({
|
||||
name: 'LayoutHeader',
|
||||
setup() {
|
||||
|
|
@ -57,14 +58,7 @@ export default defineComponent({
|
|||
async function handleSelect(key) {
|
||||
switch (key) {
|
||||
case 'out':
|
||||
await logOut()
|
||||
}
|
||||
}
|
||||
|
||||
async function logOut() {
|
||||
const res = await userStore.userLogout()
|
||||
if (res.code === 0) {
|
||||
router.replace('/login')
|
||||
await signoutRedirect()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,15 +32,9 @@ import SideBar from './components/Sidebar/index.vue'
|
|||
import Tags from './components/Tags/index.vue'
|
||||
import { useSettingStore } from '@/store/modules/setting.js'
|
||||
import { computed } from 'vue'
|
||||
import { useUserStore } from '@/store/modules/user.js'
|
||||
const settingStore = useSettingStore()
|
||||
const menuMode = computed(() => settingStore.getMenuMode)
|
||||
const tagsMenuSetting = computed(() => settingStore.getTagsMenuSetting)
|
||||
const useUser = useUserStore()
|
||||
function getUserNow() {
|
||||
useUser.getUserInfo()
|
||||
}
|
||||
getUserNow()
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +1,50 @@
|
|||
/*
|
||||
* @Author: whyafterme
|
||||
* @Date: 2022-11-03 11:31:21
|
||||
* @LastEditTime: 2022-11-21 09:02:20
|
||||
* @LastEditors: whyafterme
|
||||
* @Description:
|
||||
* @FilePath: \new\src\router\guard\permission-guard.js
|
||||
*/
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import { NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes'
|
||||
import { getToken } from '@/utils/token'
|
||||
import { getUserInfo, signinRedirect, signoutRedirect } from '@/utils/oidc/index.js'
|
||||
|
||||
const WHITE_LIST = ['/login', '/redirect']
|
||||
export function createPermissionGuard(router) {
|
||||
const userStore = useUserStore()
|
||||
const permissionStore = usePermissionStore()
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
// const token = getToken()
|
||||
const token = true
|
||||
if (token) {
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
const oidcUser = await getUserInfo()
|
||||
if (oidcUser) {
|
||||
const hasRoutes = !!permissionStore.permissionRoutes.length
|
||||
if (hasRoutes) {
|
||||
next()
|
||||
} else {
|
||||
const hasRoutes = !!permissionStore.permissionRoutes.length
|
||||
if (hasRoutes) {
|
||||
next()
|
||||
} else {
|
||||
try {
|
||||
// await userStore.getUserInfo()
|
||||
const routes = await permissionStore.generateRoutesMock()
|
||||
routes.forEach((item) => {
|
||||
router.addRoute(item)
|
||||
})
|
||||
router.addRoute(NOT_FOUND_ROUTE)
|
||||
router.addRoute(REDIRECT_ROUTE)
|
||||
next({ ...to, replace: true })
|
||||
} catch (error) {
|
||||
// removeToken()
|
||||
// $message.error(error)
|
||||
next({ path: '/login', query: { ...to.query, redirect: to.path }})
|
||||
}
|
||||
try {
|
||||
const { clientRoleList } = oidcUser.profile
|
||||
const { VITE_CLIENT_ID } = import.meta.env
|
||||
const { roleId } = clientRoleList.find((item) => {
|
||||
return item.clientId === VITE_CLIENT_ID
|
||||
})
|
||||
// await userStore.getUserInfo()
|
||||
// const routes = await permissionStore.generateRoutes(roleId)
|
||||
const routes = await permissionStore.generateRoutesMock()
|
||||
routes.forEach((item) => {
|
||||
router.addRoute(item)
|
||||
})
|
||||
router.addRoute(NOT_FOUND_ROUTE)
|
||||
router.addRoute(REDIRECT_ROUTE)
|
||||
next({ ...to, replace: true })
|
||||
} catch (error) {
|
||||
signinRedirect()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (WHITE_LIST.includes(to.path)) {
|
||||
if (to.path === '/login') {
|
||||
next()
|
||||
} else {
|
||||
next({ path: '/login', query: { ...to.query, redirect: to.path }})
|
||||
signinRedirect()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ const setting = {
|
|||
},
|
||||
/* tags */
|
||||
tagsMenuSetting: {
|
||||
show: true,
|
||||
fixed: true,
|
||||
show: false,
|
||||
fixed: false,
|
||||
background: '#f5f7f9'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { asyncRoutes, basicRoutes } from '@/router/routes'
|
||||
import { getMenu } from '@/api/auth/index'
|
||||
import { fetchPermission } from '@/api/auth/index'
|
||||
import Layout from '@/layout/index.vue'
|
||||
import modules from '@/utils/module.js'
|
||||
|
||||
|
|
@ -44,55 +44,43 @@ function filterAsyncRoutes(routes = [], role) {
|
|||
return ret
|
||||
}
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @param {*} routes
|
||||
* @return {*}
|
||||
*/
|
||||
function dataArrayToRoutes(routes) {
|
||||
function dealRoutes(routes) {
|
||||
const res = []
|
||||
routes.forEach(item => {
|
||||
const tmp = { ...item }
|
||||
// // 如果有component配置
|
||||
// if (tmp.component) {
|
||||
// // Layout引入
|
||||
// if (tmp.component === 'Layout') {
|
||||
// tmp.component = Layout
|
||||
// } else {
|
||||
// const sub_view = tmp.component.replace(/^\/*/g, '')
|
||||
// const component = `../${sub_view}.vue`
|
||||
// tmp.component = modules[component]
|
||||
// }
|
||||
// if (tmp.children) {
|
||||
// tmp.children = dataArrayToRoutes(tmp.children)
|
||||
// }
|
||||
// }
|
||||
// 如果pid为0
|
||||
if (tmp.pid === 0) {
|
||||
// Layout引入
|
||||
if (tmp.parentId === 0) {
|
||||
tmp.component = Layout
|
||||
if (tmp.children) {
|
||||
tmp.children = dataArrayToRoutes(tmp.children)
|
||||
tmp.redirect = tmp.path === '/' ? `/${tmp.children[0].path}` : `${tmp.path}/${tmp.children[0].path}`
|
||||
tmp.children = dealRoutes(tmp.children)
|
||||
}
|
||||
} else {
|
||||
const sub_view = tmp.component.replace(/^\/*/g, '')
|
||||
const component = `../${sub_view}.vue`
|
||||
tmp.component = modules[component]
|
||||
}
|
||||
tmp.name = tmp.title
|
||||
tmp.title = tmp.name
|
||||
tmp.meta = {
|
||||
...tmp.meta,
|
||||
title: tmp.meta.title || tmp.title
|
||||
...tmp?.meta,
|
||||
title: tmp.name
|
||||
}
|
||||
res.push(tmp)
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
function dealPermissions(permissionsList) {
|
||||
const res = permissionsList.map((tmp) => {
|
||||
return tmp.code
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
export const usePermissionStore = defineStore('permission', {
|
||||
state() {
|
||||
return {
|
||||
accessRoutes: []
|
||||
accessRoutes: [],
|
||||
accessPermissions: []
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
|
|
@ -101,23 +89,31 @@ export const usePermissionStore = defineStore('permission', {
|
|||
},
|
||||
permissionRoutes() {
|
||||
return this.accessRoutes
|
||||
},
|
||||
validatePermission() {
|
||||
return this.accessPermissions
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
generateRoutesMock(role = []) {
|
||||
const accessRoutes = filterAsyncRoutes(asyncRoutes, role)
|
||||
this.accessRoutes = accessRoutes
|
||||
console.log(accessRoutes)
|
||||
return accessRoutes
|
||||
},
|
||||
async generateRoutes() {
|
||||
async generateRoutes(roleId) {
|
||||
try {
|
||||
const res = await getMenu()
|
||||
const res = await fetchPermission(roleId)
|
||||
// const res = await fetchPermission(3)
|
||||
if (res.code === 0) {
|
||||
const result = dataArrayToRoutes(res.data)
|
||||
console.log(result)
|
||||
this.accessRoutes = result
|
||||
return Promise.resolve(result)
|
||||
const { opMenusList, permissionsList } = res.data
|
||||
const menus = dealRoutes(opMenusList)
|
||||
const permissions = dealPermissions(permissionsList)
|
||||
this.accessRoutes = menus
|
||||
this.accessPermissions = permissions
|
||||
return Promise.resolve(menus)
|
||||
// const accessRoutes = filterAsyncRoutes(asyncRoutes)
|
||||
// this.accessRoutes = accessRoutes
|
||||
// return Promise.resolve(accessRoutes)
|
||||
} else {
|
||||
return Promise.reject(res.message)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,71 +1,56 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { userLogin, loginOut } from '@/api/login'
|
||||
import { getUser } from '@/api/login/index.js'
|
||||
import { setToken, removeToken } from '@/utils/token'
|
||||
|
||||
import { useTagsMenuStore } from './tagsMenu.js'
|
||||
import { usePermissionStore } from './permission.js'
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
persist: true,
|
||||
persist: {
|
||||
enabled: true
|
||||
},
|
||||
state() {
|
||||
return {
|
||||
userInfo: {}
|
||||
userInfo: {
|
||||
hasLogin: false
|
||||
}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
userInfoMsg() {
|
||||
return this.userInfo
|
||||
// userId() {
|
||||
// return this.userInfo?.id
|
||||
// },
|
||||
userName() {
|
||||
return this.userInfo?.userName
|
||||
},
|
||||
realname() {
|
||||
return this.userInfo?.realname
|
||||
},
|
||||
avatar() {
|
||||
return this.userInfo?.avatar
|
||||
},
|
||||
role() {
|
||||
return this.userInfo?.role || []
|
||||
},
|
||||
authority() {
|
||||
return this.userInfo.authority
|
||||
},
|
||||
hasLogin() {
|
||||
return this.userInfo.hasLogin
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
/* 登录 */
|
||||
async getLoginToken(form) {
|
||||
async getUserInfos() {
|
||||
try {
|
||||
const res = await userLogin(form)
|
||||
const res = await getUser()
|
||||
if (res.code === 0) {
|
||||
/* 设置token */
|
||||
setToken(res.data.access_token)
|
||||
this.getUserInfo()
|
||||
return Promise.resolve(res)
|
||||
this.setUserInfo({ hasLogin: true, ...res.data })
|
||||
return Promise.resolve(res.data.type)
|
||||
} else {
|
||||
return Promise.reject(res)
|
||||
this.setUserInfo()
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
console.error(error)
|
||||
this.setUserInfo()
|
||||
}
|
||||
},
|
||||
/* 获取用户信息 */
|
||||
async getUserInfo() {
|
||||
const res = await getUser()
|
||||
if (res.code === 0) {
|
||||
this.setUserInfo(res.data)
|
||||
}
|
||||
},
|
||||
async userLogout() {
|
||||
try {
|
||||
const res = await loginOut()
|
||||
if (res.code === 0) {
|
||||
removeToken()
|
||||
this.reset()
|
||||
return Promise.resolve(res)
|
||||
} else {
|
||||
return Promise.reject(res)
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.$reset()
|
||||
const tagsMenuStore = useTagsMenuStore()
|
||||
const permissionStore = usePermissionStore()
|
||||
tagsMenuStore.$reset()
|
||||
permissionStore.$reset()
|
||||
},
|
||||
|
||||
setUserInfo(userInfo = {}) {
|
||||
setUserInfo(userInfo = { hasLogin: false }) {
|
||||
this.userInfo = { ...this.userInfo, ...userInfo }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,3 +28,20 @@ export const MENU_STATUS = [
|
|||
{ label: '在用', value: 1 },
|
||||
{ label: '停用', value: 2 }
|
||||
]
|
||||
|
||||
export const ADVERTISING_TYPE = [
|
||||
{ label: '图片', value: 1, color: { color: '#f6ffed', textColor: '#389e0d', borderColor: '#b7eb8f' }},
|
||||
{ label: '文字', value: 2, color: { color: '#e6f7ff', textColor: '#096dd9', borderColor: '#91d5ff' }},
|
||||
{ label: '视频', value: 2, color: { color: '#fff1f0', textColor: '#cf1322', borderColor: '#ffa39e' }},
|
||||
{ label: '推荐', value: 2, color: { color: '#fff7e6', textColor: '#d46b08', borderColor: '#ffd591' }}
|
||||
]
|
||||
|
||||
export const ADVERTISING_PLATFORM = [
|
||||
{ label: '微信小程序', value: 1, color: { color: '#e6f7ff', textColor: '#096dd9', borderColor: '#91d5ff' }},
|
||||
{ label: '其他', value: 2, color: { color: '#f6ffed', textColor: '#389e0d', borderColor: '#b7eb8f' }}
|
||||
]
|
||||
|
||||
export const ADVERTISING_STATUS = [
|
||||
{ label: '正常', value: 1, color: { color: '#e6f7ff', textColor: '#096dd9', borderColor: '#91d5ff' }},
|
||||
{ label: '停用', value: 2, color: { color: '#fff1f0', textColor: '#cf1322', borderColor: '#ffa39e' }}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { router } from '@/router'
|
||||
import { getToken, removeToken } from '@/utils/token'
|
||||
import { isWithoutToken } from './help'
|
||||
import { getUserInfo, signoutRedirect } from '@/utils/oidc/index.js'
|
||||
|
||||
export function setupInterceptor(service) {
|
||||
service.interceptors.request.use(
|
||||
|
|
@ -12,22 +11,20 @@ export function setupInterceptor(service) {
|
|||
// 处理不需要token的请求
|
||||
if (isWithoutToken(config)) {
|
||||
return config
|
||||
} else {
|
||||
const userInfo = await getUserInfo()
|
||||
if (userInfo) {
|
||||
const { token_type, access_token } = userInfo
|
||||
// config.headers.Authorization = `${token_type} ${access_token}`
|
||||
config.headers.Authorization = '70aa58b4-dda7-446d-8cbf-8e6d6ab89a02'
|
||||
const { VITE_CLIENT_ID } = import.meta.env
|
||||
config.headers['Client-Id'] = VITE_CLIENT_ID
|
||||
return config
|
||||
} else {
|
||||
signoutRedirect()
|
||||
return Promise.reject({ response: { status: 401, message: '未登录' }})
|
||||
}
|
||||
}
|
||||
const token = getToken()
|
||||
if (token) {
|
||||
config.headers.Authorization = token
|
||||
return config
|
||||
}
|
||||
/**
|
||||
* * 未登录或者token过期的情况下
|
||||
* * 跳转登录页重新登录,携带当前路由及参数,登录成功会回到原来的页面
|
||||
*/
|
||||
const { currentRoute } = router
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: { ...currentRoute.query, redirect: currentRoute.path }
|
||||
})
|
||||
return Promise.reject({ code: '-1', message: '未登录' })
|
||||
},
|
||||
(error) => Promise.reject(error)
|
||||
)
|
||||
|
|
@ -36,7 +33,6 @@ export function setupInterceptor(service) {
|
|||
(response) => {
|
||||
const { method } = response?.config
|
||||
const { code } = response?.data
|
||||
const { currentRoute } = router
|
||||
switch (code) {
|
||||
case 0:
|
||||
if (method !== 'get') {
|
||||
|
|
@ -48,11 +44,7 @@ export function setupInterceptor(service) {
|
|||
break
|
||||
case 401:
|
||||
// 未登录(可能是token过期或者无效了)
|
||||
removeToken()
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: { ...currentRoute.query, redirect: currentRoute.path }
|
||||
})
|
||||
signoutRedirect()
|
||||
break
|
||||
default:
|
||||
break
|
||||
|
|
@ -60,7 +52,15 @@ export function setupInterceptor(service) {
|
|||
return response?.data
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
const { status } = error.response
|
||||
if (status === 401) {
|
||||
signoutRedirect()
|
||||
} else if (status === 403) {
|
||||
$message.error('暂无权限访问,请联系管理员')
|
||||
return Promise.reject(error)
|
||||
} else {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
import { UserManager } from 'oidc-client'
|
||||
import { createLocalStorage } from '../cache'
|
||||
let oidcManager = null
|
||||
|
||||
export const initServe = () => {
|
||||
if (oidcManager) return oidcManager
|
||||
const { VITE_AUTHORITY, VITE_CLIENT_ID, VITE_CLIENT_SECRET, VITE_REDIRECT_URI } = import.meta.env
|
||||
oidcManager = new UserManager({
|
||||
/* 认证服务器 */
|
||||
authority: VITE_AUTHORITY,
|
||||
/* 客户端id */
|
||||
client_id: VITE_CLIENT_ID,
|
||||
client_secret: VITE_CLIENT_SECRET,
|
||||
/* 回调客户端页面 */
|
||||
redirect_uri: VITE_REDIRECT_URI,
|
||||
post_logout_redirect_uri: VITE_REDIRECT_URI,
|
||||
response_type: 'code',
|
||||
/* 授权范围 */
|
||||
scope: 'openid profile',
|
||||
automaticSilentRenew: true,
|
||||
revokeAccessTokenOnSignout: true,
|
||||
metadata: {
|
||||
issuer: `${VITE_AUTHORITY}`,
|
||||
authorization_endpoint: `${VITE_AUTHORITY}/oauth2/authorize`,
|
||||
token_endpoint: `${VITE_AUTHORITY}/oauth2/token`,
|
||||
userinfo_endpoint: `${VITE_AUTHORITY}/userinfo`,
|
||||
end_session_endpoint: `${VITE_AUTHORITY}/toLogout`,
|
||||
revocation_endpoint: `${VITE_AUTHORITY}/oauth2/revoke`
|
||||
}
|
||||
})
|
||||
return oidcManager
|
||||
}
|
||||
|
||||
export const getUserInfo = async() => {
|
||||
oidcManager = initServe()
|
||||
return await oidcManager.getUser()
|
||||
}
|
||||
/* 登录 */
|
||||
export const signinRedirect = async() => {
|
||||
oidcManager = initServe()
|
||||
oidcManager.signinRedirect({})
|
||||
.then(res => {
|
||||
setPath(window.location.pathname)
|
||||
console.log('signed in', res)
|
||||
}).catch(err => {
|
||||
console.err(err)
|
||||
})
|
||||
}
|
||||
/* 登录回调 */
|
||||
export const signinRedirectCallback = async() => {
|
||||
const userInfo = await getUserInfo()
|
||||
if (!userInfo) {
|
||||
oidcManager = initServe()
|
||||
return await oidcManager.signinRedirectCallback()
|
||||
}
|
||||
}
|
||||
/* 退出 */
|
||||
export const signoutRedirect = () => {
|
||||
oidcManager = initServe()
|
||||
oidcManager.signoutRedirect({})
|
||||
.then(function(res) {
|
||||
setPath(window.location.pathname)
|
||||
console.log('signed out', res)
|
||||
}).catch(function(err) {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
/* 退出回调 */
|
||||
export const signoutRedirectCallback = async() => {
|
||||
const userInfo = await getUserInfo()
|
||||
if (!userInfo) {
|
||||
oidcManager = initServe()
|
||||
return await oidcManager.signoutRedirectCallback()
|
||||
}
|
||||
}
|
||||
|
||||
const PATH_CODE = 'redirect_path'
|
||||
const DURATION = 24 * 60 * 60
|
||||
export const isPath = createLocalStorage()
|
||||
/* 获取Path */
|
||||
export function getPath() {
|
||||
return isPath.get(PATH_CODE)
|
||||
}
|
||||
/* 设置Path */
|
||||
export function setPath(Path, duration = DURATION) {
|
||||
isPath.set(PATH_CODE, Path, duration)
|
||||
}
|
||||
/* 移出Path */
|
||||
export function removePath() {
|
||||
isPath.remove(PATH_CODE)
|
||||
}
|
||||
|
|
@ -1,17 +1,78 @@
|
|||
<template>
|
||||
<div>
|
||||
登录页
|
||||
<div class="login">
|
||||
<n-spin>
|
||||
<template #description>
|
||||
正在进入系统中...
|
||||
</template>
|
||||
</n-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: '',
|
||||
setup() {
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { fetchPermission } from '@/api/auth/index'
|
||||
import { signinRedirectCallback, signoutRedirectCallback, signoutRedirect, getPath, removePath } from '@/utils/oidc/index.js'
|
||||
|
||||
export default {
|
||||
name: 'LoginPage',
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
if (route.query?.code && route.query?.state) {
|
||||
/* 登录后的回调 */
|
||||
signinRedirectCallback().then(res => {
|
||||
// router.push({ path: getPath() })
|
||||
// removePath()
|
||||
// userStore.getUserInfos()
|
||||
/* 判断返回的授权信息是否能访问该平台 */
|
||||
const { authority, clientRoleList } = res.profile
|
||||
|
||||
const { VITE_PLATFORM, VITE_CLIENT_ID } = import.meta.env
|
||||
const { roleId } = clientRoleList.find((item) => {
|
||||
return item.clientId === VITE_CLIENT_ID
|
||||
})
|
||||
if (authority && (authority.includes(VITE_PLATFORM) || authority.includes('admin'))) {
|
||||
fetchPermission(roleId)
|
||||
.then(res => {
|
||||
const { opMenusList } = res.data
|
||||
const path = opMenusList[0].path
|
||||
router.push(path)
|
||||
})
|
||||
// router.push('/')
|
||||
} else {
|
||||
$message.error('暂无权限访问,请联系管理员')
|
||||
setTimeout(() => {
|
||||
signoutRedirect()
|
||||
}, 2000)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
/* 失败则退出登录 */
|
||||
signoutRedirect()
|
||||
})
|
||||
// } else if (getPath()) {
|
||||
// signoutRedirectCallback().then(res => {
|
||||
// router.push({ path: getPath() })
|
||||
// userStore.setUserInfo()
|
||||
// removePath()
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.login{
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
.n-spin-body{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
河道管理
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'RiverManage',
|
||||
setup() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
<template>
|
||||
<Modal
|
||||
:options="getModalOptions"
|
||||
:on-positive-click="handleConfirm"
|
||||
:on-negative-click="handleClose"
|
||||
:on-close="handleClose"
|
||||
>
|
||||
<template #Context>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="advertisingForm"
|
||||
:rules="advertisingRules"
|
||||
:label-width="100"
|
||||
label-placement="left"
|
||||
require-mark-placement="left"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<div class="flex__body">
|
||||
<template v-for="(item,index) in getFormOptions" :key="index">
|
||||
<n-form-item :label="item.label" :path="item.key" :class="{ 'flex__item': !['oss','editor'].includes(item.type) }">
|
||||
<UploadOss v-if="item.type === 'oss'" :ref="el=>{ossRefs[item.refIndex] = el}" :default-list="advertisingForm[item.file]" @upload-status="handleUploadStatus" />
|
||||
<n-input v-if="item.type === 'input'" v-model:value="advertisingForm[item.key]" v-bind="item.props" />
|
||||
<n-select v-if="item.type === 'select'" v-model:value="advertisingForm[item.key]" v-bind="item.props" />
|
||||
<n-radio-group v-if="item.type === 'radio'" v-model:value="advertisingForm[item.key]" :name="item.key">
|
||||
<n-space>
|
||||
<n-radio v-for="(cItem,cIndex) in item.options" :key="`${item.key}_${cIndex}`" :value="cItem.value"> {{ cItem.label }}</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
<n-date-picker v-if="item.type === 'date'" v-model:formatted-value="advertisingForm[item.key]" v-bind="item.props" />
|
||||
<n-input-number v-if="item.type === 'number'" v-model:value="advertisingForm[item.key]" v-bind="item.props" />
|
||||
<TinymceEditor v-if="item.type === 'editor'" v-model:modelValue="advertisingForm[item.key]" v-bind="item.props" />
|
||||
</n-form-item>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</n-form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { form } from '../tools/form.js'
|
||||
import Modal from '@/components/Modal/index.vue'
|
||||
import UploadOss from '@/components/UploadOss/index.vue'
|
||||
import TinymceEditor from '@/components/TinymceEditor/index.vue'
|
||||
import { advertisingCreate, advertisingUpdate } from '@/api/setting/advertising.js'
|
||||
import { defineComponent, ref, reactive, computed, toRefs } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'UserModal',
|
||||
components: { Modal, UploadOss, TinymceEditor },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'create'
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'update:visible': null,
|
||||
'reload': null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const MODAL_TYPE = {
|
||||
'create': '新建广告',
|
||||
'preview': '广告详情',
|
||||
'update': '编辑广告'
|
||||
}
|
||||
const { advertisingForm, advertisingRules } = form
|
||||
const formRef = ref()
|
||||
const ossRefs = ref([])
|
||||
const data = reactive({
|
||||
advertisingForm: {
|
||||
...advertisingForm,
|
||||
imageStatus: '',
|
||||
...props.data
|
||||
},
|
||||
advertisingRules: {
|
||||
...advertisingRules
|
||||
},
|
||||
disabled: props.type === 'preview'
|
||||
})
|
||||
const getModalOptions = computed(() => {
|
||||
return {
|
||||
title: MODAL_TYPE[props.type],
|
||||
width: 800,
|
||||
show: props.visible,
|
||||
trapFocus: false,
|
||||
negativeText: '取消',
|
||||
positiveText: '确认'
|
||||
}
|
||||
})
|
||||
|
||||
const getFormOptions = computed(() => {
|
||||
return {
|
||||
...form.formItem
|
||||
}
|
||||
})
|
||||
|
||||
function handleConfirm() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
const uploads = ossRefs.value.map((item, index) => {
|
||||
return item.startUpload()
|
||||
})
|
||||
Promise.all(uploads)
|
||||
.then(response => {
|
||||
const isError = response.map((item) => {
|
||||
return item.includes('error')
|
||||
})
|
||||
if (!isError.includes(true)) {
|
||||
const imageStr = response.join()
|
||||
const params = { ...data.advertisingForm, cover: imageStr }
|
||||
if (params.id) {
|
||||
advertisingUpdate(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
} else {
|
||||
advertisingCreate(params).then(res => {
|
||||
if (res.code === 0) {
|
||||
emit('reload')
|
||||
handleClose()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$message.error('文件上传失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 关闭弹窗 */
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
function handleUploadStatus(status) {
|
||||
data.advertisingForm.imageStatus = status
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
formRef,
|
||||
ossRefs,
|
||||
getModalOptions,
|
||||
getFormOptions,
|
||||
handleConfirm,
|
||||
handleClose,
|
||||
handleUploadStatus
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
.n-input-number{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.flex__body{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
.n-form-item{
|
||||
width: 100%;
|
||||
}
|
||||
.flex__item{
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.n-date-picker{
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,17 +1,72 @@
|
|||
<template>
|
||||
<div>
|
||||
广告管理
|
||||
<n-card>
|
||||
<headSearch :info="search" @search="handleSearch" @reset="handleSearch" />
|
||||
<data-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
:scroll-x="2200"
|
||||
size="large"
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-button type="primary" @click="handleModal"> 新建 </n-button>
|
||||
</template>
|
||||
</data-table>
|
||||
</n-card>
|
||||
</div>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<AdvertisingModal v-if="modalShow" v-model:visible="modalShow" :data="rowData" :type="modalType" @reload="handleSearch" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import search from './tools/search.js'
|
||||
import table from './tools/table.js'
|
||||
import headSearch from '@/components/Search/index.vue'
|
||||
import dataTable from '@/components/DataTable/index.vue'
|
||||
import AdvertisingModal from './components/AdvertisingModal.vue'
|
||||
import { fetchAdList } from '@/api/setting/advertising.js'
|
||||
import { unref, toRefs, reactive, onUnmounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'AdvertisingPage',
|
||||
components: { dataTable, AdvertisingModal, headSearch },
|
||||
setup() {
|
||||
const data = reactive({
|
||||
...toRefs(table),
|
||||
search
|
||||
})
|
||||
|
||||
const loadDataTable = async(res) => {
|
||||
const _params = {
|
||||
...unref(data.searchParams),
|
||||
...res
|
||||
}
|
||||
return await fetchAdList(_params)
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleModal() {
|
||||
data.rowData = null
|
||||
data.modalType = 'create'
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
data.searchParams = null
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(data),
|
||||
loadDataTable,
|
||||
handleModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.n-button + .n-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
import { ref, reactive } from 'vue'
|
||||
import { ADVERTISING_TYPE, ADVERTISING_PLATFORM, ADVERTISING_STATUS } from '@/utils/dictionary.js'
|
||||
|
||||
export const form = reactive({
|
||||
advertisingForm: {
|
||||
cover: null,
|
||||
title: null,
|
||||
description: null,
|
||||
type: 1,
|
||||
platform: 1,
|
||||
url: null,
|
||||
status: 1,
|
||||
width: null,
|
||||
height: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
sort: null,
|
||||
content: null
|
||||
},
|
||||
advertisingRules: {
|
||||
title: [{ required: true, message: '请输入广告标题', trigger: 'blur' }],
|
||||
sort: [{ required: true, type: 'number', message: '请输入排序号', trigger: 'blur' }]
|
||||
},
|
||||
formItem: [
|
||||
{ type: 'oss', refIndex: 0, key: 'imageStatus', file: 'cover', label: '广告图片', props: { maxlength: '20', placeholder: '请输入部门编号', clearable: true }},
|
||||
|
||||
{ type: 'input', key: 'title', label: '广告标题', props: { maxlength: '20', placeholder: '请输入广告标题', clearable: true }},
|
||||
{ type: 'input', key: 'description', label: '广告描述', props: { maxlength: '20', placeholder: '请输入广告描述', clearable: true }},
|
||||
|
||||
{ type: 'select', key: 'type', label: '广告类型', props: { options: ADVERTISING_TYPE, placeholder: '请选择广告类型' }},
|
||||
{ type: 'select', key: 'platform', label: '投放平台', props: { options: ADVERTISING_PLATFORM, placeholder: '请选择投放平台' }},
|
||||
|
||||
{ type: 'input', key: 'url', label: '广告URL', props: { maxlength: '20', placeholder: '请输入广告URL', clearable: true }},
|
||||
{ type: 'radio', key: 'status', label: '广告状态', options: ADVERTISING_STATUS, mode: ['config'] },
|
||||
|
||||
{ type: 'number', key: 'width', label: '广告宽度', props: { min: 0, placeholder: '请输入广告宽度', showButton: false, clearable: true }},
|
||||
{ type: 'number', key: 'height', label: '广告高度', props: { min: 0, placeholder: '请输入广告高度', showButton: false, clearable: true }},
|
||||
|
||||
{ type: 'date', key: 'startTime', label: '开始时间', props: {
|
||||
type: 'datetime',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss', format: 'yyyy-MM-dd HH:mm:ss',
|
||||
actions: ['clear', 'confirm'],
|
||||
timePickerProps: { actions: ['confirm'] }
|
||||
}},
|
||||
{ type: 'date', key: 'endTime', label: '结束时间', props: {
|
||||
type: 'datetime',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss', format: 'yyyy-MM-dd HH:mm:ss',
|
||||
actions: ['clear', 'confirm'],
|
||||
timePickerProps: { actions: ['confirm'] }
|
||||
}},
|
||||
|
||||
{ type: 'number', key: 'sort', label: '排序号', props: { min: 0, placeholder: '请输入排序号', showButton: false, clearable: true }},
|
||||
|
||||
{ type: 'editor', key: 'content', label: '广告内容', props: { height: 300 }}
|
||||
]
|
||||
})
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { reactive } from 'vue'
|
||||
|
||||
const data = reactive([
|
||||
{
|
||||
label: '广告名称',
|
||||
key: 'title',
|
||||
props: {
|
||||
placeholder: '请输入广告名称'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
export default data
|
||||
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
import { h, ref, reactive } from 'vue'
|
||||
import TableImage from '@/components/DataTable/tools/Image.vue'
|
||||
import TableTags from '@/components/DataTable/tools/Tags.vue'
|
||||
import TableAction from '@/components/DataTable/tools/Action.vue'
|
||||
import { ADVERTISING_TYPE, ADVERTISING_PLATFORM, ADVERTISING_STATUS } from '@/utils/dictionary.js'
|
||||
import { advertisingDelete } from '@/api/setting/advertising.js'
|
||||
|
||||
/* 注册table */
|
||||
const tableRef = ref()
|
||||
const searchParams = ref()
|
||||
|
||||
function handleSearch(params) {
|
||||
searchParams.value = { ...params }
|
||||
tableRef.value.reFetch({ searchParams })
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取数据及操作
|
||||
* @param {*} row 单行数据
|
||||
* @param {*} type 操作类型 create:创建,preview:预览,edit:编辑
|
||||
* @return {*}
|
||||
*/
|
||||
function getRowData(row, type) {
|
||||
data.rowData = type === 'create' ? { pid: row.id } : row
|
||||
data.modalType = type
|
||||
data.modalShow = true
|
||||
}
|
||||
|
||||
// 删除方法
|
||||
function deleteData(id) {
|
||||
advertisingDelete(id)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
handleSearch()
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
tableRef,
|
||||
searchParams,
|
||||
rowData: {},
|
||||
modalType: 'create',
|
||||
modalShow: false,
|
||||
handleSearch,
|
||||
|
||||
columns: [
|
||||
{
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
key: 'key',
|
||||
render: (_, index) => {
|
||||
return `${index + 1}`
|
||||
},
|
||||
align: 'center',
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: '广告名称',
|
||||
key: 'title',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '广告封面',
|
||||
key: 'cover',
|
||||
render(row) {
|
||||
return h(TableImage, {
|
||||
images: {
|
||||
width: 36,
|
||||
height: 36,
|
||||
src: row.cover
|
||||
}
|
||||
})
|
||||
},
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '广告类型',
|
||||
key: 'type',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.type,
|
||||
filters: ADVERTISING_TYPE,
|
||||
tags: {
|
||||
bordered: true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '投放平台',
|
||||
key: 'platform',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.platform,
|
||||
filters: ADVERTISING_PLATFORM,
|
||||
tags: {
|
||||
bordered: true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '广告描述',
|
||||
key: 'description',
|
||||
align: 'center',
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
},
|
||||
width: 250
|
||||
},
|
||||
{
|
||||
title: '广告地址',
|
||||
key: 'url',
|
||||
align: 'center',
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
},
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '广告尺寸',
|
||||
key: 'size',
|
||||
align: 'center',
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: `${row.width} x ${row.height}`
|
||||
})
|
||||
},
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
key: 'startTime',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
key: 'endTime',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '浏览量',
|
||||
key: 'viewNum',
|
||||
align: 'center',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 50,
|
||||
render(row) {
|
||||
return h(TableTags, {
|
||||
data: row.status,
|
||||
filters: ADVERTISING_STATUS,
|
||||
tags: {
|
||||
bordered: true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort',
|
||||
align: 'center',
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
return h(TableAction, {
|
||||
actions: [
|
||||
{
|
||||
label: '添加',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'create')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '修改',
|
||||
type: 'button',
|
||||
props: {
|
||||
type: 'primary',
|
||||
text: true,
|
||||
onClick: getRowData.bind(null, row, 'update')
|
||||
},
|
||||
auth: 'basic_list'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
type: 'popconfirm',
|
||||
auth: 'basic_list',
|
||||
tip: '确定删除这条数据吗?',
|
||||
props: {
|
||||
onPositiveClick: deleteData.bind(null, [row.id])
|
||||
},
|
||||
ButtonProps: {
|
||||
text: true,
|
||||
type: 'primary'
|
||||
}
|
||||
}
|
||||
],
|
||||
align: 'center'
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default data
|
||||
|
|
@ -1,14 +1,32 @@
|
|||
<template>
|
||||
<div>
|
||||
统计分析
|
||||
<n-button v-if="validatePermission.includes('sys:permission:testOne')" @click="handleOne">这是按钮one</n-button>
|
||||
<n-button v-if="validatePermission.includes('sys:permission:testTwo')" @click="handleTwo">这是按钮two</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { usePermissionStore } from '@/store/modules/permission.js'
|
||||
import { permissionOne, permissionTwo } from '@/api/auth/index.js'
|
||||
import { computed } from 'vue'
|
||||
import { signinRedirectCallback, signoutRedirectCallback, signoutRedirect, getPath, removePath } from '@/utils/oidc/index.js'
|
||||
export default {
|
||||
name: 'StatisticalAnalysis',
|
||||
setup() {
|
||||
const { validatePermission } = usePermissionStore()
|
||||
const handleOne = async() => {
|
||||
const res = await permissionOne()
|
||||
alert(res)
|
||||
}
|
||||
const handleTwo = async() => {
|
||||
const res = await permissionTwo()
|
||||
}
|
||||
|
||||
return {
|
||||
handleOne,
|
||||
handleTwo,
|
||||
validatePermission
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue