diff --git a/package.json b/package.json
index f4882f6f4e605516c45da63f8cc52b1f9a77a8e3..cefc95b54e728c748a033653995f56d8c106cde9 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"qrcodejs2-fixes": "^0.0.2",
"qs": "^6.11.0",
"sortablejs": "^1.15.0",
+ "v-code-diff": "^1.8.0",
"vue": "^3.3.4",
"vue-clipboard3": "^2.0.0",
"vue-cropper": "1.0.2",
diff --git a/src/api/system/user.js b/src/api/system/user.js
index b3477bf9c944585211bae537103243438ba69225..8ae212d4fa8dd3aeed4be4185d96f4c1c21fabce 100644
--- a/src/api/system/user.js
+++ b/src/api/system/user.js
@@ -22,7 +22,7 @@ export function getUser(userId) {
// 新增用户
export function addUser(data) {
return request({
- url: '/system/user/edit',
+ url: '/system/user/add',
method: 'post',
data: data
})
diff --git a/src/assets/icons/svg/emailLog.svg b/src/assets/icons/svg/emailLog.svg
new file mode 100644
index 0000000000000000000000000000000000000000..5cb5987468453710e54c512641f2893135b7d4ba
--- /dev/null
+++ b/src/assets/icons/svg/emailLog.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/emailSend.svg b/src/assets/icons/svg/emailSend.svg
new file mode 100644
index 0000000000000000000000000000000000000000..41155d34ca16ebc5378c6aa34ea2945ccf40310c
--- /dev/null
+++ b/src/assets/icons/svg/emailSend.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss
index d399128d86504bd663c50eea5169086f3f149445..ad06e971bbf4881c576f6687c1635d3f5534ad08 100644
--- a/src/assets/styles/sidebar.scss
+++ b/src/assets/styles/sidebar.scss
@@ -91,16 +91,3 @@
}
}
}
-
-// when menu collapsed
-.el-menu--vertical {
- // the scroll bar appears when the subMenu is too long
- > .el-menu--popup {
- max-height: 100vh;
- overflow-y: auto;
-
- &::-webkit-scrollbar {
- width: 6px;
- }
- }
-}
diff --git a/src/components/DictTag/index.vue b/src/components/DictTag/index.vue
index 407a1d711081447bb5cb4b9af0f0999fe55c370f..556dd84ff6f2876ce37cd1efccdeac153f9a1dff 100644
--- a/src/components/DictTag/index.vue
+++ b/src/components/DictTag/index.vue
@@ -1,5 +1,5 @@
-
+
@@ -42,9 +42,28 @@ const props = defineProps({
split: {
type: String,
default: null
+ },
+ //自定义属性值 例如:{ label: 'name', value: 'id'}
+ config: {
+ type: Object,
+ default: null
}
})
+const dataList = computed(() => {
+ if (props.config) {
+ let config = props.config
+ var newList = []
+
+ for (let d of props.options) {
+ let label = d[config.label]
+ let value = d[config.value]
+ newList.push({ dictLabel: label, dictValue: value, ...d })
+ }
+ return newList
+ }
+ return props.options
+})
const values = computed(() => {
if (props.value !== null && typeof props.value !== 'undefined') {
if (props.split != null && props.split != '') {
diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue
index b6dfe92af459c4eca32e1ba986a0e307a74799d1..732c10cf61a312cb0fe8710575b6e7e513403785 100644
--- a/src/components/HeaderSearch/index.vue
+++ b/src/components/HeaderSearch/index.vue
@@ -68,12 +68,17 @@ function close() {
}
function change(val) {
const path = val.path
+ const query = val.query
if (isHttp(path)) {
// http(s):// 路径新窗口打开
const pindex = path.indexOf('http')
window.open(path.substr(pindex, path.length), '_blank')
} else {
- router.push(path)
+ if (query) {
+ router.push({ path: path, query: JSON.parse(query) })
+ } else {
+ router.push(path)
+ }
}
search.value = ''
@@ -104,7 +109,7 @@ function initFuse(list) {
}
// Filter out the routes that can be displayed in the sidebar
// And generate the internationalized title
-function generateRoutes(routes, basePath = '', prefixTitle = []) {
+function generateRoutes(routes, basePath = '', prefixTitle = [], query = {}) {
let res = []
for (const r of routes) {
@@ -130,6 +135,9 @@ function generateRoutes(routes, basePath = '', prefixTitle = []) {
res.push(data)
}
}
+ if (r.query) {
+ data.query = r.query
+ }
// recursive child routes
if (r.children) {
diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue
index 9a8300a31dbaa77d9d077c622265f5b61ff62a91..9fd5cb3c1fd96447b39c294c5dc42b467b1270e2 100644
--- a/src/components/TopNav/index.vue
+++ b/src/components/TopNav/index.vue
@@ -126,7 +126,13 @@ function handleSelect(key, keyPath) {
window.open(key, '_blank')
} else if (!route || !route.children) {
// 没有子路由路径内部打开
- router.push({ path: key })
+ const routeMenu = childrenMenus.value.find((item) => item.path === key)
+ if (routeMenu && routeMenu.query) {
+ let query = JSON.parse(routeMenu.query)
+ router.push({ path: key, query: query })
+ } else {
+ router.push({ path: key })
+ }
appStore.toggleSideBarHide(true)
} else {
// 显示左侧联动菜单
diff --git a/src/layout/components/IframeToggle/index.vue b/src/layout/components/IframeToggle/index.vue
index 464d0ddf0cca9df64c1bac038a14b28e1e43b533..1e5727c04761a9dbde8c12acf883f3c8e72db0b7 100644
--- a/src/layout/components/IframeToggle/index.vue
+++ b/src/layout/components/IframeToggle/index.vue
@@ -5,7 +5,8 @@
:key="item.path"
:iframeId="'iframe' + index"
v-show="route.path === item.path"
- :src="item.meta.link">
+ :src="iframeUrl(item.meta.link, item.query)">
+
@@ -15,4 +16,14 @@ import useTagsViewStore from '@/store/modules/tagsView'
const route = useRoute()
const tagsViewStore = useTagsViewStore()
+
+function iframeUrl(url, query) {
+ if (Object.keys(query).length > 0) {
+ let params = Object.keys(query)
+ .map((key) => key + '=' + query[key])
+ .join('&')
+ return url + '?' + params
+ }
+ return url
+}
diff --git a/src/utils/ruoyi.js b/src/utils/ruoyi.js
index decde9c89edd2dcf54526d413a09d157f2fff9a8..3ce6e73ebc6452126b0040146eda58eba5d046a5 100644
--- a/src/utils/ruoyi.js
+++ b/src/utils/ruoyi.js
@@ -180,6 +180,29 @@ export function handleTree(data, id, parentId, children) {
}
return tree
}
+/**
+ * 将自定义数据转换成字典
+ * @param {*} data 数据源
+ * @param {*} dictLabel dictLabel
+ * @param {*} dictValue dictValue
+ */
+export function toDict(data, dictLabel, dictValue) {
+ let config = {
+ label: dictLabel || 'dictLabel',
+ value: dictValue || 'dictValue'
+ }
+
+ var tree = []
+
+ for (let d of data) {
+ let label = d[config.label]
+ let value = d[config.value]
+
+ tree.push({ dictLabel: label, dictValue: value })
+ }
+
+ return tree
+}
/**
* 参数处理
diff --git a/src/views/login.vue b/src/views/login.vue
index f113b57d789aed00e5f4281f80c12919d92f7fe1..8375a8938337017db89b04b1102c7a6781385f25 100644
--- a/src/views/login.vue
+++ b/src/views/login.vue
@@ -123,6 +123,13 @@ fpPromise
visitorId = result.visitorId
userStore.setClientId(visitorId)
})
+watch(
+ route,
+ (newRoute) => {
+ redirect.value = newRoute.query && newRoute.query.redirect
+ },
+ { immediate: true }
+)
function handleLogin() {
proxy.$refs.loginRef.validate((valid) => {
if (valid) {
@@ -143,7 +150,14 @@ function handleLogin() {
.login(loginForm.value)
.then(() => {
proxy.$modal.msgSuccess(proxy.$t('login.loginSuccess'))
- router.push({ path: redirect.value || '/' })
+ const query = route.query
+ const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
+ if (cur !== 'redirect') {
+ acc[cur] = query[cur]
+ }
+ return acc
+ }, {})
+ router.push({ path: redirect.value || '/', query: otherQueryParams })
})
.catch((error) => {
console.error(error)
diff --git a/src/views/monitor/SqlDiffLog.vue b/src/views/monitor/SqlDiffLog.vue
index 96c0d3141e19e0bf050aa6f9181ee65226ebd6ea..6af67b9780a1f6e722d8a353c7012e54ac31692e 100644
--- a/src/views/monitor/SqlDiffLog.vue
+++ b/src/views/monitor/SqlDiffLog.vue
@@ -114,21 +114,25 @@
-
+
+
-
+
-
-
+
+
+
+
+
@@ -158,6 +162,10 @@
diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue
index 4c83073ae7c389b3cfa9c36efe448e537a959871..4ef7f9d9dd499a0618c23e9aa3649b2d854f2e08 100644
--- a/src/views/system/menu/index.vue
+++ b/src/views/system/menu/index.vue
@@ -50,7 +50,13 @@
ref="listRef"
:loading="loading"
:column-config="{ resizable: true }"
- :tree-config="{}"
+ :tree-config="{
+ parentField: 'parentId',
+ reserve: true
+ }"
+ :row-config="{
+ keyField: 'menuId'
+ }"
:scroll-y="{ enabled: true, gt: 20 }"
:data="menuList">
diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue
index e61dab8bcc860c60f2894ea76e40689a31a813e7..3b1b9a0add87af5e74550b43e758106c8bb4c120 100644
--- a/src/views/system/notice/index.vue
+++ b/src/views/system/notice/index.vue
@@ -23,12 +23,12 @@
{{ $t('btn.add') }}
-
+
{{ $t('btn.edit') }}
-
+
{{ $t('btn.delete') }}
@@ -56,12 +56,12 @@
{{ parseTime(scope.row.createTime, 'YYYY-MM-DD') }}
-
+
预览
- 通知
- 修改
- 删除
+ 通知
+ 修改
+ 删除
diff --git a/src/views/tool/email/emailLog.vue b/src/views/tool/email/emailLog.vue
index 5a363d78ecf5dac50a05f613fb84208621970658..326f1829e80662d945da0c838eb75df30cf97012 100644
--- a/src/views/tool/email/emailLog.vue
+++ b/src/views/tool/email/emailLog.vue
@@ -230,18 +230,22 @@ function handlePreview(row) {
}
function handleSendEmail() {
router.push({
- path: '/tool/email/sendemail'
+ name: 'sendemail'
})
}
// 添加&修改 表单提交
function handleSend(row) {
const Ids = row.id != undefined ? [row.id] : ids.value
-
- sendEmail({ idArr: Ids }).then((res) => {
- getList()
- proxy.$modal.msgSuccess('发送成功')
- })
+ proxy.$modal.loading('发送中...')
+ sendEmail({ idArr: Ids })
+ .then(() => {
+ getList()
+ proxy.$modal.msgSuccess('发送成功')
+ })
+ .finally(() => {
+ proxy.$modal.closeLoading()
+ })
}
// 删除按钮操作
diff --git a/src/views/tool/email/emailTpl.vue b/src/views/tool/email/emailTpl.vue
index f3b1452ce44117e944d17597d624263e6196671c..e169357de8428fb7128ba30a24a89c2ea5da0dbd 100644
--- a/src/views/tool/email/emailTpl.vue
+++ b/src/views/tool/email/emailTpl.vue
@@ -21,9 +21,6 @@
{{ $t('btn.add') }}
-
- 发送邮件
-
@@ -44,7 +41,7 @@
-
+
-
+
@@ -268,8 +265,5 @@ const handleOpenPre = function (row) {
openPreview.value = true
info.value = { ...row }
}
-function handleSend() {
- proxy.$tab.openPage('/tool/email/sendEmail')
-}
handleQuery()
diff --git a/src/views/tool/email/sendEmail.vue b/src/views/tool/email/sendEmail.vue
index 0888f64e9ae74b3d82ea1d4adc933c70677b03c2..3814f75d7ff6edf77873acfe7a80464e65941ea2 100644
--- a/src/views/tool/email/sendEmail.vue
+++ b/src/views/tool/email/sendEmail.vue
@@ -16,20 +16,26 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
@@ -38,7 +44,7 @@
-