门店管理,分配门店

master
fy 2026-01-19 16:32:53 +08:00
parent 262611f77a
commit c03f4e2053
7 changed files with 235 additions and 44 deletions

View File

@ -134,3 +134,5 @@ export function deptTreeSelect() {
method: 'get' method: 'get'
}) })
} }

View File

@ -110,13 +110,27 @@ export const dynamicRoutes = [
path: '/system/role-auth', path: '/system/role-auth',
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:role:edit'], permissions: ['system:role:edits'],
children: [ children: [
{ {
path: 'user/:roleId(\\d+)', path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'), component: () => import('@/views/system/role/authUser'),
name: 'AuthUser', name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' } meta: { title: '分配用户', activeMenu: '/system/user' }
}
]
},
{
path: '/system/user-stores',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'auth/:userId(\\d+)',
component: () => import('@/views/system/user/userStores'),
name: 'UserStores',
meta: { title: '分配门店', activeMenu: '/system/user' }
} }
] ]
}, },

View File

@ -67,8 +67,8 @@ service.interceptors.request.use(config => {
} }
return config return config
}, error => { }, error => {
console.log(error) console.log(error)
Promise.reject(error) Promise.reject(error)
}) })
// 响应拦截器 // 响应拦截器
@ -89,10 +89,10 @@ service.interceptors.response.use(res => {
store.dispatch('LogOut').then(() => { store.dispatch('LogOut').then(() => {
location.href = '/index' location.href = '/index'
}) })
}).catch(() => { }).catch(() => {
isRelogin.show = false isRelogin.show = false
}) })
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) { } else if (code === 500) {
Message({ message: msg, type: 'error' }) Message({ message: msg, type: 'error' })

View File

@ -82,6 +82,7 @@
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['system:user:resetPwd']"></el-dropdown-item> <el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['system:user:resetPwd']"></el-dropdown-item>
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']"></el-dropdown-item> <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']"></el-dropdown-item>
<el-dropdown-item command="handleAuthStore" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']"></el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
@ -432,6 +433,9 @@ export default {
case "handleAuthRole": case "handleAuthRole":
this.handleAuthRole(row) this.handleAuthRole(row)
break break
case "handleAuthStore":
this.handleAuthStore(row)
break
default: default:
break break
} }
@ -486,6 +490,11 @@ export default {
const userId = row.userId const userId = row.userId
this.$router.push("/system/user-auth/role/" + userId) this.$router.push("/system/user-auth/role/" + userId)
}, },
/** 分配门店操作 */
handleAuthStore: function(row) {
const userId = row.userId
this.$router.push("/system/user-stores/auth/" + userId)
},
/** 提交按钮 */ /** 提交按钮 */
submitForm: function() { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {

View File

@ -0,0 +1,165 @@
<template>
<div class="app-container">
<h4 class="form-header h4">基本信息</h4>
<!-- <el-form ref="form" :model="form" label-width="80px">-->
<!-- <el-row>-->
<!-- <el-col :span="8" :offset="2">-->
<!-- <el-form-item label="用户昵称" prop="nickName">-->
<!-- <el-input v-model="form.nickName" disabled />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<!-- <el-col :span="8" :offset="2">-->
<!-- <el-form-item label="登录账号" prop="userName">-->
<!-- <el-input v-model="form.userName" disabled />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </el-form>-->
<h4 class="form-header h4">门店信息</h4>
<el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="table" @selection-change="handleSelectionChange" :data="(stores || []).slice((pageNum-1)*pageSize,pageNum*pageSize)">
<el-table-column label="序号" type="index" align="center">
<template slot-scope="scope">
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55" />
<el-table-column label="门店ID" align="center" prop="storeId" />
<el-table-column label="门店名称" align="center" prop="storeName" />
<el-table-column label="门店编码" align="center" prop="storeCode" />
<el-table-column label="联系电话" align="center" prop="contactPhone" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" />
<el-form label-width="100px">
<el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;">
<el-button type="primary" @click="submitForm"></el-button>
<el-button @click="close"></el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { storeApi } from '@/api/store'
import { parseTime } from "@/utils/ruoyi"
export default {
name: 'UserStores',
data() {
return {
//
loading: true,
//
total: 0,
pageNum: 1,
pageSize: 10,
//
storeIds: [],
//
stores: [],
//
form: {},
userId: '',
}
},
created() {
const userId = this.$route.params && this.$route.params.userId
if (userId) {
this.loading = true
storeApi.getUserStore(userId).then((response) => {
console.log("111111",response)
// API
const responseData = response.data.data || {}
//
this.form = responseData.user || {}
//
const associatedStores = responseData.stores || []
this.stores = responseData.allStores || []
this.userId =response.data.data.userId
this.total = this.stores.length
console.log("22222",this.stores)
console.log("关联门店:", associatedStores)
console.log("ididid----", this.userId)
// ID
const associatedStoreIds = associatedStores.map(store => store.storeId)
//
this.$nextTick(() => {
this.stores.forEach((row) => {
//
if (associatedStoreIds.includes(row.storeId)) {
this.$refs.table.toggleRowSelection(row, true)
}
})
})
this.loading = false
}).catch(error => {
console.error('获取门店信息失败:', error)
this.loading = false
})
}
},
methods: {
/** 单击选中行数据 */
clickRow(row) {
if (this.checkSelectable(row)) {
this.$refs.table.toggleRowSelection(row)
}
},
//
handleSelectionChange(selection) {
this.storeIds = selection.map((item) => item.storeId)
},
//
getRowKey(row) {
return row.storeId
},
// APIstatus
checkSelectable(row) {
return true
},
/** 提交按钮 */
submitForm() {
const userId = this.$route.params.userId
// Long
const storeIds = this.storeIds
console.log("00000000", userId)
console.log("99999",storeIds)
storeApi.updateUserStore({ userId: userId, storeIds: storeIds }).then(() => {
this.$message.success("授权成功")
this.close()
}).catch((error) => {
console.error('门店分配失败:', error)
this.$message.error("授权失败")
})
},
/** 关闭按钮 */
close() {
this.$router.push("/system/user")
},
//
parseTime
}
}
</script>
<style scoped>
.app-container {
padding: 20px;
}
.form-header {
border-bottom: 1px solid #ebeef5;
padding-bottom: 10px;
margin-bottom: 20px;
font-weight: 600;
}
</style>

View File

@ -11,7 +11,8 @@ const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const baseUrl = 'http://193.112.94.36:8080' // 后端接口 const baseUrl = 'http://193.112.94.36:8080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口 // const port = process.env.port || process.env.npm_config_port || 80 // 端口
const port = 8080
// vue.config.js 配置说明 // vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions //官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
@ -31,7 +32,7 @@ module.exports = {
// webpack-dev-server 相关配置 // webpack-dev-server 相关配置
devServer: { devServer: {
host: '0.0.0.0', host: '0.0.0.0',
port: 8087, port: port,
open: true, open: true,
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
@ -98,39 +99,39 @@ module.exports = {
.end() .end()
config.when(process.env.NODE_ENV !== 'development', config => { config.when(process.env.NODE_ENV !== 'development', config => {
config config
.plugin('ScriptExtHtmlWebpackPlugin') .plugin('ScriptExtHtmlWebpackPlugin')
.after('html') .after('html')
.use('script-ext-html-webpack-plugin', [{ .use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime` // `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/ inline: /runtime\..*\.js$/
}]) }])
.end() .end()
config.optimization.splitChunks({ config.optimization.splitChunks({
chunks: 'all', chunks: 'all',
cacheGroups: { cacheGroups: {
libs: { libs: {
name: 'chunk-libs', name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
priority: 10, priority: 10,
chunks: 'initial' // only package third parties that are initially dependent chunks: 'initial' // only package third parties that are initially dependent
}, },
elementUI: { elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package name: 'chunk-elementUI', // split elementUI into a single package
test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
}, },
commons: { commons: {
name: 'chunk-commons', name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number minChunks: 3, // minimum common number
priority: 5, priority: 5,
reuseExistingChunk: true reuseExistingChunk: true
} }
} }
}) })
config.optimization.runtimeChunk('single') config.optimization.runtimeChunk('single')
}) })
} }
} }