第一版联调

main
ysn 4 days ago
parent 8dc209f8fc
commit 0dd4edec04
  1. 4
      .env.development
  2. 14
      src/api/knowledge.js
  3. 20
      src/api/login.js
  4. 4
      src/layout/components/Navbar.vue
  5. 28
      src/store/modules/permission.js
  6. 27
      src/store/modules/user.js
  7. 66
      src/utils/request.js
  8. 179
      src/views/knowledge/index.vue
  9. 62
      src/views/login.vue
  10. 23
      vue.config.js

@ -4,8 +4,8 @@ VUE_APP_TITLE = 信联
# 开发环境配置
ENV = 'development'
# 信联/开发环境
VUE_APP_BASE_API = '/dev-api'
# 修改为你真实的接口前缀
VUE_APP_BASE_API = '/api_admin/v1'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

@ -1,13 +1,18 @@
import request from '@/utils/request'
// 获取知识库左侧分类列表
export function getKnowledgeCateList(data) {
return request({ url: '/v1/knowledge/cate/list', method: 'post', data })
}
// 获取知识库右侧列表
export function getKnowledgeList(data) {
return request({ url: '/v1/knowledge/list', method: 'post', data })
}
export function createKnowledge(data) {
return request({ url: '/api/v1/knowledge/create', method: 'post', data })
}
export function getKnowledgeList(data) {
return request({ url: '/api/v1/knowledge/list', method: 'post', data })
}
export function playKnowledge(data) {
return request({ url: '/api/v1/knowledge/play', method: 'post', data })
@ -33,6 +38,3 @@ export function deleteKnowledgeCate(data) {
return request({ url: '/api/v1/knowledge/cate/delete', method: 'post', data })
}
export function getKnowledgeCateList(data) {
return request({ url: '/api/v1/knowledge/cate/list', method: 'post', data })
}

@ -1,19 +1,9 @@
import request from '@/utils/request'
// 登录方法
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
export function login(data) {
return request({
url: '/login',
headers: {
isToken: false,
repeatSubmit: false
},
url: '/auth/login/access-token',
method: 'post',
data: data
})
@ -34,8 +24,8 @@ export function register(data) {
// 获取用户详细信息
export function getInfo() {
return request({
url: '/getInfo',
method: 'get'
url: '/users/detail',
method: 'POST'
})
}
@ -51,7 +41,7 @@ export function unlockScreen(password) {
// 退出方法
export function logout() {
return request({
url: '/logout',
url: '/auth/logout',
method: 'post'
})
}

@ -60,13 +60,13 @@
icon="el-icon-circle-check"
:underline="false"
>
{{ selectDictLabel(dict.type.sys_normal_disable, status) || "-" }}
{{ status }}
</el-link>
</span>
<span class="user-nickname">
所属单位
<el-link type="primary" :underline="false">
{{ dept.deptName }}
{{ dept }}
</el-link>
</span>
</div>

@ -33,20 +33,20 @@ const permission = {
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes)
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes)
})
// getRouters().then(res => {
// const sdata = JSON.parse(JSON.stringify(res.data))
// const rdata = JSON.parse(JSON.stringify(res.data))
// const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter([], false, true)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes)
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(asyncRoutes))
commit('SET_DEFAULT_ROUTES', asyncRoutes)
commit('SET_TOPBAR_ROUTES', asyncRoutes)
resolve(rewriteRoutes)
// })
})
}
}

@ -53,14 +53,11 @@ const user = {
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
login(userInfo).then(res => {
console.log(res)
setToken(res.data.token)
commit('SET_TOKEN', res.data.token)
store.dispatch('lock/unlockScreen')
resolve()
}).catch(error => {
@ -73,7 +70,7 @@ const user = {
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const user = res.user
const user = res.data
let avatar = user.avatar || ""
if (!isHttp(avatar)) {
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
@ -88,20 +85,20 @@ const user = {
commit('SET_NAME', user.userName)
commit('SET_NICK_NAME', user.nickName)
commit('SET_AVATAR', avatar)
commit('SET_DEPT', user.dept)
commit('SET_DEPT', user.grp_name)
commit('SET_STATUS', user.status)
cache.session.set('pwrChrtype', res.pwdChrtype)
/* 初始密码提示 */
if(res.isDefaultModifyPwd) {
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
if (res.isDefaultModifyPwd) {
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
}).catch(() => {})
}).catch(() => { })
}
/* 过期密码提示 */
if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
if (!res.isDefaultModifyPwd && res.isPasswordExpired) {
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
}).catch(() => {})
}).catch(() => { })
}
resolve(res)
}).catch(error => {

@ -29,7 +29,7 @@ service.interceptors.request.use(config => {
// 间隔时间(ms),小于此时间视为重复提交
const interval = (config.headers || {}).interval || 1000
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
config.headers['x-token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
@ -68,46 +68,46 @@ service.interceptors.request.use(config => {
}
return config
}, error => {
console.log(error)
Promise.reject(error)
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false
store.dispatch('LogOut').then(() => {
location.href = '/index'
})
// 未设置状态码则默认成功状态
const code = res.data.code || 200
// 获取错误信息
const msg = errorCode[code] || res.data.message || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false
store.dispatch('LogOut').then(() => {
location.href = '/index'
})
}).catch(() => {
isRelogin.show = false
})
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
Message({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
Message({ message: msg, type: 'warning' })
return Promise.reject('error')
} else if (code !== 200) {
Notification.error({ title: msg })
return Promise.reject('error')
} else {
return res.data
}
},
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500 || code === 901) {
Message({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
Message({ message: msg, type: 'warning' })
return Promise.reject('error')
} else if (code !== 200) {
Notification.error({ title: msg })
return Promise.reject('error')
} else {
return res.data
}
},
error => {
console.log('err' + error)
let { message } = error

@ -4,19 +4,20 @@
<!-- 左侧分类菜单 -->
<el-col :span="6">
<el-form>
<el-form-item prop="userName">
<el-form-item prop="name">
<el-input
v-model="deptFilterText"
v-model="queryLeftParams.name"
placeholder="输入部门名称过滤"
clearable
size="small"
prefix-icon="el-icon-search"
@keyup.enter.native="getKnowledgeCateList"
>
<template slot="append">
<el-button
slot="append"
icon="el-icon-refresh-right"
@click="refreshMenu"
@click="refreshKnowledgeCateList"
/>
</template>
</el-input>
@ -25,14 +26,14 @@
<el-menu :default-active="defaultActive" @select="handleSelect">
<!-- 内置标签 -->
<el-menu-item
v-for="(dept, index) in builtInDepts"
v-for="(item, index) in systemCateList"
:key="`built-in-${index}`"
:index="`built-in-${index}`"
class="custom-item"
>
<div class="left">
<i :class="getBuiltInIcon(index)" />
<span>{{ dept.label }}</span>
<span>{{ item.name }}</span>
</div>
<!-- 内置标签无操作按钮 -->
</el-menu-item>
@ -45,7 +46,7 @@
>
<div class="left">
<i class="el-icon-collection-tag" />
<span>{{ dept.label }}</span>
<span>{{ dept.name }}</span>
</div>
<div class="right">
<el-button
@ -73,15 +74,15 @@
<el-col :span="18">
<!-- 搜索区域 -->
<el-form
:model="queryParams"
:model="queryRightParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="文件名称" prop="userName">
<el-form-item label="文件名称" prop="file_name">
<el-input
v-model="queryParams.userName"
v-model="queryRightParams.file_name"
placeholder="请输入文件名称"
clearable
style="width: 240px"
@ -115,16 +116,16 @@
<el-table v-loading="loading" :data="userList">
<el-table-column
label="缩略图"
prop="thumbnail"
prop="thumbnail_path"
align="center"
v-if="columns.thumbnail.visible"
v-if="columns.thumbnail_path.visible"
width="250"
>
<template slot-scope="scope">
<el-image
class="resource-thumb"
:src="
scope.row.thumbnail || defaultThumbnail(scope.row.fileType)
scope.row.thumbnail_path || defaultthumbnail_path(scope.row.fileType)
"
fit="contain"
@click="handlePreview(scope.row)"
@ -136,8 +137,8 @@
<el-table-column
label="文件名"
align="center"
prop="userName"
v-if="columns.userName.visible"
prop="file_name"
v-if="columns.file_name.visible"
:show-overflow-tooltip="true"
/>
<el-table-column
@ -197,8 +198,8 @@
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
:page.sync="queryRightParams.pageNum"
:limit.sync="queryRightParams.pageSize"
@pagination="getList"
/>
</el-col>
@ -245,9 +246,9 @@
ref="fileNameFormRef"
label-width="80px"
>
<el-form-item label="文件名称" prop="userName">
<el-form-item label="文件名称" prop="file_name">
<el-input
v-model="fileNameForm.userName"
v-model="fileNameForm.file_name"
placeholder="请输入文件名称"
show-word-limit
maxlength="8"
@ -324,6 +325,9 @@
</template>
<script>
import { getKnowledgeCateList, getKnowledgeList } from "@/api/knowledge";
import { listUser, delUser, deptTreeSelect } from "@/api/system/user";
import { getToken } from "@/utils/auth";
import CreateGroupDialog from "@/views/message/components/CreateGroupDialog";
@ -331,33 +335,34 @@ import CreateGroupDialog from "@/views/message/components/CreateGroupDialog";
export default {
name: "Knowledge",
components: {
CreateGroupDialog
CreateGroupDialog,
},
data() {
return {
loading: true,
total: 0,
userList: [],
showSearch: true,
queryParams: {
defaultActive: "",
queryLeftParams: {
name: "",
},
systemCateList: [],
userCateList: [],
queryRightParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
deptId: undefined,
total: 0,
},
columns: {
thumbnail: { label: "缩略图", visible: true },
userName: { label: "文件名", visible: true },
thumbnail_path: { label: "缩略图", visible: true },
file_name: { label: "文件名", visible: true },
createTime: { label: "上传时间", visible: true },
fileSize: { label: "文件大小", visible: true },
},
list: [],
loading: true,
userList: [],
showSearch: true,
deptFilterText: "",
deptOptions: [],
builtInDepts: [
{ label: "海信产品介绍", id: "built-in-0" },
{ label: "公共教学视频", id: "built-in-1" },
{ label: "个人收藏录像", id: "built-in-2" },
],
currentTag: "",
//
tagDialogVisible: false,
@ -370,9 +375,9 @@ export default {
},
//
fileNameDialogVisible: false,
fileNameForm: { userId: undefined, userName: "" },
fileNameForm: { userId: undefined, file_name: "" },
fileNameRules: {
userName: [
file_name: [
{ required: true, message: "文件名不能为空", trigger: "blur" },
],
},
@ -406,20 +411,86 @@ export default {
},
},
created() {
this.getList();
this.getDeptTree();
this.getContactList();
this.getKnowledgeCateList();
// this.getList();
// this.getDeptTree();
// this.getContactList();
},
methods: {
refreshMenu() {
this.deptFilterText = "";
this.getDeptTree();
refreshKnowledgeCateList() {
this.queryLeftParams.name = "";
this.getKnowledgeCateList();
},
getKnowledgeCateList() {
// getKnowledgeCateList().then((res) => {
let res = {
code: 200,
message: "成功",
data: {
system_cate_list: [
{ id: 2, name: "产品介绍" },
{ id: 0, name: "公共教学视频" },
{ id: 1, name: "个人收藏录像" },
],
user_cate_list: [],
},
};
this.systemCateList = res.data.system_cate_list;
this.defaultActive = this.systemCateList[0].id;
this.userCateList = res.data.user_cate_list;
// })
},
handleSelect(key) {
console.log(key);
// const [type, idx] = key.split("-");
// this.currentTag =
// type === "built-in"
// ? this.systemCateList[idx].id
// : this.filteredCustomDeptList[idx]?.id;
this.queryRightParams.deptId = this.currentTag;
this.handleQuery();
},
getKnowledgeList() {
// getKnowledgeList(this.queryRightParams).then((res) => {
let res = {
code: 200,
message: "成功",
data: {
list: [
{
id: 824,
title: "1633500241136.mp4",
thumbnail_path_path:
"personal-test/video/688/1779759317/1633500241136.png",
file_path: "personal-test/video/688/1779759317/1633500241136.mp4",
file_name: "1633500241136.mp4",
file_type: "MP4",
file_size: 18794616,
true_file_size: 18796714,
creator_id: 688,
play_times: 0,
is_mine: 1,
cate_id: 152,
description: "",
del_flag: 0,
create_time: "2026-05-26 09:35:14",
update_time: "2026-05-26 09:35:14",
},
],
total: 1,
is_mine: 0,
cate_id: 152,
},
};
this.list = res.data.list;
this.queryRightParams.total = res.data.total;
// })
},
getContactList() {
listUser({ pageNum: 1, pageSize: 100 }).then((res) => {
this.recentContacts = res.rows.map((user) => ({
id: user.userId,
name: user.nickName || user.userName,
name: user.nickName || user.file_name,
avatar: user.avatar || "",
}));
});
@ -435,7 +506,7 @@ export default {
getFileIcon(t) {
return t === "video" ? "el-icon-video-play" : "el-icon-document";
},
defaultThumbnail(t) {
defaultthumbnail_path(t) {
return t === "video"
? "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
: "https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3794312f7670b85636.jpeg";
@ -451,15 +522,7 @@ export default {
}
return s.toFixed(2) + u[i];
},
handleSelect(key) {
const [type, idx] = key.split("-");
this.currentTag =
type === "built-in"
? this.builtInDepts[idx].id
: this.filteredCustomDeptList[idx]?.id;
this.queryParams.deptId = this.currentTag;
this.handleQuery();
},
handleAddTag() {
this.tagForm = { id: null, label: "" };
this.tagDialogVisible = true;
@ -477,7 +540,7 @@ export default {
.then(() => {
this.$modal.msgSuccess("删除成功");
this.getDeptTree();
this.migrateResource(tag.id, this.builtInDepts[2].id);
this.migrateResource(tag.id, this.systemCateList[2].id);
})
.catch(() => {});
},
@ -485,7 +548,7 @@ export default {
migrateResource(oldDeptId, newDeptId) {
this.getList();
},
submitTagForm() {
submitTagForm() {
this.$refs["tagFormRef"].validate((valid) => {
if (valid) {
if (this.tagForm.id) {
@ -504,18 +567,18 @@ export default {
this.tagDialogVisible = false;
},
handleQuery() {
this.queryParams.pageNum = 1;
this.queryRightParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.queryParams.deptId = null;
this.queryRightParams.deptId = null;
this.currentTag = "";
this.handleQuery();
},
getList() {
this.loading = true;
listUser(this.queryParams).then((res) => {
listUser(this.queryRightParams).then((res) => {
this.userList = res.rows;
this.total = res.total;
this.loading = false;
@ -579,7 +642,7 @@ export default {
},
//
beforeUpload(file) {
this.uploadParams.deptId = this.currentTag || this.builtInDepts[2].id;
this.uploadParams.deptId = this.currentTag || this.systemCateList[2].id;
this.uploadParams.fileType = this.currentFileType;
this.uploadProgressDialogVisible = true;
this.uploadPercent = 0;

@ -62,24 +62,6 @@
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" />
</div>
</el-form-item>
<el-form-item>
<el-checkbox v-model="loginForm.rememberMe"> 自动登录 </el-checkbox>
</el-form-item>
@ -127,10 +109,9 @@
</div>
</template>
<script>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import CryptoJS from "crypto-js";
export default {
name: "Login",
data() {
@ -138,12 +119,10 @@ export default {
//
roleName: "会诊专家", // ,
roleIconText: "家", //
codeUrl: "",
loginForm: {
username: "hzzjys",
password: "",
rememberMe: false,
code: "",
uuid: "",
},
loginRules: {
@ -155,7 +134,6 @@ export default {
],
},
loading: false,
captchaEnabled: true,
redirect: undefined,
showSettingsDialog: false,
settingsForm: {
@ -174,21 +152,13 @@ export default {
},
},
created() {
this.getCode();
this.getCookie();
//
// this.getRoleInfo();
// this.handleLogin();
},
methods: {
getCode() {
getCodeImg().then((res) => {
this.captchaEnabled =
res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
}
});
// Qt CEncrypt::DataEncryptMD5
md5Encrypt(str) {
return CryptoJS.MD5(str).toString();
},
getCookie() {
const username = Cookies.get("username");
@ -200,6 +170,7 @@ export default {
password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
this.handleLogin();
},
handleLogin() {
this.$refs.loginForm.validate((valid) => {
@ -219,15 +190,17 @@ export default {
Cookies.remove("rememberMe");
}
this.$store
.dispatch("Login", this.loginForm)
.dispatch("Login", {
username: this.loginForm.username,
password: this.md5Encrypt(this.loginForm.password),
psign: this.md5Encrypt("xycloud_" + this.loginForm.password),
version: "V01.01.16",
})
.then(() => {
this.$router.push({ path: this.redirect || "/" }).catch(() => {});
})
.catch(() => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
});
}
});
@ -387,17 +360,6 @@ export default {
margin-left: 2px;
color: #009696;
}
.login-code {
width: 33%;
height: 36px;
float: right;
img {
height: 36px;
cursor: pointer;
vertical-align: middle;
}
}
}
}
}

@ -9,7 +9,10 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '信联' // 网页标题
const baseUrl = 'http://vue.ruoyi.vip/prod-api' // 后端接口
// const baseUrl = 'http://www.haiteriot.com:13002' // 后端接口
const baseUrl = 'http://47.92.6.51:8005' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口
@ -34,14 +37,16 @@ module.exports = {
port: port,
open: true,
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: baseUrl,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
},
// 匹配环境变量里的接口前缀
[process.env.VUE_APP_BASE_API]: {
// 替换成你的真实后端地址,比如 http://localhost:8080
target: baseUrl,
changeOrigin: true,
// 关键:注释或删除 pathRewrite,不再去掉前缀
// pathRewrite: {
// ['^' + process.env.VUE_APP_BASE_API]: ''
// }
},
// springdoc proxy
'^/v3/api-docs/(.*)': {
target: baseUrl,

Loading…
Cancel
Save