Commit 4da590b1 by tang

Merge branch 'master' of https://gitee.com/gs1-office-web-sit/gs1

parents b9d58637 e0767cb1
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "front",
"name": "gs1",
"version": "0.1.0",
"private": true,
"scripts": {
......@@ -39,7 +39,7 @@
"babel-plugin-component": "^1.1.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.13.0",
"node-sass": "^4.14.1",
"sass-loader": "^7.1.0",
"vue-cli-plugin-axios": "0.0.4",
"vue-cli-plugin-element": "^1.0.1",
......
......@@ -12,38 +12,17 @@ VueRouter.prototype.push = function push (to) {
const routes = [
{
path: "/user",
name: "user",
component: main,
redirect: "/user",
meta: {
icon: "el-icon-arrow-right",
name: "用户管理"
},
children: [
{
path: "/",
name: "user_index",
meta: {
name: "用户管理",
type: "sidebar"
},
component: () => import("@/views/user/index")
}
]
},
{
path:"/404",
name:"404",
component:() => import("@/views/user/404")
path: "/",
redirect: "/login"
},
{
path: "*",
redirect: "/404"
},
{
path: "/",
redirect: "/login"
path:"/404",
name:"404",
component:() => import("@/views/entry/404")
},
{
path: "/login",
......
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
# 中国物品编码中心官网
Business:业务大厅
Djwh :党建文化
User(entry): 会员中心
Home: 首页
Knowledge: 知识中心
Member: 成员
News:资讯中心
Org: 机构概况
Search: 条码查询
Service: 服务中心
\ No newline at end of file
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div></div>
</template>
<script>
</script>
<style lang="scss">
</style>
<template>
<div class="main-content">
<div class="content-query">
<el-form inline>
<el-form-item label="用户名称">
<el-input clearable v-model.trim="queryInfo.name" placeholder="请输入用户名称"></el-input>
</el-form-item>
<el-form-item label="联系电话">
<el-input clearable v-model.trim="queryInfo.mobile" placeholder="请输入联系电话"></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input clearable v-model.trim="queryInfo.idCard" placeholder="请输入身份证号"></el-input>
</el-form-item>
<el-form-item>
<el-button class="query" v-preventReClick @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
</div>
<div class="content-list">
<el-table
:data="dataList"
stripe
v-loading="loading"
element-loading-text="数据加载中..."
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255, 255, 255, 1)">
<el-table-column width="100px" label="用户编号">
<template slot-scope="scope">
<span class="row-index">{{scope.$index+1}}</span>
</template>
</el-table-column>
<el-table-column label="用户名称" prop="realName">
<template slot-scope="scope">
<span v-clipboard="scope.row.realName" v-clipboard:success="clipboardSuccess">{{scope.row.realName}}</span>
</template>
</el-table-column>
<el-table-column label="身份证号" prop="idCard">
<template slot-scope="scope">
<span v-clipboard="scope.row.idCard" v-clipboard:success="clipboardSuccess">{{scope.row.idCard}}</span>
</template>
</el-table-column>
<el-table-column label="联系电话" prop="mobile">
<template slot-scope="scope">
<span v-clipboard="scope.row.mobile" v-clipboard:success="clipboardSuccess">{{scope.row.mobile}}</span>
</template>
</el-table-column>
<el-table-column label="用户角色">
<template slot-scope="scope">
<span class="row-role" v-preventReClick @click="handleCheck(scope.row)">
{{scope.row.roleEdits|roleFilter}}
</span>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" :queryInfo="queryInfo" :inquireList="queryList"></Pagination>
</div>
<Dialog title="角色详情" :data="dialog.data" :isVisible="dialog.isShow" :callCancel="handleDialogCancel">
</Dialog>
</div>
</template>
<script>
import Pagination from "@/components/tool/pagination.vue"
import Dialog from "./userDetailDialog.vue"
import {
QUERY_PAGE_SIZE_20,
BlockRoleType,
BlockRoleSortIndex,
BlockRoleNameFromType
} from "@/config/constant.js"
export default {
components: {
Pagination,
Dialog
},
data() {
return {
loading: false,
queryInfo: {
pageIndex: 1,
pageSize: QUERY_PAGE_SIZE_20,
name: "",
mobile: "",
idCard: ""
},
total: 0,
dataList: [],
dialog: {
isShow: false,
data: {}
},
}
},
computed: {
},
methods: {
// 获取数据函数
async queryList() {
this.loading = true
const response = await this.$api.QueryUserListAsync(this.queryInfo)
this.loading = false
if (response.success) {
const { count = 0, data = [] } = response.data || {}
this.total = count
this.dataList = Object.freeze(data)
} else {
this.$message.error(response.returnMsg || "数据加载失败")
}
},
// 条件查询
handleSearch() {
this.queryInfo.pageIndex = 1
this.queryList()
},
handleCheck(row) {
this.dialog.data = row
this.dialog.isShow = true
},
handleDialogCancel() {
this.dialog.isShow = false
},
clipboardSuccess({ value }) {
if (!value) {
return
}
this.$notify({
title: '',
message: '拷贝成功',
type: 'success',
duration: 1500
})
}
},
filters: {
roleFilter: (roles) => {
if (roles && Array.isArray(roles) && roles.length > 0) {
return [...roles].sort((i1, i2) => {
if (BlockRoleSortIndex(i1.roleId) > BlockRoleSortIndex(i2.roleId)) return 1
else if (BlockRoleSortIndex(i1.roleId) === BlockRoleSortIndex(i2.roleId)) return 0
else return -1
}).map(item => {
return BlockRoleNameFromType(Number(item.roleId))
}).filter((item, index, arr) => {
return !!item && arr.indexOf(item, 0) === index
}).join('、')
}
return BlockRoleNameFromType(BlockRoleType.simple)
}
},
mounted() {
},
created() {
document.title = "链通万家 | 用户管理"
this.queryList()
}
}
</script>
<style lang="scss">
</style>
<template>
<div class="main-login">
<div class="login-content">
<h2><img src="../../assets/image/icon-login-logo.png" alt="">链通万家</h2>
<div class="qrcode-main">
<div class="qrcode-img" ref="qrcodeImg"></div>
<div :class="['qrcode-help', {'scanned': scanned}]">
<p class="error-cont center">二维码已扫描</p>
</div>
<div :class="['qrcode-help', {'agreed': agreed}]">
<p class="error-cont center">登录中...</p>
</div>
<div :class="['qrcode-help', {'cancelled': cancelled}]"
v-preventReClick
@click="resetQRCode">
<img src="../../assets/image/icon-qrcode-refresh.png" alt="">
<p class="error-cont">登录已取消</p>
</div>
<div :class="['qrcode-help', {'invalid': invalid}]"
v-preventReClick
@click="resetQRCode">
<img src="../../assets/image/icon-qrcode-refresh.png" alt="">
<p class="error-cont">二维码已失效</p>
</div>
<div :class="['qrcode-help', {'req_failed': requestFailed}]"
v-preventReClick
@click="resetQRCode">
<img src="../../assets/image/icon-qrcode-refresh.png" alt="">
<p class="error-cont">获取二维码失败</p>
</div>
</div>
<div class="tip-message">请使用微信小程序扫码登录</div>
</div>
</div>
</template>
<script>
import {
mapState,
mapActions
} from "vuex"
import QRCode from "qrcodejs2"
import { QrCodeStatus } from "@/config/constant"
export default {
data() {
return {
qrcodeInfo: {
qrcode: '',
token: '',
status: QrCodeStatus.ready
},
requestQRCodeFlag: true,
qrcode: null,
timer: null,
loopTime: 2000 // 2s
}
},
computed: {
...mapState({
token: state => state.user.token,
userMenus: state => state.user.userMenus
}),
invalid() {
return this.qrcodeInfo.status === QrCodeStatus.outdated
},
scanned() {
return this.qrcodeInfo.status === QrCodeStatus.scanned
},
cancelled() {
return this.qrcodeInfo.status === QrCodeStatus.cancelled
},
agreed() {
return this.qrcodeInfo.status === QrCodeStatus.agreed
},
requestFailed() {
return !this.requestQRCodeFlag && !this.qrcodeInfo.qrcode
}
},
methods: {
...mapActions("user", [
"SetUserTokenAction",
"SetUserInfoAction",
"SetUserMenusAction",
"CleanLoggedDataAction"
]),
...mapActions("industry", [
"SetIndustryBlockId"
]),
startLoop() {
this.stopLoop()
this.timer = setInterval(this.fetchQRCodeStatus, this.loopTime);
},
stopLoop() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
createQRCode() {
this.qrcode = new QRCode(this.$refs.qrcodeImg, {
width: 160,
height: 160,
colorDark: "#333333",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.L
})
},
async fetchQRCodeStatus() {
const response = await this.$api.GetQRCodeStatusAsync(this.qrcodeInfo.qrcode)
const resData = response.data || {}
const status = Number(resData.code)
this.qrcodeInfo.status = status
if (status === QrCodeStatus.cancelled || status === QrCodeStatus.outdated) {
this.stopLoop()
} else if (status === QrCodeStatus.agreed && resData.token) {
this.stopLoop()
this.handleLogin(resData)
}
},
async getQRCode() {
const response = await this.$api.GetQRCodeAsync()
this.requestQRCodeFlag = response.success && response.data
if (this.requestQRCodeFlag) {
this.qrcodeInfo = {
qrcode: response.data,
status: QrCodeStatus.ready
}
this.qrcode.makeCode(this.qrcodeInfo.qrcode)
this.$refs.qrcodeImg.title = ""
this.startLoop()
}
},
resetQRCode() {
this.qrcode.clear()
this.requestQRCodeFlag = true
this.qrcodeInfo.qrcode = ''
this.qrcodeInfo.status = QrCodeStatus.ready
this.getQRCode()
},
async handleLogin(data) {
const { token, userInfo, consoleMenus } = data || {}
console.log(token, userInfo, consoleMenus)
// 设置token
this.SetUserTokenAction(token)
// 设置用户信息
this.SetUserInfoAction(userInfo)
// 设置业委会成立小区ID
this.SetIndustryBlockId(userInfo.blockId)
// 设置菜单栏
this.SetUserMenusAction(consoleMenus.map(({name, url}) => {return { name, path: url }}))
// 进入主页
this.redirectHomePage()
},
redirectHomePage() {
const homeMenu = this.userMenus[0]
if (homeMenu && homeMenu.path) {
// 根据当前权限跳转到菜单栏第一个页面
this.$router.push({ path: homeMenu.path })
} else {
this.$router.push({ path: "/404" })
}
}
},
beforeDestroy() {
this.stopLoop()
},
created() {
document.title = "链通万家 | 登录"
},
mounted() {
const homeMenu = this.userMenus[0]
if (this.token && homeMenu && homeMenu.path) {
this.redirectHomePage()
} else {
this.CleanLoggedDataAction()
this.$nextTick(() => {
this.createQRCode()
this.getQRCode()
})
}
}
}
</script>
<style lang="scss" scoped>
$content-width: 320px;
$content-height: 350px;
$qrcode-width:160px;
$qrcode-height:160px;
.main-login {
width: 100%;
height: 100vh;
background: #DCDCDC;
background-image: url(../../assets/image/login-bg.jpg);
background-size: 100% 100%;
position: relative;
.login-content {
width: $content-width;
height: $content-height;
position: absolute;
right: 80px;
top: 130px;
padding: 0;
background: rgba(255,255,255,1.0);
opacity: 0.9;
border-radius: 30px;
box-shadow:0px 5px 16px 0px rgba(13,4,8,0.33);
text-align: center;
h2 {
margin: 30px auto;
font-size: 24px;
text-align: center;
color: #ffb73f;
font-weight:bold;
img {
width: 35px;
height: 35px;
margin-right: 8px;
}
}
.qrcode-main {
margin: 0 auto 30px;
width: $qrcode-width;
height: $qrcode-height;
.qrcode-img {
position: absolute;
display: inline-block;
background: rgba(250,250,250,0.9);
left: ceil(($content-width - $qrcode-width) / 2);
img {
width: $qrcode-width;
height: $qrcode-height;
background-color: lightgray;
}
}
.qrcode-help {
position: absolute;
width: $qrcode-width;
height: $qrcode-height;
background: rgba(250,250,250,0.9);
z-index: 9;
text-align: center;
display: none;
&.scanned,&.cancelled,&.invalid,&.agreed,&.req_failed {
display: block;
}
.error-cont {
color: #4C91B0;
font-size: 20px;
font-weight: 500;
margin-top: 5px;
&.center {
margin-top: 70px;
}
}
img {
margin: 20px auto 0px;
width: 80px;
height: 80px;
}
}
}
.tip-message{
color: #585858;
font-size:18px;
font-weight:bold;
}
}
}
</style>
<template>
<Dialog
width="650px"
:title="title"
:isVisible="isVisible"
:callOpen="handleOpen"
:callClose="handleClose"
:callCancel="callCancel">
<div class="user-detail-dialog__content" slot="content">
<div class="row-detail__item">
<span class="row-detail__item_title">用户名称:</span>
<span class="row-detail__item_text">{{userInfo.realName}}</span>
</div>
<div class="row-detail__item">
<span class="row-detail__item_title">联系电话:</span>
<span class="row-detail__item_text">{{userInfo.mobile}}</span>
</div>
<div class="row-detail__item">
<span class="row-detail__item_title">身份证号:</span>
<span class="row-detail__item_text">{{userInfo.idCard}}</span>
</div>
<div class="row-detail__item bottom">
<span class="row-detail__item_title roles">角色对应小区:</span>
<el-table max-height="250" class="row-detail__item_roles" :data="rolesData" border stripe>
<el-table-column label="角色名称">
<template slot-scope="scope">
{{scope.row.roleId | roleFormat}}
</template>
</el-table-column>
<el-table-column label="所属小区">
<template slot-scope="scope">
{{scope.row.blockName || '/'}}
</template>
</el-table-column>
<el-table-column label="楼栋">
<template slot-scope="scope">
{{scope.row.building}}
</template>
</el-table-column>
<el-table-column label="单元">
<template slot-scope="scope">
{{scope.row.unit}}
</template>
</el-table-column>
<el-table-column label="房号">
<template slot-scope="scope">
{{scope.row.room}}
</template>
</el-table-column>
</el-table>
</div>
</div>
</Dialog>
</template>
<script>
import Dialog from "@/components/tool/dialog.vue"
import {
BlockRoleSortIndex,
BlockRoleNameFromType
} from "@/config/constant.js"
export default{
components: {
Dialog
},
props:{
title: {
type: String,
default: ''
},
data: {
type: Object,
default: null
},
isVisible: {
type: Boolean,
default: false,
},
callCancel: {
type: Function
}
},
data() {
return {
userInfo: {
realName: '',
mobile: '',
idCard: ''
},
rolesData: null
}
},
filters: {
roleFormat: (roleId) => {
return BlockRoleNameFromType(Number(roleId))
}
},
methods:{
handleOpen() {
this.$nextTick(function() {
const data = this.data || {}
this.userInfo.realName = data.realName || ''
this.userInfo.mobile = data.mobile || ''
this.userInfo.idCard = data.idCard || ''
if (data.roleEdits && Array.isArray(data.roleEdits) && data.roleEdits.length > 0) {
this.rolesData = [...data.roleEdits].sort((i1, i2) => {
if (BlockRoleSortIndex(i1.roleId) > BlockRoleSortIndex(i2.roleId)) return 1
else if (BlockRoleSortIndex(i1.roleId) === BlockRoleSortIndex(i2.roleId)) return 0
else return -1
})
}
})
},
handleClose() {
this.$nextTick(function() {
this.userInfo.realName = ''
this.userInfo.mobile = ''
this.userInfo.idCard = ''
this.rolesData = null
})
},
},
mounted(){}
}
</script>
<style lang="scss">
.user-detail-dialog__content {
$item_height: 35px;
.row-detail__item {
&.bottom {
margin-bottom: 25px;
}
.row-detail__item_title {
margin-left: 100px;
color: #5C5C5C;
font-size: 14px;
font-weight: bold;
line-height: $item_height;
&.roles {
color: #868686;
font-size: 10px;
}
}
.row-detail__item_text {
margin-left: 20px;
color: #8A4E22;
font-size: 14px;
font-weight: 400;
line-height: $item_height;
}
.row-detail__item_roles {
width: 550px;
margin: 0 auto;
th {
background-color: #FFB73F;
padding: 1px 0;
text-align: center;
.cell {
font-size: 13px;
color: #8A4E22;
line-height: 35px;
}
}
td {
background-color: #fff;
padding: 1px 0;
text-align: center;
.cell {
font-size: 12px;
color: #5BACAB;
line-height: 30px;
}
}
}
}
}
</style>
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment