liyongli 4 miesięcy temu
rodzic
commit
236bef7b56

+ 7 - 0
src/App.vue

@@ -1,5 +1,12 @@
 <script setup lang="ts">
 import { RouterView } from 'vue-router'
+import { getUserDetail } from '@/api/index'
+const token = localStorage.getItem('token')
+if (token)
+  getUserDetail().then(({ data }) => {
+    console.log(data)
+    localStorage.setItem('user', JSON.stringify(data))
+  })
 </script>
 
 <template>

+ 37 - 7
src/router/index.ts

@@ -1,4 +1,5 @@
 import { createRouter, createWebHistory } from 'vue-router'
+import type { menu } from '@/types/Tool'
 
 import SkeletonPage from '@/views/SkeletonPage.vue'
 
@@ -60,21 +61,50 @@ const router = createRouter({
           name: 'ReportSpaceForms',
           component: () => import('../views/ReportSpaceFormsPage.vue'),
         },
+        {
+          path: 'examine',
+          name: 'Examine',
+          component: () => import('../views/ExaminePage.vue'),
+        },
       ],
     },
   ],
 })
+
+const checkAuth = (list: menu[], path: string): menu => {
+  let out: menu = {}
+  for (let i = 0; i < list.length; i++) {
+    const v = list[i]
+    if (v.path === path) {
+      out = v
+      break
+    } else if (v.children) {
+      out = checkAuth(v.children, path)
+      if (out) break
+    }
+  }
+  return out
+}
+
 // 路由卫士
 router.beforeEach((to, from, next) => {
-  const token = localStorage.getItem('token')
   // 如果是登录页面,直接放行
-  if (to.path === '/') {
-    return next(token ? '/authorized/originality' : '/login')
-  }
   if (to.path === '/login') return next()
-  // 如果不是登录页面,判断是否登录,如果登录,直接放行,否则跳转到登录页面
-  if (token) return next()
-  next('/login')
+  const token = localStorage.getItem('token')
+  const {
+    role: { menus },
+  }: { role: { menus: menu[] } } = JSON.parse(
+    localStorage.getItem('user') || '{role: { menus: [] }}',
+  )
+  const haveAuth = checkAuth(menus, to.path)
+  if (!token || !haveAuth) {
+    localStorage.removeItem('phone')
+    localStorage.removeItem('token')
+    localStorage.removeItem('user')
+    return next('/login')
+  }
+  if (to.path === '/') return next(token ? '/authorized/originality' : '/login')
+  next()
 })
 
 export default router

+ 6 - 0
src/types/Tool.d.ts

@@ -51,3 +51,9 @@ export interface AsProp {
   intervalType: number | undefined
   timeInterval: string
 }
+
+export interface menu {
+  title?: string
+  path?: string
+  children?: menu[]
+}

+ 255 - 0
src/views/ExaminePage.vue

@@ -0,0 +1,255 @@
+<!-- 素材列表页 -->
+<template>
+  <el-form :inline="true">
+    <el-form-item label="素材名称">
+      <el-input v-model="pages.keyword" placeholder="输入素材关键词" clearable />
+    </el-form-item>
+    <el-form-item label="选择创意">
+      <el-select
+        filterable
+        v-model="pages.creativeId"
+        placeholder="选择创意"
+        clearable
+        style="width: 240px"
+      >
+        <el-option
+          v-for="item in originalityList"
+          :key="item.creativeId"
+          :label="item.creativeName"
+          :value="item.creativeId"
+        />
+      </el-select>
+    </el-form-item>
+    <el-form-item>
+      <el-button type="primary" @click="onSubmit">搜索</el-button>
+    </el-form-item>
+  </el-form>
+
+  <el-table :data="tableData" stripe style="width: 100%">
+    <el-table-column prop="stuffName" label="名称" />
+    <el-table-column prop="stuffName" label="状态">
+      <template #default="scope">
+        {{ getStatus(scope.row.status) }}
+      </template>
+    </el-table-column>
+    <el-table-column prop="stuffName" label="创意">
+      <template #default="scope">
+        {{ OriginalityName(scope.row.creativeId) }}
+      </template>
+    </el-table-column>
+    <el-table-column prop="width" label="宽(px)" width="80" />
+    <el-table-column prop="height" label="高(px)" width="80" />
+    <el-table-column prop="landingPage" label="跳转地址" />
+    <el-table-column prop="updatedTime" label="最近更新">
+      <template #default="scope">
+        {{ formatDateSite(scope.row.updatedTime, 'Y-M-D') }}
+      </template>
+    </el-table-column>
+    <el-table-column label="操作">
+      <template #default="scope">
+        <el-popconfirm
+          title="确定通过该素材吗?"
+          v-if="scope.row.status == 0"
+          @confirm="changeStatus(scope.row.stuffId, 10, '审核成功')"
+        >
+          <template #reference>
+            <el-button link type="primary" size="small">通过</el-button>
+          </template>
+        </el-popconfirm>
+        <el-popconfirm
+          title="确定通过该素材吗?"
+          v-if="scope.row.status == 0"
+          @confirm="changeStatus(scope.row.stuffId, 3, '拒审成功')"
+        >
+          <template #reference>
+            <el-button link type="primary" size="small">不通过</el-button>
+          </template>
+        </el-popconfirm>
+      </template>
+    </el-table-column>
+  </el-table>
+  <br />
+  <el-pagination
+    background
+    layout="prev, pager, next"
+    :total="pages.total"
+    @current-change="page"
+  />
+
+  <el-dialog v-model="dialogVisible" title="素材">
+    <el-form ref="ruleFormRef" :rules="rules" :model="form" label-width="auto">
+      <el-form-item label="素材名称" prop="stuffName">
+        <el-input v-model="form.stuffName" />
+      </el-form-item>
+      <el-form-item label="选择创意" prop="creativeId">
+        <el-select filterable v-model="form.creativeId" placeholder="选择创意">
+          <el-option
+            v-for="item in originalityList"
+            :key="item.creativeId"
+            :label="item.creativeName"
+            :value="item.creativeId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="跳转地址" prop="landingPage">
+        <el-input v-model="form.landingPage" />
+      </el-form-item>
+      <el-form-item label="上传素材" prop="addr">
+        <MediaComponents
+          v-if="dialogVisible"
+          :src="form.addr || ''"
+          @change="(val: string) => (form.addr = val)"
+          @getCalc="getCalc"
+        />
+      </el-form-item>
+      <el-form-item label="宽(px)" prop="width">
+        <el-input-number v-model="form.width" :min="0" />
+      </el-form-item>
+      <el-form-item label="高(px)" prop="height">
+        <el-input-number v-model="form.height" :min="0" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="creatMaterial(ruleFormRef)">确定</el-button>
+        <el-button v-if="form.stuffId" type="primary" @click="addNewMaterial(ruleFormRef)">
+          添加到新创意
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import type { FormInstance, FormRules } from 'element-plus'
+import type { Pages } from '@/types/Tool'
+import type { OriginalityList } from '@/types/AdListPage'
+import type { SourceMaterialList, ISourceMaterialProps } from '@/types/SourceMaterial'
+import { formatDateSite, getStatus } from '@/tool/index'
+import { ElMessage } from 'element-plus'
+import {
+  getMaterialList,
+  getOriginalityList,
+  createMaterial,
+  updateMaterial,
+  updateMaterialStatus,
+} from '@/api/index'
+import { ref, reactive } from 'vue'
+
+import MediaComponents from '@/components/mediaComponents.vue'
+
+// vue3 获取url参数
+
+const ruleFormRef = ref<FormInstance>()
+const rules = reactive<FormRules<ISourceMaterialProps>>({
+  stuffName: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+  landingPage: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+  creativeId: [{ required: true, message: '请选择创意', trigger: 'change' }],
+  addr: [{ required: true, message: '请选择素材', trigger: 'change' }],
+  width: [{ required: true, message: '请输入宽', trigger: 'change' }],
+  height: [{ required: true, message: '请输入高', trigger: 'change' }],
+})
+const originalityList = ref<OriginalityList>([])
+getOriginalityList({
+  pageNum: 1,
+  pageSize: 999999,
+}).then(({ data }) => {
+  originalityList.value = data.records || {}
+})
+
+const dialogVisible = ref(false)
+const form = ref<ISourceMaterialProps>({
+  width: 0,
+  height: 0,
+})
+
+const pages = reactive<Pages>({
+  pageNum: 1,
+  pageSize: 10,
+  creativeId: undefined,
+})
+
+const tableData = ref<SourceMaterialList>([])
+
+const OriginalityName = (id: number) => {
+  const item = originalityList.value.find((item) => item.creativeId === id)
+  return item?.creativeName
+}
+
+const onSubmit = () => {
+  getMaterialList({
+    creativeId: pages.creativeId,
+    keyword: pages.keyword,
+    status: pages.status,
+    pageNum: pages.pageNum,
+    pageSize: pages.pageSize,
+  }).then(({ data }) => {
+    tableData.value = data.records
+    pages.total = data.total
+  })
+}
+
+const creatMaterial = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate((valid) => {
+    if (!valid) return
+    if (typeof form.value.stuffId === 'number') {
+      updateMaterial(form.value).then(() => {
+        ElMessage({
+          message: '更新成功',
+          type: 'success',
+        })
+        onSubmit()
+        dialogVisible.value = false
+      })
+      return
+    }
+    createMaterial(form.value).then(() => {
+      ElMessage({
+        message: '创建成功',
+        type: 'success',
+      })
+      onSubmit()
+      dialogVisible.value = false
+    })
+  })
+}
+
+const addNewMaterial = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate((valid) => {
+    if (!valid) return
+    const p = {
+      ...form.value,
+    }
+    delete p.stuffId
+    createMaterial(p).then(() => {
+      ElMessage({
+        message: '复制成功',
+        type: 'success',
+      })
+      onSubmit()
+      dialogVisible.value = false
+    })
+  })
+}
+
+const page = (val: number) => {
+  pages.pageNum = val
+  onSubmit()
+}
+
+const getCalc = (width: number, height: number) => {
+  form.value.width = width
+  form.value.height = height
+}
+
+const changeStatus = (id: number, status: number, text: string) => {
+  updateMaterialStatus({ id, status }).then(() => {
+    ElMessage.success(text)
+    onSubmit()
+  })
+}
+
+onSubmit()
+</script>
+
+<style></style>

+ 17 - 2
src/views/LoginPage.vue

@@ -5,7 +5,7 @@ import { ElMessage } from 'element-plus'
 
 import type { UserData } from '@/types/User'
 import type { FormInstance } from 'element-plus'
-import { getCaptcha, login } from '@/api/index'
+import { getCaptcha, login, getUserDetail } from '@/api/index'
 import { useRouter } from 'vue-router'
 
 const router = useRouter()
@@ -76,8 +76,23 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
           message: '登录成功',
           type: 'success',
         })
+
+        getUserDetail().then(({ data }) => {
+          localStorage.setItem('user', JSON.stringify(data))
+          const path = data.role.menus
+            ? data.role.menus[0].path !== '-1'
+              ? data.role.menus[0].path
+              : ''
+            : ''
+
+          if (path === '')
+            return ElMessage({
+              message: '暂无权限',
+              type: 'warning',
+            })
+          router.replace(path)
+        })
         localStorage.setItem('phone', form.value.phone || '')
-        router.replace('/authorized/originality')
       })
     }
   })

+ 21 - 39
src/views/SkeletonPage.vue

@@ -1,22 +1,17 @@
 <script setup lang="ts">
 // RouterLink
+import type { menu } from '@/types/Tool'
 import { ref } from 'vue'
 import { RouterView } from 'vue-router'
 import { useRouter, useRoute } from 'vue-router'
-import { getUserDetail } from '@/api/index'
-const token = localStorage.getItem('token')
-if (token)
-  getUserDetail().then(({ data }) => {
-    console.log(data.role.menus)
-    localStorage.setItem('user', JSON.stringify(data))
-  })
-
-const phone: string = localStorage.getItem('phone') || ''
-
 const router = useRouter()
 const route = useRoute()
+const deact = ref<string>(route.path)
+const user = JSON.parse(localStorage.getItem('user') || '{ role: { menus: [] } }')
 
-const deact = ref(route.path)
+const menu = ref<menu[]>(user.role.menus || [])
+
+const phone: string = localStorage.getItem('phone') || ''
 
 const handleSelect = (key: string) => {
   // 如果不是/开头的字符串则return
@@ -27,6 +22,7 @@ const handleSelect = (key: string) => {
 const loginout = () => {
   localStorage.removeItem('phone')
   localStorage.removeItem('token')
+  localStorage.removeItem('user')
   router.replace({ path: '/login' })
 }
 </script>
@@ -40,34 +36,20 @@ const loginout = () => {
         <el-button type="warning" @click="loginout" link> 退出 </el-button>
       </div>
       <el-menu :default-active="deact" @select="handleSelect">
-        <el-sub-menu index="no-1">
-          <template #title>
-            <span>广告</span>
-          </template>
-          <!-- <el-menu-item index="/authorized/adlist">广告计划</el-menu-item> -->
-          <el-menu-item index="/authorized/originality">广告创意</el-menu-item>
-          <el-menu-item index="/authorized/sourceMaterial">广告素材</el-menu-item>
-        </el-sub-menu>
-        <el-menu-item index="/authorized/site">
-          <span>站点</span>
-        </el-menu-item>
-        <el-menu-item index="/authorized/advertiser">
-          <span>广告主</span>
-        </el-menu-item>
-        <el-sub-menu index="3">
-          <template #title>
-            <span>广告位</span>
-          </template>
-          <el-menu-item index="/authorized/advertisingSpace">广告位</el-menu-item>
-          <el-menu-item index="/authorized/advertisingSpaceDate">广告位占用情况</el-menu-item>
-        </el-sub-menu>
-        <el-sub-menu index="4">
-          <template #title>
-            <span>报表</span>
-          </template>
-          <el-menu-item index="/authorized/reportForms">广告报表</el-menu-item>
-          <el-menu-item index="/authorized/reportSpaceForms">广告位报表</el-menu-item>
-        </el-sub-menu>
+        <template v-for="item in menu" :key="item.path">
+          <el-sub-menu index="no-1" v-if="item.children && item.children.length">
+            <template #title>
+              <span v-text="item.title"></span>
+            </template>
+            <!-- <el-menu-item index="/authorized/adlist">广告计划</el-menu-item> -->
+            <el-menu-item v-for="(v, i) in item.children" :index="v.path" :key="i">{{
+              v.title
+            }}</el-menu-item>
+          </el-sub-menu>
+          <el-menu-item v-else :index="item.path">
+            <span v-text="item.title"></span>
+          </el-menu-item>
+        </template>
       </el-menu>
     </el-aside>
     <el-main>