Browse Source

对接隐患流程, UI + 接口, 调整登录页面UI ,跳转title 等

master
DU 1 month ago
parent
commit
c6f56d1696
  1. 2
      .env.production
  2. 2
      .env.staging
  3. 2
      package.json
  4. 60
      src/api/flowable/hazardConfig.js
  5. 8
      src/layout/components/Sidebar/Logo.vue
  6. 614
      src/views/flowable/hazardConfig/index.vue
  7. 55
      src/views/login.vue

2
.env.production

@ -1,5 +1,5 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 陈山智慧油库 VUE_APP_TITLE = 积分管理系统
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'

2
.env.staging

@ -1,5 +1,5 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 积分管理系统
NODE_ENV = production NODE_ENV = production

2
package.json

@ -1,5 +1,5 @@
{ {
"name": "chenshan", "name": "jifenguanlixitong",
"version": "3.8.7", "version": "3.8.7",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",

60
src/api/flowable/hazardConfig.js

@ -0,0 +1,60 @@
import request from '@/utils/request'
export function listHazardFlowConfigs(params) {
return request({
url: '/flowable/hazardFlowConfig/list',
method: 'get',
params
})
}
export function getHazardFlowConfig(id) {
return request({
url: '/flowable/hazardFlowConfig/' + id,
method: 'get'
})
}
export function addHazardFlowConfig(data) {
return request({
url: '/flowable/hazardFlowConfig',
method: 'post',
data
})
}
export function updateHazardFlowConfig(data) {
return request({
url: '/flowable/hazardFlowConfig',
method: 'put',
data
})
}
export function deleteHazardFlowConfig(id) {
return request({
url: '/flowable/hazardFlowConfig/' + id,
method: 'delete'
})
}
export function listMyFactoryHazardFlowConfigs() {
return request({
url: '/flowable/hazardFlowConfig/myFactoryConfigs',
method: 'get'
})
}
export function listFactoryDepartments() {
return request({
url: '/system/dept/factoryList',
method: 'get'
})
}
export function getMyFactoryDepartment() {
return request({
url: '/system/dept/myFactory',
method: 'get'
})
}

8
src/layout/components/Sidebar/Logo.vue

@ -2,10 +2,12 @@
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<transition name="sidebarLogoFade"> <transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <!-- <img v-if="logo" :src="logo" class="sidebar-logo" /> -->
<span class="sidebar-title"> 管理端</span>
</router-link> </router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/"> <router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <!-- <img v-if="logo" :src="logo" class="sidebar-logo" /> -->
<span class="sidebar-title"> 随手拍积分商城 · 管理端</span>
</router-link> </router-link>
</transition> </transition>
</div> </div>
@ -76,7 +78,7 @@ export default {
& .sidebar-title { & .sidebar-title {
display: inline-block; display: inline-block;
margin: 0; margin: 0;
color: #fff; color: #666;
font-weight: 600; font-weight: 600;
line-height: 52px; line-height: 52px;
font-size: 14px; font-size: 14px;

614
src/views/flowable/hazardConfig/index.vue

@ -1,9 +1,619 @@
<template> <template>
<div class="app-container"></div> <div class="app-container hazard-flow-config-page">
<data-list-panel>
<template #filters>
<el-form
v-show="showSearch"
ref="queryForm"
:model="queryParams"
size="small"
:inline="true"
class="data-list-filter-form"
>
<el-form-item label="厂区" prop="deptId">
<el-select
v-model="queryParams.deptId"
:disabled="!isSuperAdmin"
:loading="factoryLoading"
clearable
filterable
placeholder="全部厂区"
>
<el-option
v-for="item in displayedFactoryOptions"
:key="factoryId(item)"
:label="factoryName(item)"
:value="factoryId(item)"
/>
</el-select>
</el-form-item>
<el-form-item label="隐患等级" prop="hazardLevel">
<el-select
v-model="queryParams.hazardLevel"
clearable
placeholder="全部隐患等级"
>
<el-option
v-for="item in levelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
clearable
placeholder="全部状态"
>
<el-option label="正常" value="1" />
<el-option label="停用" value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button>
<el-button
icon="el-icon-refresh"
size="mini"
@click="resetQuery"
>重置</el-button>
</el-form-item>
</el-form>
</template>
<template #actions>
<div class="data-list-actions">
<el-button
type="primary"
size="small"
icon="el-icon-plus"
@click="handleAdd"
>新增</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-edit"
:disabled="single"
:loading="detailLoading"
@click="handleUpdate()"
>修改</el-button>
<el-button
type="danger"
size="small"
icon="el-icon-delete"
:disabled="multiple"
@click="handleDelete()"
>删除</el-button>
<right-toolbar
:show-search.sync="showSearch"
@queryTable="getList"
/>
</div>
</template>
<!-- <template #header>
<div class="config-heading">
<div class="config-heading__title">隐患流程模板配置</div>
<div class="config-heading__description">
按厂区和隐患等级绑定对应的 Flowable 流程模板。
</div>
</div>
</template> -->
<el-table
v-loading="loading"
:data="configList"
row-key="id"
class="data-list-table"
empty-text="暂无流程模板配置"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column
prop="id"
label="配置编号"
width="100"
align="center"
/>
<el-table-column
prop="deptName"
label="厂区名称"
min-width="130"
show-overflow-tooltip
>
<template slot-scope="scope">
{{ scope.row.deptName || scope.row.deptId || '-' }}
</template>
</el-table-column>
<el-table-column label="隐患等级" width="130" align="center">
<template slot-scope="scope">
<el-tag :type="levelTagType(scope.row.hazardLevel)" size="small">
{{ levelLabel(scope.row) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="flowKey"
label="流程 Key"
min-width="190"
show-overflow-tooltip
/>
<el-table-column
prop="flowName"
label="流程名称"
min-width="220"
show-overflow-tooltip
>
<template slot-scope="scope">
{{ scope.row.flowName || '-' }}
</template>
</el-table-column>
<el-table-column label="状态" width="130" align="center">
<template slot-scope="scope">
<el-tag
:type="statusValue(scope.row.status) === '1' ? 'success' : 'info'"
size="small"
>
{{ statusValue(scope.row.status) === '1' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
label="操作"
width="160"
align="center"
fixed="right"
class-name="data-list-operation-column"
>
<template slot-scope="scope">
<el-button
size="mini"
:loading="detailLoadingId === scope.row.id"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
type="danger"
size="mini"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div class="scope-note">
管理员可查看/配置所有厂区;厂区二级管理员仅能查看本厂区配置(数据范围「本部门」自动过滤)。隐患上报时后端根据「用户所属厂区 + 隐患等级」自动匹配对应 flowKey 启动流程。
</div>
</template>
</data-list-panel>
<el-dialog
:title="dialogTitle"
:visible.sync="dialogVisible"
width="620px"
append-to-body
:close-on-click-modal="false"
>
<el-form
ref="configForm"
:model="form"
:rules="formRules"
label-width="92px"
size="small"
class="config-form"
>
<el-row :gutter="16">
<el-col :xs="24" :sm="12">
<el-form-item label="厂区" prop="deptId">
<el-select
v-model="form.deptId"
:disabled="dialogMode === 'edit' || !isSuperAdmin"
:loading="factoryLoading"
filterable
placeholder="请选择厂区"
style="width: 100%"
>
<el-option
v-for="item in displayedFactoryOptions"
:key="factoryId(item)"
:label="factoryName(item)"
:value="factoryId(item)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12">
<el-form-item label="隐患等级" prop="hazardLevel">
<el-select
v-model="form.hazardLevel"
:disabled="dialogMode === 'edit'"
placeholder="请选择隐患等级"
style="width: 100%"
>
<el-option
v-for="item in levelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12">
<el-form-item label="流程 Key" prop="flowKey">
<el-input
v-model.trim="form.flowKey"
maxlength="100"
placeholder="请输入 Flowable 流程定义 Key"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12">
<el-form-item label="流程名称" prop="flowName">
<el-input
v-model.trim="form.flowName"
maxlength="100"
placeholder="请输入流程名称"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="状态" prop="status">
<el-switch
v-model="form.status"
active-value="1"
inactive-value="0"
active-text="正常"
inactive-text="停用"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="submitForm">
确定
</el-button>
</span>
</el-dialog>
</div>
</template> </template>
<script> <script>
import {
addHazardFlowConfig,
deleteHazardFlowConfig,
getHazardFlowConfig,
getMyFactoryDepartment,
listFactoryDepartments,
listHazardFlowConfigs,
updateHazardFlowConfig
} from '@/api/flowable/hazardConfig'
const LEVEL_OPTIONS = [
{ value: 'general', label: '一般隐患' },
{ value: 'major', label: '较大隐患' },
{ value: 'critical', label: '重大隐患' }
]
export default { export default {
name: 'HazardFlowConfig' name: 'HazardFlowConfig',
data() {
const validateDept = (rule, value, callback) => {
if (this.isSuperAdmin && !value) {
callback(new Error('请选择厂区'))
return
}
callback()
}
return {
showSearch: true,
loading: false,
factoryLoading: false,
detailLoading: false,
detailLoadingId: undefined,
saving: false,
total: 0,
configList: [],
selectedRows: [],
single: true,
multiple: true,
factoryOptions: [],
currentFactory: null,
levelOptions: LEVEL_OPTIONS,
dialogVisible: false,
dialogMode: 'add',
dialogTitle: '新增流程模板配置',
queryParams: {
pageNum: 1,
pageSize: 10,
deptId: undefined,
hazardLevel: undefined,
status: undefined
},
form: this.createEmptyForm(),
formRules: {
deptId: [{ validator: validateDept, trigger: 'change' }],
hazardLevel: [
{ required: true, message: '请选择隐患等级', trigger: 'change' }
],
flowKey: [
{ required: true, message: '请输入流程 Key', trigger: 'blur' }
]
}
}
},
computed: {
isSuperAdmin() {
return (this.$store.getters.roles || []).indexOf('admin') !== -1
},
displayedFactoryOptions() {
if (this.isSuperAdmin) return this.factoryOptions
return this.currentFactory ? [this.currentFactory] : []
}
},
created() {
this.getList()
this.loadFactoryScope()
},
methods: {
createEmptyForm() {
return {
id: undefined,
deptId: '',
deptName: '',
hazardLevel: '',
hazardLevelName: '',
flowKey: '',
flowName: '',
status: '1'
}
},
unwrapData(response) {
return response && response.data !== undefined ? response.data : response
},
getList() {
this.loading = true
const params = Object.assign({}, this.queryParams)
if (!this.isSuperAdmin) delete params.deptId
listHazardFlowConfigs(params)
.then(response => {
const page = this.unwrapData(response) || {}
this.configList = Array.isArray(page.list) ? page.list : []
this.total = Number(page.total) || 0
})
.catch(() => {
this.configList = []
this.total = 0
this.$modal.msgError('流程模板配置加载失败')
})
.finally(() => {
this.loading = false
})
},
loadFactoryScope() {
this.factoryLoading = true
const request = this.isSuperAdmin
? listFactoryDepartments()
: getMyFactoryDepartment()
request
.then(response => {
const data = this.unwrapData(response)
if (this.isSuperAdmin) {
this.factoryOptions = Array.isArray(data)
? data
: (data && (data.list || data.rows)) || []
return
}
this.currentFactory = data || null
if (this.currentFactory) {
this.queryParams.deptId = this.factoryId(this.currentFactory)
}
})
.catch(() => {
this.factoryOptions = []
this.currentFactory = null
this.$modal.msgError('厂区信息加载失败')
})
.finally(() => {
this.factoryLoading = false
})
},
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
resetQuery() {
this.resetForm('queryForm')
if (!this.isSuperAdmin && this.currentFactory) {
this.queryParams.deptId = this.factoryId(this.currentFactory)
}
this.handleQuery()
},
handleSelectionChange(selection) {
this.selectedRows = selection
this.single = selection.length !== 1
this.multiple = selection.length === 0
},
handleAdd() {
this.dialogMode = 'add'
this.dialogTitle = '新增流程模板配置'
this.form = this.createEmptyForm()
if (!this.isSuperAdmin && this.currentFactory) {
this.form.deptId = this.factoryId(this.currentFactory)
this.form.deptName = this.factoryName(this.currentFactory)
}
this.dialogVisible = true
this.$nextTick(() => this.$refs.configForm.clearValidate())
},
handleUpdate(row) {
const target = row || this.selectedRows[0]
if (!target || target.id === undefined || target.id === null) return
this.detailLoading = true
this.detailLoadingId = target.id
getHazardFlowConfig(target.id)
.then(response => {
const detail = this.unwrapData(response) || target
this.form = this.normalizeForm(Object.assign({}, target, detail))
this.dialogMode = 'edit'
this.dialogTitle = '修改流程模板配置'
this.dialogVisible = true
this.$nextTick(() => this.$refs.configForm.clearValidate())
})
.catch(() => {
this.$modal.msgError('流程模板配置详情加载失败')
})
.finally(() => {
this.detailLoading = false
this.detailLoadingId = undefined
})
},
normalizeForm(data) {
return {
id: data.id,
deptId: data.deptId === undefined || data.deptId === null
? ''
: String(data.deptId),
deptName: data.deptName || '',
hazardLevel: data.hazardLevel || '',
hazardLevelName: data.hazardLevelName || '',
flowKey: data.flowKey || '',
flowName: data.flowName || '',
status: this.statusValue(data.status)
}
},
submitForm() {
this.$refs.configForm.validate(valid => {
if (!valid) return
const payload = this.buildPayload(this.form)
const request = this.dialogMode === 'edit'
? updateHazardFlowConfig(payload)
: addHazardFlowConfig(payload)
this.saving = true
request
.then(() => {
this.$modal.msgSuccess(
this.dialogMode === 'edit' ? '修改成功' : '新增成功'
)
this.dialogVisible = false
this.getList()
})
.finally(() => {
this.saving = false
})
})
},
buildPayload(source) {
const payload = {
id: source.id,
deptId: source.deptId,
deptName: source.deptName,
hazardLevel: source.hazardLevel,
hazardLevelName: this.levelName(source.hazardLevel),
flowKey: source.flowKey,
flowName: source.flowName || undefined,
status: this.statusValue(source.status)
}
const factory = this.displayedFactoryOptions.find(
item => this.factoryId(item) === String(payload.deptId || '')
)
if (factory) payload.deptName = this.factoryName(factory)
if (this.dialogMode === 'add') delete payload.id
if (this.dialogMode === 'add' && !this.isSuperAdmin) {
delete payload.deptId
delete payload.deptName
}
return payload
},
handleDelete(row) {
const rows = row && row.id !== undefined ? [row] : this.selectedRows
const ids = rows
.map(item => item.id)
.filter(id => id !== undefined && id !== null)
if (!ids.length) return
const message = ids.length === 1
? '确认删除该流程模板配置吗?'
: '确认删除选中的 ' + ids.length + ' 条流程模板配置吗?'
this.$modal.confirm(message)
.then(() => Promise.all(ids.map(id => deleteHazardFlowConfig(id))))
.then(() => {
this.$modal.msgSuccess('删除成功')
this.getList()
})
},
factoryId(item) {
const value = item && (item.deptId !== undefined ? item.deptId : item.id)
return value === undefined || value === null ? '' : String(value)
},
factoryName(item) {
return (item && (item.deptName || item.label || item.name)) || ''
},
levelName(value) {
const item = this.levelOptions.find(option => option.value === value)
return item ? item.label : value || '-'
},
levelLabel(row) {
return row.hazardLevelName || this.levelName(row.hazardLevel)
},
levelTagType(value) {
return {
general: '',
major: 'warning',
critical: 'danger'
}[value] || 'info'
},
statusValue(value) {
return String(value) === '0' ? '0' : '1'
}
}
} }
</script> </script>
<style lang="scss" scoped>
.config-heading__title {
color: var(--prototype-text, #1a1a2e);
font-size: 14px;
font-weight: 600;
}
.config-heading__description {
margin-top: 4px;
color: var(--prototype-text-secondary, #6b7280);
font-size: 12px;
font-weight: 400;
}
.scope-note {
margin-top: 10px;
padding: 9px 12px;
// border-left: 3px solid var(--prototype-primary, #1890ff);
// background: var(--prototype-panel-soft, #fafbfc);
color: var(--prototype-text-secondary, #6b7280);
font-size: 12px;
line-height: 20px;
}
::v-deep .config-form .el-form-item {
margin-bottom: 18px;
}
@media (max-width: 768px) {
::v-deep .el-dialog {
width: calc(100% - 24px) !important;
}
}
</style>

55
src/views/login.vue

@ -7,7 +7,7 @@
<div class="container" @keyup.enter="handleLogin"> <div class="container" @keyup.enter="handleLogin">
<div class="loginBox"> <div class="loginBox">
<div class="loginDiv" :style="{ height: captchaEnabled ? '445px' : '370px'}"> <div class="loginDiv" :style="{ height: captchaEnabled ? '445px' : '370px'}">
<div class="loginname">智慧油库系统</div> <div class="loginname">积分管理系统</div>
<el-input v-model="loginForm.username" class="username" type="text" placeholder="请输入用户名"> <el-input v-model="loginForm.username" class="username" type="text" placeholder="请输入用户名">
<template #prepend style="padding: 0;"> <template #prepend style="padding: 0;">
<i class="el-icon-user" style="color: #fff; font-size: 25px;"></i> <i class="el-icon-user" style="color: #fff; font-size: 25px;"></i>
@ -141,30 +141,31 @@ export default {
.container { .container {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: url('../assets/images/loginbg.jpg') no-repeat; min-height: 100vh;
background-size: 100% 100%; overflow: auto;
background: #061354 url('../assets/images/loginbg.jpg') no-repeat center;
background-size: cover;
} }
.loginBox { .loginBox {
background: url("../assets/images/loginbox.png") no-repeat center bottom; background: url("../assets/images/loginbox.png") no-repeat center bottom;
width: 1920px; width: 100%;
height: 1080px; min-height: 100%;
position: absolute; padding: 24px 16px;
top: 0; display: flex;
right: 0; align-items: center;
margin-left: -699px; justify-content: center;
z-index: 1; z-index: 1;
background-size: 100%; background-size: cover;
.loginDiv { .loginDiv {
width: 550px; width: 550px;
max-width: 100%;
flex: 0 0 auto;
height: 370px; height: 370px;
color: #fff; color: #fff;
background: #07226f; background: #07226f;
position: relative; position: relative;
top: 240px;
left: 50%;
transform: translateX(-50%);
border-radius: 15px; border-radius: 15px;
background: background:
radial-gradient(circle at 100% 100%, transparent 13px, #2dfdff 0) top left, radial-gradient(circle at 100% 100%, transparent 13px, #2dfdff 0) top left,
@ -224,7 +225,15 @@ export default {
} }
.login-code-img { .login-code-img {
display: block;
width: 100%;
height: 50px; height: 50px;
object-fit: fill;
cursor: pointer;
}
.login-code {
min-width: 0;
flex: 1;
} }
.code { .code {
display: flex; display: flex;
@ -280,4 +289,24 @@ export default {
background: #f09253; background: #f09253;
} }
} }
@media (max-width: 600px) {
.loginBox {
padding: 16px;
.loginDiv {
padding-right: 24px;
padding-left: 24px;
.loginname {
margin-bottom: 20px;
font-size: 28px;
}
}
.login_btn {
width: 100%;
}
}
}
</style> </style>

Loading…
Cancel
Save