root 3 lat temu
rodzic
commit
054e582892

+ 6 - 6
src/api/user.js

@@ -56,9 +56,9 @@ export function getInfo(token) {
   })
 }
 
-export function logout() {
-  return request({
-    url: '/vue-element-admin/user/logout',
-    method: 'post'
-  })
-}
+// export function logout() {
+//   return request({
+//     url: '/vue-element-admin/user/logout',
+//     method: 'post'
+//   })
+// }

+ 2 - 0
src/lang/en.js

@@ -1,6 +1,8 @@
 export default {
   route: {
     dashboard: 'Dashboard',
+    shop: 'Mall management',
+    indexShop: 'Shop List',
     documentation: 'Documentation',
     guide: 'Guide',
     permission: 'Permission',

+ 2 - 0
src/lang/es.js

@@ -1,6 +1,8 @@
 export default {
   route: {
     dashboard: 'Panel de control',
+    shop: 'Mall management',
+    indexShop: 'Shop List',
     documentation: 'Documentación',
     guide: 'Guía',
     permission: 'Permisos',

+ 2 - 0
src/lang/ja.js

@@ -1,6 +1,8 @@
 export default {
   route: {
     dashboard: 'トップ',
+    shop: 'Mall management',
+    indexShop: 'Shop List',
     documentation: 'ドキュメント',
     guide: 'ガイド',
     permission: '権限',

+ 2 - 0
src/lang/zh.js

@@ -1,6 +1,8 @@
 export default {
   route: {
     dashboard: '首页',
+    shop: '商城管理',
+    indexShop: '商品管理',
     documentation: '文档',
     guide: '引导页',
     permission: '权限测试页',

+ 3 - 4
src/permission.js

@@ -28,7 +28,6 @@ router.beforeEach(async(to, from, next) => {
     } else {
       // determine whether the user has obtained his permission roles through getInfo
       const hasRoles = store.getters.roles && store.getters.roles.length > 0
-      console.log('ssss', hasRoles)
       if (hasRoles) {
         next()
       } else {
@@ -37,12 +36,13 @@ router.beforeEach(async(to, from, next) => {
           // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
           // const { roles } = await store.dispatch('user/getInfo')
           const { roles } = ['admin'];
+         
           // generate accessible routes map based on roles
           const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
           // dynamically add accessible routes
-          
-          // router.addRoutes(accessRoutes)
+          console.log(accessRoutes)
           selfAddRoutes(accessRoutes)
+          // selfAddRoutes(accessRoutes)
 
           // hack method to ensure that addRoutes is complete
           // set the replace: true, so the navigation will not leave a history record
@@ -59,7 +59,6 @@ router.beforeEach(async(to, from, next) => {
     }
   } else {
     /* has no token*/
-alert('no token')
     if (whiteList.indexOf(to.path) !== -1) {
       // in the free login whitelist, go directly
       next()

+ 24 - 0
src/router/index.js

@@ -130,6 +130,29 @@ export const constantRoutes = [
  * the routes that need to be dynamically loaded based on user roles
  */
 export const asyncRoutes = [
+  {
+    path: '/shop',
+    component: Layout,
+    redirect: '/shop/index',
+    // alwaysShow: true,
+    name: 'Shop',
+    meta: {
+      title: 'shop',
+      icon: 'edit',
+      // roles: ['admin', 'editor']
+    },
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/shop/index'),
+        name: 'IndexShop',
+        meta: {
+          title: 'indexShop',
+          roles: ['admin', 'editor'] // or you can only set roles in sub nav
+        }
+      }
+    ]
+  },
   {
     path: '/permission',
     component: Layout,
@@ -405,6 +428,7 @@ const createRouter = () => new Router({
   // mode: 'history', // require service support
   scrollBehavior: () => ({ y: 0 }),
   routes: constantRoutes.concat(asyncRoutes)
+  // routes: constantRoutes.concat(asyncRoutes)
 })
 
 const router = createRouter()

+ 60 - 42
src/store/modules/user.js

@@ -124,53 +124,71 @@ const actions = {
     })
   },
 
-  // get user info
-  getInfo({ commit, state }) {
-    return new Promise((resolve, reject) => {
-      getInfo(state.token).then(response => {
-        const { data } = response
-
-        if (!data) {
-          reject('Verification failed, please Login again.')
-        }
-
-        const { roles, name, avatar, introduction } = data
-
-        // roles must be a non-empty array
-        if (!roles || roles.length <= 0) {
-          reject('getInfo: roles must be a non-null array!')
-        }
-
-        commit('SET_ROLES', roles)
-        commit('SET_NAME', name)
-        commit('SET_AVATAR', avatar)
-        commit('SET_INTRODUCTION', introduction)
-        resolve(data)
-      }).catch(error => {
-        reject(error)
-      })
-    })
-  },
-
   // user logout
   logout({ commit, state, dispatch }) {
     return new Promise((resolve, reject) => {
-      logout(state.token).then(() => {
-        commit('SET_TOKEN', '')
-        commit('SET_ROLES', [])
-        removeToken()
-        resetRouter()
-
-        // reset visited views and cached views
-        // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
-        dispatch('tagsView/delAllViews', null, { root: true })
-
-        resolve()
-      }).catch(error => {
-        reject(error)
-      })
+      commit('SET_TOKEN', '')
+      commit('SET_ROLES', [])
+      localClear()
+      localBaseData()
+      removeToken()
+      resetRouter()
+      // reset visited views and cached views
+      // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
+      dispatch('tagsView/delAllViews', null, { root: true })
+      resolve()
     })
   },
+
+  // // get user info
+  // getInfo({ commit, state }) {
+  //   return new Promise((resolve, reject) => {
+  //     getInfo(state.token).then(response => {
+  //       const { data } = response
+
+  //       if (!data) {
+  //         reject('Verification failed, please Login again.')
+  //       }
+
+  //       const { roles, name, avatar, introduction } = data
+
+  //       // roles must be a non-empty array
+  //       if (!roles || roles.length <= 0) {
+  //         reject('getInfo: roles must be a non-null array!')
+  //       }
+
+  //       commit('SET_ROLES', roles)
+  //       commit('SET_NAME', name)
+  //       commit('SET_AVATAR', avatar)
+  //       commit('SET_INTRODUCTION', introduction)
+  //       resolve(data)
+  //     }).catch(error => {
+  //       reject(error)
+  //     })
+  //   })
+  // },
+
+  
+
+  // // user logout
+  // logout({ commit, state, dispatch }) {
+  //   return new Promise((resolve, reject) => {
+  //     logout(state.token).then(() => {
+  //       commit('SET_TOKEN', '')
+  //       commit('SET_ROLES', [])
+  //       removeToken()
+  //       resetRouter()
+
+  //       // reset visited views and cached views
+  //       // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
+  //       dispatch('tagsView/delAllViews', null, { root: true })
+
+  //       resolve()
+  //     }).catch(error => {
+  //       reject(error)
+  //     })
+  //   })
+  // },
   // remove token
   resetToken({ commit }) {
     return new Promise(resolve => {

+ 2 - 0
src/utils/localUserInfo.js

@@ -101,6 +101,8 @@ export function clear() {
   localStorage.removeItem('loginTimestamp')
   localStorage.removeItem('baseData')
   localStorage.removeItem('baseInfo')
+  localStorage.removeItem('MenuPrmStore')
+  localStorage.removeItem('roleList')
 }
 
 export function clearBaseInfo() {

+ 380 - 0
src/views/shop/index.vue

@@ -0,0 +1,380 @@
+<template>
+    <div class="app-container">
+      <div class="filter-container">
+        <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
+        <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item">
+          <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" />
+        </el-select>
+        <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px">
+          <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" />
+        </el-select>
+        <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter">
+          <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" />
+        </el-select>
+        <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
+          {{ $t('table.search') }}
+        </el-button>
+        <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
+          {{ $t('table.add') }}
+        </el-button>
+        <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
+          {{ $t('table.export') }}
+        </el-button>
+        <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
+          {{ $t('table.reviewer') }}
+        </el-checkbox>
+      </div>
+  
+      <el-table
+        :key="tableKey"
+        v-loading="listLoading"
+        :data="list"
+        border
+        fit
+        highlight-current-row
+        style="width: 100%;"
+        @sort-change="sortChange"
+      >
+        <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')">
+          <template slot-scope="{row}">
+            <span>{{ row.id }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.date')" width="150px" align="center">
+          <template slot-scope="{row}">
+            <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.title')" min-width="150px">
+          <template slot-scope="{row}">
+            <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span>
+            <el-tag>{{ row.type | typeFilter }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.author')" width="110px" align="center">
+          <template slot-scope="{row}">
+            <span>{{ row.author }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center">
+          <template slot-scope="{row}">
+            <span style="color:red;">{{ row.reviewer }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.importance')" width="80px">
+          <template slot-scope="{row}">
+            <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" />
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.readings')" align="center" width="95">
+          <template slot-scope="{row}">
+            <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
+            <span v-else>0</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.status')" class-name="status-col" width="100">
+          <template slot-scope="{row}">
+            <el-tag :type="row.status | statusFilter">
+              {{ row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width">
+          <template slot-scope="{row,$index}">
+            <el-button type="primary" size="mini" @click="handleUpdate(row)">
+              {{ $t('table.edit') }}
+            </el-button>
+            <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')">
+              {{ $t('table.publish') }}
+            </el-button>
+            <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')">
+              {{ $t('table.draft') }}
+            </el-button>
+            <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)">
+              {{ $t('table.delete') }}
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+  
+      <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+  
+      <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+        <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;">
+          <el-form-item :label="$t('table.type')" prop="type">
+            <el-select v-model="temp.type" class="filter-item" placeholder="Please select">
+              <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
+            </el-select>
+          </el-form-item>
+          <el-form-item :label="$t('table.date')" prop="timestamp">
+            <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" />
+          </el-form-item>
+          <el-form-item :label="$t('table.title')" prop="title">
+            <el-input v-model="temp.title" />
+          </el-form-item>
+          <el-form-item :label="$t('table.status')">
+            <el-select v-model="temp.status" class="filter-item" placeholder="Please select">
+              <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
+            </el-select>
+          </el-form-item>
+          <el-form-item :label="$t('table.importance')">
+            <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" />
+          </el-form-item>
+          <el-form-item :label="$t('table.remark')">
+            <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" />
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">
+            {{ $t('table.cancel') }}
+          </el-button>
+          <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
+            {{ $t('table.confirm') }}
+          </el-button>
+        </div>
+      </el-dialog>
+  
+      <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
+        <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
+          <el-table-column prop="key" label="Channel" />
+          <el-table-column prop="pv" label="Pv" />
+        </el-table>
+        <span slot="footer" class="dialog-footer">
+          <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button>
+        </span>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
+  import waves from '@/directive/waves' // waves directive
+  import { parseTime } from '@/utils'
+  import Pagination from '@/components/Pagination' // secondary package based on el-pagination
+  
+  const calendarTypeOptions = [
+    { key: 'CN', display_name: 'China' },
+    { key: 'US', display_name: 'USA' },
+    { key: 'JP', display_name: 'Japan' },
+    { key: 'EU', display_name: 'Eurozone' }
+  ]
+  
+  // arr to obj, such as { CN : "China", US : "USA" }
+  const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
+    acc[cur.key] = cur.display_name
+    return acc
+  }, {})
+  
+  export default {
+    name: 'IndexShop',
+    components: { Pagination },
+    directives: { waves },
+    filters: {
+      statusFilter(status) {
+        const statusMap = {
+          published: 'success',
+          draft: 'info',
+          deleted: 'danger'
+        }
+        return statusMap[status]
+      },
+      typeFilter(type) {
+        return calendarTypeKeyValue[type]
+      }
+    },
+    data() {
+      return {
+        tableKey: 0,
+        list: null,
+        total: 0,
+        listLoading: true,
+        listQuery: {
+          page: 1,
+          limit: 20,
+          importance: undefined,
+          title: undefined,
+          type: undefined,
+          sort: '+id'
+        },
+        importanceOptions: [1, 2, 3],
+        calendarTypeOptions,
+        sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
+        statusOptions: ['published', 'draft', 'deleted'],
+        showReviewer: false,
+        temp: {
+          id: undefined,
+          importance: 1,
+          remark: '',
+          timestamp: new Date(),
+          title: '',
+          type: '',
+          status: 'published'
+        },
+        dialogFormVisible: false,
+        dialogStatus: '',
+        textMap: {
+          update: 'Edit',
+          create: 'Create'
+        },
+        dialogPvVisible: false,
+        pvData: [],
+        rules: {
+          type: [{ required: true, message: 'type is required', trigger: 'change' }],
+          timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
+          title: [{ required: true, message: 'title is required', trigger: 'blur' }]
+        },
+        downloadLoading: false
+      }
+    },
+    created() {
+      this.getList()
+    },
+    methods: {
+      getList() {
+        this.listLoading = true
+        fetchList(this.listQuery).then(response => {
+          this.list = response.data.items
+          this.total = response.data.total
+  
+          // Just to simulate the time of the request
+          setTimeout(() => {
+            this.listLoading = false
+          }, 1.5 * 1000)
+        })
+      },
+      handleFilter() {
+        this.listQuery.page = 1
+        this.getList()
+      },
+      handleModifyStatus(row, status) {
+        this.$message({
+          message: '操作成功',
+          type: 'success'
+        })
+        row.status = status
+      },
+      sortChange(data) {
+        const { prop, order } = data
+        if (prop === 'id') {
+          this.sortByID(order)
+        }
+      },
+      sortByID(order) {
+        if (order === 'ascending') {
+          this.listQuery.sort = '+id'
+        } else {
+          this.listQuery.sort = '-id'
+        }
+        this.handleFilter()
+      },
+      resetTemp() {
+        this.temp = {
+          id: undefined,
+          importance: 1,
+          remark: '',
+          timestamp: new Date(),
+          title: '',
+          status: 'published',
+          type: ''
+        }
+      },
+      handleCreate() {
+        this.resetTemp()
+        this.dialogStatus = 'create'
+        this.dialogFormVisible = true
+        this.$nextTick(() => {
+          this.$refs['dataForm'].clearValidate()
+        })
+      },
+      createData() {
+        this.$refs['dataForm'].validate((valid) => {
+          if (valid) {
+            this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
+            this.temp.author = 'vue-element-admin'
+            createArticle(this.temp).then(() => {
+              this.list.unshift(this.temp)
+              this.dialogFormVisible = false
+              this.$notify({
+                title: '成功',
+                message: '创建成功',
+                type: 'success',
+                duration: 2000
+              })
+            })
+          }
+        })
+      },
+      handleUpdate(row) {
+        this.temp = Object.assign({}, row) // copy obj
+        this.temp.timestamp = new Date(this.temp.timestamp)
+        this.dialogStatus = 'update'
+        this.dialogFormVisible = true
+        this.$nextTick(() => {
+          this.$refs['dataForm'].clearValidate()
+        })
+      },
+      updateData() {
+        this.$refs['dataForm'].validate((valid) => {
+          if (valid) {
+            const tempData = Object.assign({}, this.temp)
+            tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
+            updateArticle(tempData).then(() => {
+              const index = this.list.findIndex(v => v.id === this.temp.id)
+              this.list.splice(index, 1, this.temp)
+              this.dialogFormVisible = false
+              this.$notify({
+                title: '成功',
+                message: '更新成功',
+                type: 'success',
+                duration: 2000
+              })
+            })
+          }
+        })
+      },
+      handleDelete(row, index) {
+        this.$notify({
+          title: '成功',
+          message: '删除成功',
+          type: 'success',
+          duration: 2000
+        })
+        this.list.splice(index, 1)
+      },
+      handleFetchPv(pv) {
+        fetchPv(pv).then(response => {
+          this.pvData = response.data.pvData
+          this.dialogPvVisible = true
+        })
+      },
+      handleDownload() {
+        this.downloadLoading = true
+        import('@/vendor/Export2Excel').then(excel => {
+          const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
+          const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
+          const data = this.formatJson(filterVal)
+          excel.export_json_to_excel({
+            header: tHeader,
+            data,
+            filename: 'table-list'
+          })
+          this.downloadLoading = false
+        })
+      },
+      formatJson(filterVal) {
+        return this.list.map(v => filterVal.map(j => {
+          if (j === 'timestamp') {
+            return parseTime(v[j])
+          } else {
+            return v[j]
+          }
+        }))
+      },
+      getSortClass: function(key) {
+        const sort = this.listQuery.sort
+        return sort === `+${key}` ? 'ascending' : 'descending'
+      }
+    }
+  }
+  </script>
+