Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
b8ffc08513
|
@ -3,7 +3,9 @@
|
||||||
VITE_API_PREFIX = '/dev-api'
|
VITE_API_PREFIX = '/dev-api'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_API_BASE_URL = 'http://pms.dtyx.net:9158/'
|
# VITE_API_BASE_URL = 'http://pms.dtyx.net:9158/'
|
||||||
|
# VITE_API_BASE_URL = 'http://localhost:8888/'
|
||||||
|
VITE_API_BASE_URL = 'http://10.18.34.213:8888/'
|
||||||
|
|
||||||
# 接口地址 (WebSocket)
|
# 接口地址 (WebSocket)
|
||||||
VITE_API_WS_URL = 'ws://localhost:8000'
|
VITE_API_WS_URL = 'ws://localhost:8000'
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules
|
|
@ -2,6 +2,5 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/Industrial-image-management-system---web" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
File diff suppressed because it is too large
Load Diff
|
@ -143,6 +143,9 @@ importers:
|
||||||
xgplayer:
|
xgplayer:
|
||||||
specifier: ^2.31.6
|
specifier: ^2.31.6
|
||||||
version: 2.32.6
|
version: 2.32.6
|
||||||
|
xlsx:
|
||||||
|
specifier: ^0.18.5
|
||||||
|
version: 0.18.5
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@antfu/eslint-config':
|
'@antfu/eslint-config':
|
||||||
specifier: ^2.16.3
|
specifier: ^2.16.3
|
||||||
|
@ -1481,6 +1484,10 @@ packages:
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
adler-32@1.3.1:
|
||||||
|
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
aieditor@1.0.13:
|
aieditor@1.0.13:
|
||||||
resolution: {integrity: sha512-A1NIydCJgno3VvEKWPyHZlS7IF5FwBO1X4QO3GEKNcs8wMmmVGbcoVDPHON3uo9bTKaxuuIiONyfLCGHLBpW2Q==}
|
resolution: {integrity: sha512-A1NIydCJgno3VvEKWPyHZlS7IF5FwBO1X4QO3GEKNcs8wMmmVGbcoVDPHON3uo9bTKaxuuIiONyfLCGHLBpW2Q==}
|
||||||
|
|
||||||
|
@ -1688,6 +1695,10 @@ packages:
|
||||||
capital-case@1.0.4:
|
capital-case@1.0.4:
|
||||||
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
||||||
|
|
||||||
|
cfb@1.2.2:
|
||||||
|
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
chalk@1.1.3:
|
chalk@1.1.3:
|
||||||
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
|
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -1759,6 +1770,10 @@ packages:
|
||||||
codemirror@6.0.1:
|
codemirror@6.0.1:
|
||||||
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||||
|
|
||||||
|
codepage@1.15.0:
|
||||||
|
resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
collection-visit@1.0.0:
|
collection-visit@1.0.0:
|
||||||
resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==}
|
resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -1849,6 +1864,11 @@ packages:
|
||||||
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
|
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
|
crc-32@1.2.2:
|
||||||
|
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
crelt@1.0.6:
|
crelt@1.0.6:
|
||||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||||
|
|
||||||
|
@ -2655,6 +2675,10 @@ packages:
|
||||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
frac@1.1.2:
|
||||||
|
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
fragment-cache@0.2.1:
|
fragment-cache@0.2.1:
|
||||||
resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
|
resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -4106,6 +4130,10 @@ packages:
|
||||||
resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==}
|
resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
ssf@0.11.2:
|
||||||
|
resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
stable@0.1.8:
|
stable@0.1.8:
|
||||||
resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
|
resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
|
||||||
deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
|
deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
|
||||||
|
@ -4687,10 +4715,18 @@ packages:
|
||||||
resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
|
resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
wmf@1.0.2:
|
||||||
|
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
word-wrap@1.2.5:
|
word-wrap@1.2.5:
|
||||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
word@0.3.0:
|
||||||
|
resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -4713,6 +4749,11 @@ packages:
|
||||||
resolution: {integrity: sha512-ESwYYcG8SQciPaN43tZkN3r0dS/jQ5RtyxyGbxn2+qcKgZQ861M899xq8Cab/z6qVVX+/4eIsxDbm3lfYGYzvA==}
|
resolution: {integrity: sha512-ESwYYcG8SQciPaN43tZkN3r0dS/jQ5RtyxyGbxn2+qcKgZQ861M899xq8Cab/z6qVVX+/4eIsxDbm3lfYGYzvA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
xlsx@0.18.5:
|
||||||
|
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
xml-name-validator@4.0.0:
|
xml-name-validator@4.0.0:
|
||||||
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
@ -6166,6 +6207,8 @@ snapshots:
|
||||||
|
|
||||||
acorn@8.11.3: {}
|
acorn@8.11.3: {}
|
||||||
|
|
||||||
|
adler-32@1.3.1: {}
|
||||||
|
|
||||||
aieditor@1.0.13(@tiptap/extension-code-block@2.5.8(@tiptap/core@2.5.8(@tiptap/pm@2.5.8))(@tiptap/pm@2.5.8)):
|
aieditor@1.0.13(@tiptap/extension-code-block@2.5.8(@tiptap/core@2.5.8(@tiptap/pm@2.5.8))(@tiptap/pm@2.5.8)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tiptap/core': 2.5.8(@tiptap/pm@2.5.8)
|
'@tiptap/core': 2.5.8(@tiptap/pm@2.5.8)
|
||||||
|
@ -6421,6 +6464,11 @@ snapshots:
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
upper-case-first: 2.0.2
|
upper-case-first: 2.0.2
|
||||||
|
|
||||||
|
cfb@1.2.2:
|
||||||
|
dependencies:
|
||||||
|
adler-32: 1.3.1
|
||||||
|
crc-32: 1.2.2
|
||||||
|
|
||||||
chalk@1.1.3:
|
chalk@1.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 2.2.1
|
ansi-styles: 2.2.1
|
||||||
|
@ -6521,6 +6569,8 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@lezer/common'
|
- '@lezer/common'
|
||||||
|
|
||||||
|
codepage@1.15.0: {}
|
||||||
|
|
||||||
collection-visit@1.0.0:
|
collection-visit@1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
map-visit: 1.0.0
|
map-visit: 1.0.0
|
||||||
|
@ -6608,6 +6658,8 @@ snapshots:
|
||||||
object-assign: 4.1.1
|
object-assign: 4.1.1
|
||||||
vary: 1.1.2
|
vary: 1.1.2
|
||||||
|
|
||||||
|
crc-32@1.2.2: {}
|
||||||
|
|
||||||
crelt@1.0.6: {}
|
crelt@1.0.6: {}
|
||||||
|
|
||||||
cron-parser@4.9.0:
|
cron-parser@4.9.0:
|
||||||
|
@ -7548,6 +7600,8 @@ snapshots:
|
||||||
combined-stream: 1.0.8
|
combined-stream: 1.0.8
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
frac@1.1.2: {}
|
||||||
|
|
||||||
fragment-cache@0.2.1:
|
fragment-cache@0.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
map-cache: 0.2.2
|
map-cache: 0.2.2
|
||||||
|
@ -9049,6 +9103,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
extend-shallow: 3.0.2
|
extend-shallow: 3.0.2
|
||||||
|
|
||||||
|
ssf@0.11.2:
|
||||||
|
dependencies:
|
||||||
|
frac: 1.1.2
|
||||||
|
|
||||||
stable@0.1.8: {}
|
stable@0.1.8: {}
|
||||||
|
|
||||||
static-extend@0.1.2:
|
static-extend@0.1.2:
|
||||||
|
@ -9717,8 +9775,12 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width: 5.1.2
|
string-width: 5.1.2
|
||||||
|
|
||||||
|
wmf@1.0.2: {}
|
||||||
|
|
||||||
word-wrap@1.2.5: {}
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
|
word@0.3.0: {}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
|
@ -9755,6 +9817,16 @@ snapshots:
|
||||||
fs-extra: 5.0.0
|
fs-extra: 5.0.0
|
||||||
xgplayer-subtitles: 1.0.19
|
xgplayer-subtitles: 1.0.19
|
||||||
|
|
||||||
|
xlsx@0.18.5:
|
||||||
|
dependencies:
|
||||||
|
adler-32: 1.3.1
|
||||||
|
cfb: 1.2.2
|
||||||
|
codepage: 1.15.0
|
||||||
|
crc-32: 1.2.2
|
||||||
|
ssf: 0.11.2
|
||||||
|
wmf: 1.0.2
|
||||||
|
word: 0.3.0
|
||||||
|
|
||||||
xml-name-validator@4.0.0: {}
|
xml-name-validator@4.0.0: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
|
|
|
@ -17,14 +17,13 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAppStore, useUserStore } from '@/stores'
|
import { useAppStore, useUserStore } from '@/stores'
|
||||||
|
// 1
|
||||||
defineOptions({ name: 'App' })
|
defineOptions({ name: 'App' })
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
appStore.initTheme()
|
appStore.initTheme()
|
||||||
appStore.initSiteConfig()
|
appStore.initSiteConfig()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.loading-icon {
|
.loading-icon {
|
||||||
animation: arco-loading-circle 1s infinite cubic-bezier(0,0,1,1);
|
animation: arco-loading-circle 1s infinite cubic-bezier(0,0,1,1);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import type { AttachInfoData, BusinessTypeResult } from './type'
|
||||||
* 批量新增附件信息
|
* 批量新增附件信息
|
||||||
* @param businessType 业务类型
|
* @param businessType 业务类型
|
||||||
* @param files 文件列表
|
* @param files 文件列表
|
||||||
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function batchAddAttachment(businessType: string, formData: FormData) {
|
export function batchAddAttachment(businessType: string, formData: FormData) {
|
||||||
return request<AttachInfoData[]>({
|
return request<AttachInfoData[]>({
|
||||||
|
|
|
@ -1,64 +1,64 @@
|
||||||
/** 用户信息响应类型 */
|
/** 用户信息响应类型 */
|
||||||
export interface UserInfoResponse {
|
export interface UserInfoResponse {
|
||||||
code: number;
|
code: number
|
||||||
status: number;
|
status: number
|
||||||
success: boolean;
|
success: boolean
|
||||||
msg: string;
|
msg: string
|
||||||
data: {
|
data: {
|
||||||
user: UserDetail;
|
user: UserDetail
|
||||||
dept: DeptDetail;
|
dept: DeptDetail
|
||||||
roles: RoleDetail[];
|
roles: RoleDetail[]
|
||||||
posts: any[];
|
posts: any[]
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 用户详细信息 */
|
/** 用户详细信息 */
|
||||||
export interface UserDetail {
|
export interface UserDetail {
|
||||||
userId: string;
|
userId: string
|
||||||
account: string;
|
account: string
|
||||||
name: string;
|
name: string
|
||||||
status: number;
|
status: number
|
||||||
userCode: string;
|
userCode: string
|
||||||
userStatus: string;
|
userStatus: string
|
||||||
userType: string;
|
userType: string
|
||||||
mobile: string;
|
mobile: string
|
||||||
createTime: string;
|
createTime: string
|
||||||
avatar?: string;
|
avatar?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 部门详细信息 */
|
/** 部门详细信息 */
|
||||||
export interface DeptDetail {
|
export interface DeptDetail {
|
||||||
deptId: string;
|
deptId: string
|
||||||
deptName: string;
|
deptName: string
|
||||||
parentId: string;
|
parentId: string
|
||||||
orderNum: number;
|
orderNum: number
|
||||||
leaderId: string;
|
leaderId: string
|
||||||
status: string;
|
status: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 角色详细信息 */
|
/** 角色详细信息 */
|
||||||
export interface RoleDetail {
|
export interface RoleDetail {
|
||||||
roleId: string;
|
roleId: string
|
||||||
roleName: string;
|
roleName: string
|
||||||
roleCode: string | null;
|
roleCode: string | null
|
||||||
roleKey: string;
|
roleKey: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 用户类型 - 兼容旧版本 */
|
/** 用户类型 - 兼容旧版本 */
|
||||||
export interface UserInfo {
|
export interface UserInfo {
|
||||||
id: string;
|
id: string
|
||||||
username: string;
|
username: string
|
||||||
nickname: string;
|
nickname: string
|
||||||
gender: 0 | 1 | 2;
|
gender: 0 | 1 | 2
|
||||||
email: string;
|
email: string
|
||||||
phone: string;
|
phone: string
|
||||||
avatar: string;
|
avatar: string
|
||||||
pwdResetTime: string;
|
pwdResetTime: string
|
||||||
pwdExpired: boolean;
|
pwdExpired: boolean
|
||||||
registrationDate: string;
|
registrationDate: string
|
||||||
deptName: string;
|
deptName: string
|
||||||
roles: string[];
|
roles: string[]
|
||||||
permissions: string[];
|
permissions: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 路由类型 */
|
/** 路由类型 */
|
||||||
|
|
|
@ -16,6 +16,7 @@ export * as InsuranceTypeAPI from './insurance-type'
|
||||||
export * as HealthRecordAPI from './health-record'
|
export * as HealthRecordAPI from './health-record'
|
||||||
export * as InsuranceFileAPI from './insurance-file'
|
export * as InsuranceFileAPI from './insurance-file'
|
||||||
export * as EmployeeAPI from './employee'
|
export * as EmployeeAPI from './employee'
|
||||||
|
export * as RegulationAPI from './regulation'
|
||||||
|
|
||||||
export * from './area/type'
|
export * from './area/type'
|
||||||
export * from './auth/type'
|
export * from './auth/type'
|
||||||
|
|
|
@ -23,9 +23,9 @@ export function deleteTaskGroup(id: number) {
|
||||||
return http.del(`${BASE_URL}/group/${id}`)
|
return http.del(`${BASE_URL}/group/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @desc 查询任务列表 */
|
/** @desc 查询任务列表(标准导出) */
|
||||||
export function listTask(query: T.TaskPageQuery) {
|
export const listTask = (params: any) => {
|
||||||
return http.get<PageRes<T.TaskResp[]>>(`${BASE_URL}`, query)
|
return http.get('/project-task/list', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @desc 获取任务详情 */
|
/** @desc 获取任务详情 */
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import http from '@/utils/http'
|
||||||
|
|
||||||
|
// 制度管理API接口
|
||||||
|
export const regulationApi = {
|
||||||
|
// 获取制度列表
|
||||||
|
getRegulationList: (params: {
|
||||||
|
page: number
|
||||||
|
size: number
|
||||||
|
}) => {
|
||||||
|
return http.get('/regulation', params)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取制度详情
|
||||||
|
getRegulationDetail: (regulationId: string) => {
|
||||||
|
return http.get(`/regulation/${regulationId}`)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 创建制度提案
|
||||||
|
createProposal: (data: {
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
regulationType: string
|
||||||
|
scope: string
|
||||||
|
level: string
|
||||||
|
remark?: string
|
||||||
|
}) => {
|
||||||
|
return http.post('/regulation/proposal', data)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新制度提案
|
||||||
|
updateProposal: (regulationId: string, data: any) => {
|
||||||
|
return http.put(`/regulation/proposal/${regulationId}`, data)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除制度提案
|
||||||
|
deleteProposal: (regulationId: string) => {
|
||||||
|
return http.del(`/regulation/proposal/${regulationId}`)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 发布制度
|
||||||
|
publishRegulation: (regulationId: string) => {
|
||||||
|
return http.post(`/regulation/${regulationId}/publish`)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取已发布制度列表
|
||||||
|
getPublishedRegulationList: (params: {
|
||||||
|
page: number
|
||||||
|
size: number
|
||||||
|
status: string
|
||||||
|
}) => {
|
||||||
|
return http.get('/regulation', params)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确认制度知晓
|
||||||
|
confirmRegulation: (regulationId: string) => {
|
||||||
|
return http.post(`/regulation/${regulationId}/confirm`)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 制度状态枚举
|
||||||
|
export enum RegulationStatus {
|
||||||
|
DRAFT = 'DRAFT', // 草稿
|
||||||
|
VOTING = 'VOTING', // 投票中
|
||||||
|
APPROVED = 'APPROVED', // 已通过
|
||||||
|
REJECTED = 'REJECTED', // 已否决
|
||||||
|
PUBLISHED = 'PUBLISHED', // 已发布
|
||||||
|
ARCHIVED = 'ARCHIVED' // 已归档
|
||||||
|
}
|
||||||
|
|
||||||
|
// 制度级别枚举
|
||||||
|
export enum RegulationLevel {
|
||||||
|
LOW = 'LOW', // 低
|
||||||
|
MEDIUM = 'MEDIUM', // 中
|
||||||
|
HIGH = 'HIGH' // 高
|
||||||
|
}
|
||||||
|
|
||||||
|
// 制度信息接口
|
||||||
|
export interface Regulation {
|
||||||
|
regulationId: string
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
regulationType: string
|
||||||
|
status: RegulationStatus
|
||||||
|
publisherId: string
|
||||||
|
publisherName: string
|
||||||
|
publishTime: string
|
||||||
|
effectiveTime: string
|
||||||
|
expireTime: string
|
||||||
|
scope: string
|
||||||
|
level: RegulationLevel
|
||||||
|
version: string
|
||||||
|
remark?: string
|
||||||
|
createBy: string
|
||||||
|
updateBy: string
|
||||||
|
createTime: string
|
||||||
|
updateTime: string
|
||||||
|
page: number
|
||||||
|
pageSize: number
|
||||||
|
delFlag: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建提案请求接口
|
||||||
|
export interface CreateProposalRequest {
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
regulationType: string
|
||||||
|
scope: string
|
||||||
|
level: RegulationLevel
|
||||||
|
remark?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页参数接口
|
||||||
|
export interface PaginationParams {
|
||||||
|
page: number
|
||||||
|
size: number
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import http from '@/utils/http'
|
||||||
export type * from './type'
|
export type * from './type'
|
||||||
|
|
||||||
const BASE_URL = '/system/role'
|
const BASE_URL = '/system/role'
|
||||||
|
const BASE_URL_NEW = '/role'
|
||||||
|
|
||||||
/** @desc 查询角色列表(已废弃) */
|
/** @desc 查询角色列表(已废弃) */
|
||||||
export function listRole(query: T.RoleQuery) {
|
export function listRole(query: T.RoleQuery) {
|
||||||
|
@ -72,7 +73,7 @@ export function updateRolePermission(id: string, data: any) {
|
||||||
|
|
||||||
/** @desc 查询角色关联用户 */
|
/** @desc 查询角色关联用户 */
|
||||||
export function listRoleUser(id: string, query: T.RoleUserPageQuery) {
|
export function listRoleUser(id: string, query: T.RoleUserPageQuery) {
|
||||||
return http.get<PageRes<T.RoleUserResp[]>>(`${BASE_URL}/${id}/user`, query)
|
return http.get<PageRes<T.RoleUserResp[]>>(`${BASE_URL_NEW}/${id}/user`, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @desc 分配角色给用户 */
|
/** @desc 分配角色给用户 */
|
||||||
|
@ -87,5 +88,5 @@ export function unassignFromUsers(userRoleIds: Array<string | number>) {
|
||||||
|
|
||||||
/** @desc 查询角色关联用户 ID */
|
/** @desc 查询角色关联用户 ID */
|
||||||
export function listRoleUserId(id: string) {
|
export function listRoleUserId(id: string) {
|
||||||
return http.get(`${BASE_URL}/${id}/user/id`)
|
return http.get(`${BASE_URL_NEW}/${id}/user`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,202 +27,258 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
path: '/organization',
|
path: '/regulation',
|
||||||
name: 'Organization',
|
name: 'Regulation',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/organization/hr/member',
|
redirect: '/regulation/system-regulation',
|
||||||
meta: { title: '组织架构', icon: 'user-group', hidden: false, sort: 2 },
|
meta: { title: '制度管理', icon: 'file-text', hidden: false, sort: 1.5 },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/organization/hr',
|
path: '/regulation/system-regulation',
|
||||||
name: 'HRManagement',
|
name: 'SystemRegulation',
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
component: () => import('@/views/regulation/repository.vue'),
|
||||||
redirect: '/organization/hr/member',
|
meta: { title: '制度确认', icon: 'file-text', hidden: false },
|
||||||
meta: { title: '人员管理', icon: 'user', hidden: false },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/organization/hr/member',
|
|
||||||
name: 'HRMember',
|
|
||||||
component: () => import('@/views/system/user/index.vue'),
|
|
||||||
meta: { title: '成员', icon: 'user', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/dept',
|
|
||||||
name: 'HRDept',
|
|
||||||
component: () => import('@/views/system/dept/index.vue'),
|
|
||||||
meta: { title: '部门', icon: 'dept', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/workload',
|
|
||||||
name: 'HRWorkload',
|
|
||||||
component: () => import('@/views/hr/workload/index.vue'),
|
|
||||||
meta: { title: '工作量', icon: 'workload', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/attendance',
|
|
||||||
name: 'HRAttendance',
|
|
||||||
component: () => import('@/views/hr/attendance/index.vue'),
|
|
||||||
meta: { title: '考勤', icon: 'attendance', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/performance',
|
|
||||||
name: 'HRPerformance',
|
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
|
||||||
meta: { title: '绩效', icon: 'performance', hidden: false },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/organization/hr/performance/dimention',
|
|
||||||
name: 'Dimention',
|
|
||||||
component: () => import('@/views/performance/setting/index.vue'),
|
|
||||||
meta: { title: '绩效维度', icon: 'performance', hidden: false },
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/performance/rule',
|
|
||||||
name: 'Rule',
|
|
||||||
component: () => import('@/views/performance/rule.vue'),
|
|
||||||
meta: { title: '绩效细则', icon: 'performance', hidden: false },
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/performance/my',
|
|
||||||
name: 'MyPerformance',
|
|
||||||
component: () => import('@/views/performance/my.vue'),
|
|
||||||
meta: { title: '我的绩效', icon: 'performance', hidden: false },
|
|
||||||
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary',
|
|
||||||
name: 'HRSalary',
|
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
|
||||||
redirect: '/organization/hr/salary/overview',
|
|
||||||
meta: { title: '工资', icon: 'salary', hidden: false },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/overview',
|
|
||||||
name: 'HRSalaryOverview',
|
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
|
||||||
meta: { title: '工资概览', icon: 'salary', hidden: false },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/payroll',
|
|
||||||
name: 'Payroll',
|
|
||||||
component: () => import('@/views/salary-management/index.vue'),
|
|
||||||
meta: { title: '工资单', icon: 'salary', hidden: false },
|
|
||||||
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance',
|
|
||||||
// name: 'HRInsurance',
|
|
||||||
// component: () => import('@/components/ParentView/index.vue'),
|
|
||||||
// redirect: '/organization/hr/salary/insurance/overview',
|
|
||||||
// meta: { title: '保险', icon: 'safety', hidden: false },
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance/overview',
|
|
||||||
// name: 'HRInsuranceOverview',
|
|
||||||
// component: () => import('@/views/hr/salary/insurance/overview/index.vue'),
|
|
||||||
// meta: { title: '工作台概览', icon: 'dashboard', hidden: false },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance/my-insurance',
|
|
||||||
// name: 'HRMyInsurance',
|
|
||||||
// component: () => import('@/views/hr/salary/insurance/my-insurance/index.vue'),
|
|
||||||
// meta: { title: '我的保险', icon: 'shield', hidden: false },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance/health-records',
|
|
||||||
// name: 'HRHealthRecords',
|
|
||||||
// component: () => import('@/views/hr/salary/insurance/health-records/index.vue'),
|
|
||||||
// meta: { title: '健康档案', icon: 'heart', hidden: false },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance/policy-files',
|
|
||||||
// name: 'HRPolicyFiles',
|
|
||||||
// component: () => import('@/views/hr/salary/insurance/policy-files/index.vue'),
|
|
||||||
// meta: { title: '保单文件', icon: 'file', hidden: false },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/organization/hr/salary/insurance/personal-info',
|
|
||||||
// name: 'HRPersonalInfo',
|
|
||||||
// component: () => import('@/views/hr/salary/insurance/personal-info/index.vue'),
|
|
||||||
// meta: { title: '个人信息', icon: 'user', hidden: false },
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/health-management',
|
|
||||||
name: 'HRSystemHealthManagement',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/health-management/index.vue'),
|
|
||||||
meta: { title: '健康档案管理', icon: 'heart', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance',
|
|
||||||
name: 'HRSystemInsurance',
|
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
|
||||||
redirect: '/organization/hr/salary/system-insurance/overview',
|
|
||||||
meta: { title: '人员保险', icon: 'settings', hidden: false },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/overview',
|
|
||||||
name: 'HRSystemInsuranceOverview',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/overview/index.vue'),
|
|
||||||
meta: { title: '工作台概览', icon: 'dashboard', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/management',
|
|
||||||
name: 'HRSystemInsuranceManagement',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/management/index.vue'),
|
|
||||||
meta: { title: '保险管理', icon: 'shield', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/file-management',
|
|
||||||
name: 'HRSystemFileManagement',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/file-management/index.vue'),
|
|
||||||
meta: { title: '保单文件管理', icon: 'file', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/company-management',
|
|
||||||
name: 'HRSystemCompanyManagement',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/company-management/index.vue'),
|
|
||||||
meta: { title: '保险公司管理', icon: 'building', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/system-insurance/type-management',
|
|
||||||
name: 'HRSystemTypeManagement',
|
|
||||||
component: () => import('@/views/hr/salary/system-insurance/type-management/index.vue'),
|
|
||||||
meta: { title: '保险类型管理', icon: 'category', hidden: false },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/salary/certification',
|
|
||||||
name: 'HRCertification',
|
|
||||||
component: () => import('@/views/hr/salary/certification/index.vue'),
|
|
||||||
meta: { title: '人员资质管理', icon: 'idcard', hidden: false },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/organization/hr/contribution',
|
|
||||||
name: 'HRContribution',
|
|
||||||
component: () => import('@/views/hr/contribution/index.vue'),
|
|
||||||
meta: { title: '责献积分制度', icon: 'contribution', hidden: false },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/organization/role',
|
path: '/regulation/process-management',
|
||||||
name: 'OrganizationRole',
|
name: 'ProcessManagement',
|
||||||
component: () => import('@/views/system/role/index.vue'),
|
component: () => import('@/views/regulation/confirm.vue'),
|
||||||
meta: { title: '角色管理', icon: 'role', hidden: false },
|
meta: { title: '流程管理', icon: 'workflow', hidden: false },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/organization',
|
||||||
|
name: 'Organization',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/organization/dept',
|
||||||
|
meta: { title: '组织架构', icon: 'user-group', hidden: false, sort: 2 },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/organization/user',
|
||||||
|
name: 'OrganizationUser',
|
||||||
|
component: () => import('@/views/system/user/index.vue'),
|
||||||
|
meta: { title: '用户管理', icon: 'user', hidden: false, sort: 2.25 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/organization/dept',
|
||||||
|
name: 'OrganizationDept',
|
||||||
|
component: () => import('@/views/system/dept/index.vue'),
|
||||||
|
meta: { title: '部门管理', icon: 'mind-mapping', hidden: false, sort: 2.5 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/organization/post',
|
||||||
|
name: 'OrganizationPost',
|
||||||
|
component: () => import('@/views/system/post/index.vue'),
|
||||||
|
meta: { title: '岗位管理', icon: 'nav', hidden: false, sort: 2.75 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/organization/hr/workload',
|
||||||
|
name: 'HRWorkload',
|
||||||
|
component: () => import('@/views/hr/workload/index.vue'),
|
||||||
|
meta: { title: '任务管理', icon: 'bookmark', hidden: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: '/organization',
|
||||||
|
// name: 'Organization',
|
||||||
|
// component: Layout,
|
||||||
|
// redirect: '/organization/hr/member',
|
||||||
|
// meta: { title: '组织架构', icon: 'user-group', hidden: false, sort: 2 },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr',
|
||||||
|
// name: 'HRManagement',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// redirect: '/organization/hr/member',
|
||||||
|
// meta: { title: '人员管理', icon: 'user', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/member',
|
||||||
|
// name: 'HRMember',
|
||||||
|
// component: () => import('@/views/system/user/index.vue'),
|
||||||
|
// meta: { title: '成员', icon: 'user', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/dept',
|
||||||
|
// name: 'HRDept',
|
||||||
|
// component: () => import('@/views/system/dept/index.vue'),
|
||||||
|
// meta: { title: '部门', icon: 'dept', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/workload',
|
||||||
|
// name: 'HRWorkload',
|
||||||
|
// component: () => import('@/views/hr/workload/index.vue'),
|
||||||
|
// meta: { title: '任务管理', icon: 'workload', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/attendance',
|
||||||
|
// name: 'HRAttendance',
|
||||||
|
// component: () => import('@/views/hr/attendance/index.vue'),
|
||||||
|
// meta: { title: '考勤', icon: 'attendance', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/performance',
|
||||||
|
// name: 'HRPerformance',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// meta: { title: '绩效', icon: 'performance', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/performance/dimention',
|
||||||
|
// name: 'Dimention',
|
||||||
|
// component: () => import('@/views/performance/setting/index.vue'),
|
||||||
|
// meta: { title: '绩效维度', icon: 'performance', hidden: false },
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/performance/rule',
|
||||||
|
// name: 'Rule',
|
||||||
|
// component: () => import('@/views/performance/rule.vue'),
|
||||||
|
// meta: { title: '绩效细则', icon: 'performance', hidden: false },
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/performance/my',
|
||||||
|
// name: 'MyPerformance',
|
||||||
|
// component: () => import('@/views/performance/my.vue'),
|
||||||
|
// meta: { title: '我的绩效', icon: 'performance', hidden: false },
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary',
|
||||||
|
// name: 'HRSalary',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// redirect: '/organization/hr/salary/overview',
|
||||||
|
// meta: { title: '工资', icon: 'salary', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/overview',
|
||||||
|
// name: 'HRSalaryOverview',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// meta: { title: '工资概览', icon: 'salary', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/payroll',
|
||||||
|
// name: 'Payroll',
|
||||||
|
// component: () => import('@/views/salary-management/index.vue'),
|
||||||
|
// meta: { title: '工资单', icon: 'salary', hidden: false },
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance',
|
||||||
|
// name: 'HRInsurance',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// redirect: '/organization/hr/salary/insurance/overview',
|
||||||
|
// meta: { title: '保险', icon: 'safety', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance/overview',
|
||||||
|
// name: 'HRInsuranceOverview',
|
||||||
|
// component: () => import('@/views/hr/salary/insurance/overview/index.vue'),
|
||||||
|
// meta: { title: '工作台概览', icon: 'dashboard', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance/my-insurance',
|
||||||
|
// name: 'HRMyInsurance',
|
||||||
|
// component: () => import('@/views/hr/salary/insurance/my-insurance/index.vue'),
|
||||||
|
// meta: { title: '我的保险', icon: 'shield', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance/health-records',
|
||||||
|
// name: 'HRHealthRecords',
|
||||||
|
// component: () => import('@/views/hr/salary/insurance/health-records/index.vue'),
|
||||||
|
// meta: { title: '健康档案', icon: 'heart', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance/policy-files',
|
||||||
|
// name: 'HRPolicyFiles',
|
||||||
|
// component: () => import('@/views/hr/salary/insurance/policy-files/index.vue'),
|
||||||
|
// meta: { title: '保单文件', icon: 'file', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/insurance/personal-info',
|
||||||
|
// name: 'HRPersonalInfo',
|
||||||
|
// component: () => import('@/views/hr/salary/insurance/personal-info/index.vue'),
|
||||||
|
// meta: { title: '个人信息', icon: 'user', hidden: false },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/health-management',
|
||||||
|
// name: 'HRSystemHealthManagement',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/health-management/index.vue'),
|
||||||
|
// meta: { title: '健康档案管理', icon: 'heart', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance',
|
||||||
|
// name: 'HRSystemInsurance',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// redirect: '/organization/hr/salary/system-insurance/overview',
|
||||||
|
// meta: { title: '人员保险', icon: 'settings', hidden: false },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/overview',
|
||||||
|
// name: 'HRSystemInsuranceOverview',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/overview/index.vue'),
|
||||||
|
// meta: { title: '工作台概览', icon: 'dashboard', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/management',
|
||||||
|
// name: 'HRSystemInsuranceManagement',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/management/index.vue'),
|
||||||
|
// meta: { title: '保险管理', icon: 'shield', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/file-management',
|
||||||
|
// name: 'HRSystemFileManagement',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/file-management/index.vue'),
|
||||||
|
// meta: { title: '保单文件管理', icon: 'file', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/company-management',
|
||||||
|
// name: 'HRSystemCompanyManagement',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/company-management/index.vue'),
|
||||||
|
// meta: { title: '保险公司管理', icon: 'building', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/system-insurance/type-management',
|
||||||
|
// name: 'HRSystemTypeManagement',
|
||||||
|
// component: () => import('@/views/hr/salary/system-insurance/type-management/index.vue'),
|
||||||
|
// meta: { title: '保险类型管理', icon: 'category', hidden: false },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/salary/certification',
|
||||||
|
// name: 'HRCertification',
|
||||||
|
// component: () => import('@/views/hr/salary/certification/index.vue'),
|
||||||
|
// meta: { title: '人员资质管理', icon: 'idcard', hidden: false },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/hr/contribution',
|
||||||
|
// name: 'HRContribution',
|
||||||
|
// component: () => import('@/views/hr/contribution/index.vue'),
|
||||||
|
// meta: { title: '责献积分制度', icon: 'contribution', hidden: false },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/organization/role',
|
||||||
|
// name: 'OrganizationRole',
|
||||||
|
// component: () => import('@/views/system/role/index.vue'),
|
||||||
|
// meta: { title: '角色管理', icon: 'role', hidden: false },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
path: '/asset-management',
|
path: '/asset-management',
|
||||||
name: 'AssetManagement',
|
name: 'AssetManagement',
|
||||||
|
@ -947,6 +1003,30 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
// }
|
// }
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/user/profile',
|
||||||
|
name: 'UserProfile',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/user/profile',
|
||||||
|
meta: {
|
||||||
|
title: '个人中心',
|
||||||
|
icon: 'user',
|
||||||
|
hidden: false,
|
||||||
|
sort: 100,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/user/profile',
|
||||||
|
name: 'UserProfile',
|
||||||
|
component: () => import('@/views/user/profile/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '个人中心',
|
||||||
|
icon: 'user',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/enterprise-settings',
|
path: '/enterprise-settings',
|
||||||
name: 'EnterpriseSettings',
|
name: 'EnterpriseSettings',
|
||||||
|
@ -1150,7 +1230,6 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: '/project-management/project-template/project-aproval',
|
redirect: '/project-management/project-template/project-aproval',
|
||||||
|
@ -1176,6 +1255,11 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// path: '/user/profile',
|
||||||
|
// component: () => import('@/views/user/profile/index.vue'),
|
||||||
|
// meta: { hidden: true },
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
component: () => import('@/views/default/error/404.vue'),
|
component: () => import('@/views/default/error/404.vue'),
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export interface Regulation {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
typeName: string
|
||||||
|
publisher: string
|
||||||
|
publishTime: string
|
||||||
|
effectiveDate: string
|
||||||
|
confirmStatus: 'pending' | 'confirmed'
|
||||||
|
content: string
|
||||||
|
scope: string
|
||||||
|
requirements: string
|
||||||
|
notes: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useRegulationStore = defineStore('regulation', () => {
|
||||||
|
// 已发布的制度列表
|
||||||
|
const publishedRegulations = ref<Regulation[]>([])
|
||||||
|
|
||||||
|
// 添加新发布的制度
|
||||||
|
const addPublishedRegulation = (regulation: Regulation) => {
|
||||||
|
publishedRegulations.value.unshift(regulation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新制度确认状态
|
||||||
|
const updateRegulationConfirmStatus = (id: string, status: 'pending' | 'confirmed') => {
|
||||||
|
const regulation = publishedRegulations.value.find(item => item.id === id)
|
||||||
|
if (regulation) {
|
||||||
|
regulation.confirmStatus = status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量确认所有制度
|
||||||
|
const confirmAllRegulations = () => {
|
||||||
|
publishedRegulations.value.forEach(regulation => {
|
||||||
|
regulation.confirmStatus = 'confirmed'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
publishedRegulations,
|
||||||
|
addPublishedRegulation,
|
||||||
|
updateRegulationConfirmStatus,
|
||||||
|
confirmAllRegulations
|
||||||
|
}
|
||||||
|
})
|
|
@ -4,10 +4,9 @@ import type { RouteRecordRaw } from 'vue-router'
|
||||||
import { mapTree, toTreeArray } from 'xe-utils'
|
import { mapTree, toTreeArray } from 'xe-utils'
|
||||||
import { cloneDeep, omit } from 'lodash-es'
|
import { cloneDeep, omit } from 'lodash-es'
|
||||||
import { constantRoutes, systemRoutes } from '@/router/route'
|
import { constantRoutes, systemRoutes } from '@/router/route'
|
||||||
import { type RouteItem, getUserRouteWithAdapter } from '@/apis'
|
import type { RouteItem } from '@/apis'
|
||||||
import { transformPathToName } from '@/utils'
|
import { transformPathToName } from '@/utils'
|
||||||
import { asyncRouteModules } from '@/router/asyncModules'
|
import { asyncRouteModules } from '@/router/asyncModules'
|
||||||
import { convertMenuData, type ApiMenuItem } from '@/utils/menuConverter'
|
|
||||||
|
|
||||||
const layoutComponentMap = {
|
const layoutComponentMap = {
|
||||||
Layout: () => import('@/layout/index.vue'),
|
Layout: () => import('@/layout/index.vue'),
|
||||||
|
@ -94,91 +93,63 @@ const storeSetup = () => {
|
||||||
// 获取路由数据并已通过适配器转换
|
// 获取路由数据并已通过适配器转换
|
||||||
// const { data } = await getUserRouteWithAdapter()
|
// const { data } = await getUserRouteWithAdapter()
|
||||||
const data = [{
|
const data = [{
|
||||||
"id": 1000,
|
id: 1000,
|
||||||
"parentId": 0,
|
parentId: 0,
|
||||||
"title": "系统管理",
|
title: '系统管理',
|
||||||
"type": 1,
|
type: 1,
|
||||||
"path": "/system",
|
path: '/system',
|
||||||
"name": "System",
|
name: 'System',
|
||||||
"component": "Layout",
|
component: 'Layout',
|
||||||
"redirect": "/system/user",
|
redirect: '/system/user',
|
||||||
"icon": "settings",
|
icon: 'settings',
|
||||||
"isExternal": false,
|
isExternal: false,
|
||||||
"isCache": false,
|
isCache: false,
|
||||||
"isHidden": false,
|
isHidden: false,
|
||||||
"sort": 1,
|
sort: 1,
|
||||||
"children": [
|
children: [
|
||||||
{
|
{
|
||||||
"id": 1010,
|
id: 1010,
|
||||||
"parentId": 1000,
|
parentId: 1000,
|
||||||
"title": "用户管理",
|
title: '用户管理',
|
||||||
"type": 2,
|
type: 2,
|
||||||
"path": "/system/user",
|
path: '/system/user',
|
||||||
"name": "SystemUser",
|
name: 'SystemUser',
|
||||||
"component": "system/user/index",
|
component: 'system/user/index',
|
||||||
"icon": "user",
|
icon: 'user',
|
||||||
"isExternal": false,
|
isExternal: false,
|
||||||
"isCache": false,
|
isCache: false,
|
||||||
"isHidden": false,
|
isHidden: false,
|
||||||
"sort": 1
|
sort: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 1030,
|
id: 1030,
|
||||||
"parentId": 1000,
|
parentId: 1000,
|
||||||
"title": "角色管理",
|
title: '角色管理',
|
||||||
"type": 2,
|
type: 2,
|
||||||
"path": "/system/role",
|
path: '/system/role',
|
||||||
"name": "SystemRole",
|
name: 'SystemRole',
|
||||||
"component": "system/role/index",
|
component: 'system/role/index',
|
||||||
"icon": "user-group",
|
icon: 'user-group',
|
||||||
"isExternal": false,
|
isExternal: false,
|
||||||
"isCache": false,
|
isCache: false,
|
||||||
"isHidden": false,
|
isHidden: false,
|
||||||
"sort": 2
|
sort: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 1050,
|
id: 1050,
|
||||||
"parentId": 1000,
|
parentId: 1000,
|
||||||
"title": "菜单管理",
|
title: '菜单管理',
|
||||||
"type": 2,
|
type: 2,
|
||||||
"path": "/system/menu",
|
path: '/system/menu',
|
||||||
"name": "SystemMenu",
|
name: 'SystemMenu',
|
||||||
"component": "system/menu/index",
|
component: 'system/menu/index',
|
||||||
"icon": "menu",
|
icon: 'menu',
|
||||||
"isExternal": false,
|
isExternal: false,
|
||||||
"isCache": false,
|
isCache: false,
|
||||||
"isHidden": false,
|
isHidden: false,
|
||||||
"sort": 3
|
sort: 3,
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
"id": 1070,
|
|
||||||
"parentId": 1000,
|
|
||||||
"title": "部门管理",
|
|
||||||
"type": 2,
|
|
||||||
"path": "/system/dept",
|
|
||||||
"name": "SystemDept",
|
|
||||||
"component": "system/dept/index",
|
|
||||||
"icon": "mind-mapping",
|
|
||||||
"isExternal": false,
|
|
||||||
"isCache": false,
|
|
||||||
"isHidden": false,
|
|
||||||
"sort": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1090,
|
|
||||||
"parentId": 1000,
|
|
||||||
"title": "岗位管理",
|
|
||||||
"type": 2,
|
|
||||||
"path": "/system/post",
|
|
||||||
"name": "SystemPost",
|
|
||||||
"component": "system/post/index",
|
|
||||||
"icon": "settings",
|
|
||||||
"isExternal": false,
|
|
||||||
"isCache": false,
|
|
||||||
"isHidden": false,
|
|
||||||
"sort": 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}]
|
}]
|
||||||
// 使用已转换的数据生成路由
|
// 使用已转换的数据生成路由
|
||||||
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
const asyncRoutes = formatAsyncRoutes(data as unknown as RouteItem[])
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
<!-- 考勤统计 -->
|
||||||
<template>
|
<template>
|
||||||
<GiPageLayout>
|
<GiPageLayout>
|
||||||
<GiTable
|
<GiTable
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
<!--任务管理-->
|
||||||
<template>
|
<template>
|
||||||
<GiPageLayout>
|
<GiPageLayout>
|
||||||
|
<a-button type="primary" style="margin-bottom: 16px" @click="openAddModal">发布任务</a-button>
|
||||||
<GiTable
|
<GiTable
|
||||||
row-key="id"
|
row-key="taskId"
|
||||||
title="工作量管理"
|
title="任务记录"
|
||||||
:data="dataList"
|
:data="dataList"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
@ -11,38 +13,74 @@
|
||||||
@page-change="onPageChange"
|
@page-change="onPageChange"
|
||||||
@page-size-change="onPageSizeChange"
|
@page-size-change="onPageSizeChange"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
|
@row-click="onRowClick"
|
||||||
>
|
>
|
||||||
<template #top>
|
<template #top>
|
||||||
<GiForm
|
<GiForm
|
||||||
v-model="searchForm"
|
v-model="searchForm"
|
||||||
search
|
search
|
||||||
:columns="queryFormColumns"
|
:columns="queryFormColumns"
|
||||||
size="medium"
|
size="medium"
|
||||||
@search="search"
|
@search="search"
|
||||||
@reset="reset"
|
@reset="reset"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #status="{ record }">
|
||||||
<template #toolbar-left>
|
<a-tag :color="getTaskStatusColor(record.status)">{{ getTaskStatusText(record.status) }}</a-tag>
|
||||||
<a-button type="primary" @click="openAddModal">
|
|
||||||
<template #icon><icon-plus /></template>
|
|
||||||
<template #default>新增工作量记录</template>
|
|
||||||
</a-button>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 工作量显示 -->
|
|
||||||
<template #workload="{ record }">
|
|
||||||
<span class="font-medium text-blue-600">{{ record.workload }}小时</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 操作列 -->
|
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-link @click="editRecord(record)">编辑</a-link>
|
<a-link @click.stop="onRowClick(record)">详情</a-link>
|
||||||
<a-link status="danger" @click="deleteRecord(record)">删除</a-link>
|
<a-link status="danger" @click.stop="deleteRecord(record)">删除</a-link>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</GiTable>
|
</GiTable>
|
||||||
|
<!-- 发布任务弹窗 -->
|
||||||
|
<a-modal v-model:visible="showAddModal" title="发布任务" @ok="handleAddTask" @cancel="showAddModal = false">
|
||||||
|
<a-form :model="addForm" label-width="90px">
|
||||||
|
<a-form-item label="任务ID">
|
||||||
|
<a-input v-model="addForm.taskId" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="任务描述">
|
||||||
|
<a-input v-model="addForm.remark" placeholder="请输入任务描述" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="创建时间">
|
||||||
|
<a-input v-model="addForm.createTime" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
<!-- 任务详情弹窗 -->
|
||||||
|
<a-modal v-model:visible="showDetailModal" title="任务详情" @ok="handleUpdateTask" @cancel="showDetailModal = false" :footer="false">
|
||||||
|
<a-form :model="detailForm" label-width="90px">
|
||||||
|
<a-form-item label="任务ID">
|
||||||
|
<a-input v-model="detailForm.taskId" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="任务描述">
|
||||||
|
<a-input v-model="detailForm.remark" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="分配岗位">
|
||||||
|
<a-select v-model="detailForm.deptName" :options="deptOptions" allow-clear placeholder="请选择岗位" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="分配人员">
|
||||||
|
<a-select v-model="detailForm.mainUserId" :options="userOptions" allow-clear placeholder="请选择人员" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="任务状态">
|
||||||
|
<a-input :value="getTaskStatusText(detailForm.status)" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="创建时间">
|
||||||
|
<a-input v-model="detailForm.createTime" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="完成时间">
|
||||||
|
<a-input v-model="detailForm.finishTime" disabled />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<a-space style="float: right">
|
||||||
|
<a-button status="danger" @click="handleDeleteTask">删除</a-button>
|
||||||
|
<a-button type="primary" @click="handleUpdateTask">确定</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
</GiPageLayout>
|
</GiPageLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -50,13 +88,52 @@
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { Message } from '@arco-design/web-vue'
|
import { Message } from '@arco-design/web-vue'
|
||||||
import type { TableColumnData } from '@arco-design/web-vue'
|
import type { TableColumnData } from '@arco-design/web-vue'
|
||||||
|
// import { listTask } from '@/apis/project/task' // 接口调用处注释
|
||||||
|
|
||||||
|
// 任务状态映射
|
||||||
|
// 0未分配,1已分配,2已完成,3已取消
|
||||||
|
const statusOptions = [
|
||||||
|
{ label: '未分配', value: 0 },
|
||||||
|
{ label: '已分配', value: 1 },
|
||||||
|
{ label: '已完成', value: 2 },
|
||||||
|
{ label: '已取消', value: 3 }
|
||||||
|
]
|
||||||
|
const getTaskStatusColor = (status: number) => {
|
||||||
|
const colorMap: Record<number, string> = {
|
||||||
|
0: 'gray',
|
||||||
|
1: 'blue',
|
||||||
|
2: 'green',
|
||||||
|
3: 'red'
|
||||||
|
}
|
||||||
|
return colorMap[status] || 'gray'
|
||||||
|
}
|
||||||
|
const getTaskStatusText = (status: number) => {
|
||||||
|
const textMap: Record<number, string> = {
|
||||||
|
0: '未分配',
|
||||||
|
1: '已分配',
|
||||||
|
2: '已完成',
|
||||||
|
3: '已取消'
|
||||||
|
}
|
||||||
|
return textMap[status] || status
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例岗位和人员
|
||||||
|
const deptOptions = [
|
||||||
|
{ label: '开发', value: '开发' },
|
||||||
|
{ label: '测试', value: '测试' },
|
||||||
|
{ label: '运维', value: '运维' }
|
||||||
|
]
|
||||||
|
const userOptions = [
|
||||||
|
{ label: '张三', value: '张三' },
|
||||||
|
{ label: '李四', value: '李四' },
|
||||||
|
{ label: '王五', value: '王五' }
|
||||||
|
]
|
||||||
|
|
||||||
// 搜索表单
|
// 搜索表单
|
||||||
let searchForm = reactive({
|
let searchForm = reactive({
|
||||||
userName: '',
|
taskName: '',
|
||||||
projectName: '',
|
responsiblePerson: '', // mainUserId
|
||||||
startDate: '',
|
status: '',
|
||||||
endDate: '',
|
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 10
|
size: 10
|
||||||
})
|
})
|
||||||
|
@ -64,119 +141,241 @@ let searchForm = reactive({
|
||||||
// 查询条件配置
|
// 查询条件配置
|
||||||
const queryFormColumns = [
|
const queryFormColumns = [
|
||||||
{
|
{
|
||||||
field: 'userName',
|
field: 'taskName',
|
||||||
label: '员工姓名',
|
label: '任务标题',
|
||||||
type: 'input' as const,
|
type: 'input' as const,
|
||||||
props: {
|
props: {
|
||||||
placeholder: '请输入员工姓名'
|
placeholder: '请输入任务标题',
|
||||||
|
style: { width: '200px' }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'projectName',
|
field: 'responsiblePerson',
|
||||||
label: '项目名称',
|
label: '分配用户',
|
||||||
type: 'input' as const,
|
type: 'input' as const,
|
||||||
props: {
|
props: {
|
||||||
placeholder: '请输入项目名称'
|
placeholder: '请输入分配用户',
|
||||||
|
style: { width: '200px' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
label: '任务状态',
|
||||||
|
type: 'select' as const,
|
||||||
|
props: {
|
||||||
|
placeholder: '请选择任务状态',
|
||||||
|
options: statusOptions,
|
||||||
|
style: { width: '200px' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const tableColumns: TableColumnData[] = [
|
const tableColumns: TableColumnData[] = [
|
||||||
{ title: '员工姓名', dataIndex: 'userName', width: 120 },
|
{ title: '任务ID', dataIndex: 'taskId', width: 80 },
|
||||||
{ title: '部门', dataIndex: 'deptName', width: 120 },
|
{ title: '任务标题', dataIndex: 'taskName', width: 200, ellipsis: true, tooltip: true },
|
||||||
{ title: '项目名称', dataIndex: 'projectName', width: 200, ellipsis: true, tooltip: true },
|
{ title: '分配用户', dataIndex: 'mainUserId', width: 120 },
|
||||||
{ title: '工作内容', dataIndex: 'workContent', width: 250, ellipsis: true, tooltip: true },
|
{ title: '分配部门', dataIndex: 'deptName', width: 120 },
|
||||||
{ title: '工作量(小时)', dataIndex: 'workload', slotName: 'workload', width: 120 },
|
{ title: '任务内容', dataIndex: 'remark', width: 250, ellipsis: true, tooltip: true },
|
||||||
{ title: '工作日期', dataIndex: 'workDate', width: 120 },
|
{ title: '任务状态', dataIndex: 'status', slotName: 'status', width: 120 },
|
||||||
{ title: '创建时间', dataIndex: 'createTime', width: 160 },
|
{ title: '创建时间', dataIndex: 'createTime', width: 160 },
|
||||||
{ title: '操作', slotName: 'action', width: 120, fixed: 'right' }
|
{ title: '操作', slotName: 'action', width: 120, fixed: 'right' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 数据状态
|
// 数据状态
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const dataList = ref([
|
const dataList = ref<any[]>([])
|
||||||
{
|
const allData = ref<any[]>([])
|
||||||
id: 1,
|
|
||||||
userName: '张三',
|
|
||||||
deptName: '技术部',
|
|
||||||
projectName: '企业管理系统',
|
|
||||||
workContent: '前端开发',
|
|
||||||
workload: 8,
|
|
||||||
workDate: '2024-01-15',
|
|
||||||
createTime: '2024-01-15 10:30:00'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
userName: '李四',
|
|
||||||
deptName: '技术部',
|
|
||||||
projectName: '移动端应用',
|
|
||||||
workContent: '后端接口开发',
|
|
||||||
workload: 6,
|
|
||||||
workDate: '2024-01-15',
|
|
||||||
createTime: '2024-01-15 11:20:00'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const pagination = reactive({
|
const pagination = reactive({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 2,
|
total: 0,
|
||||||
showTotal: true,
|
showTotal: true,
|
||||||
showPageSize: true
|
showPageSize: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 搜索和重置
|
// 发布任务弹窗
|
||||||
const search = async () => {
|
const showAddModal = ref(false)
|
||||||
loading.value = true
|
const addForm = reactive({
|
||||||
// 模拟API请求
|
taskId: '',
|
||||||
setTimeout(() => {
|
remark: '',
|
||||||
loading.value = false
|
createTime: ''
|
||||||
}, 1000)
|
})
|
||||||
|
const openAddModal = () => {
|
||||||
|
addForm.taskId = Date.now().toString()
|
||||||
|
addForm.remark = ''
|
||||||
|
addForm.createTime = new Date().toLocaleString()
|
||||||
|
showAddModal.value = true
|
||||||
|
}
|
||||||
|
const handleAddTask = () => {
|
||||||
|
if (!addForm.remark) {
|
||||||
|
Message.warning('请输入任务描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newTask = {
|
||||||
|
taskId: addForm.taskId,
|
||||||
|
taskName: addForm.remark,
|
||||||
|
mainUserId: '',
|
||||||
|
deptName: '',
|
||||||
|
remark: addForm.remark,
|
||||||
|
status: 0, // 未分配
|
||||||
|
createTime: addForm.createTime,
|
||||||
|
finishTime: ''
|
||||||
|
}
|
||||||
|
allData.value.unshift(newTask)
|
||||||
|
filterAndPaginate()
|
||||||
|
showAddModal.value = false
|
||||||
|
Message.success('任务发布成功')
|
||||||
}
|
}
|
||||||
|
|
||||||
const reset = () => {
|
// 任务详情弹窗
|
||||||
|
const showDetailModal = ref(false)
|
||||||
|
const detailForm = reactive({
|
||||||
|
taskId: '',
|
||||||
|
taskName: '',
|
||||||
|
mainUserId: '',
|
||||||
|
deptName: '',
|
||||||
|
remark: '',
|
||||||
|
status: 0,
|
||||||
|
createTime: '',
|
||||||
|
finishTime: ''
|
||||||
|
})
|
||||||
|
let detailIndex = -1
|
||||||
|
const onRowClick = (record: any) => {
|
||||||
|
Object.assign(detailForm, record)
|
||||||
|
detailIndex = allData.value.findIndex(item => item.taskId === record.taskId)
|
||||||
|
showDetailModal.value = true
|
||||||
|
}
|
||||||
|
const handleUpdateTask = () => {
|
||||||
|
if (detailIndex !== -1) {
|
||||||
|
allData.value[detailIndex] = { ...detailForm }
|
||||||
|
filterAndPaginate()
|
||||||
|
showDetailModal.value = false
|
||||||
|
Message.success('任务更新成功')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleDeleteTask = () => {
|
||||||
|
if (detailIndex !== -1) {
|
||||||
|
allData.value.splice(detailIndex, 1)
|
||||||
|
filterAndPaginate()
|
||||||
|
showDetailModal.value = false
|
||||||
|
Message.success('任务已删除')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取任务数据(用示例数据,接口调用处注释)
|
||||||
|
const fetchTaskList = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// const res = await listTask(params)
|
||||||
|
// const rows = res?.rows || res?.data?.rows || []
|
||||||
|
// allData.value = rows
|
||||||
|
// 示例数据:
|
||||||
|
allData.value = [
|
||||||
|
{
|
||||||
|
taskId: '1710000000000',
|
||||||
|
taskName: '示例任务A',
|
||||||
|
mainUserId: '张三',
|
||||||
|
deptName: '开发',
|
||||||
|
remark: '开发新功能',
|
||||||
|
status: 1,
|
||||||
|
createTime: '2024-05-01 10:00:00',
|
||||||
|
finishTime: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
taskId: '1710000000001',
|
||||||
|
taskName: '示例任务B',
|
||||||
|
mainUserId: '',
|
||||||
|
deptName: '',
|
||||||
|
remark: '待分配任务',
|
||||||
|
status: 0,
|
||||||
|
createTime: '2024-05-02 11:00:00',
|
||||||
|
finishTime: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
taskId: '1710000000002',
|
||||||
|
taskName: '示例任务C',
|
||||||
|
mainUserId: '李四',
|
||||||
|
deptName: '测试',
|
||||||
|
remark: '测试任务',
|
||||||
|
status: 2,
|
||||||
|
createTime: '2024-05-03 09:00:00',
|
||||||
|
finishTime: '2024-05-05 18:00:00'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
filterAndPaginate()
|
||||||
|
pagination.total = allData.value.length
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('获取任务数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 前端筛选和分页
|
||||||
|
const filterAndPaginate = () => {
|
||||||
|
let filtered = allData.value
|
||||||
|
if (searchForm.taskName) {
|
||||||
|
filtered = filtered.filter((item: any) =>
|
||||||
|
item.taskName?.toLowerCase().includes(searchForm.taskName.toLowerCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (searchForm.responsiblePerson) {
|
||||||
|
filtered = filtered.filter((item: any) =>
|
||||||
|
item.mainUserId?.toLowerCase().includes(searchForm.responsiblePerson.toLowerCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (searchForm.status !== '' && searchForm.status !== undefined) {
|
||||||
|
filtered = filtered.filter((item: any) => String(item.status) === String(searchForm.status))
|
||||||
|
}
|
||||||
|
// 分页
|
||||||
|
const start = (pagination.current - 1) * pagination.pageSize
|
||||||
|
const end = start + pagination.pageSize
|
||||||
|
dataList.value = filtered.slice(start, end)
|
||||||
|
pagination.total = filtered.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索和重置
|
||||||
|
const search = async () => {
|
||||||
|
pagination.current = 1
|
||||||
|
filterAndPaginate()
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = async () => {
|
||||||
Object.assign(searchForm, {
|
Object.assign(searchForm, {
|
||||||
userName: '',
|
taskName: '',
|
||||||
projectName: '',
|
responsiblePerson: '',
|
||||||
startDate: '',
|
status: '',
|
||||||
endDate: '',
|
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 10
|
size: 10
|
||||||
})
|
})
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
search()
|
filterAndPaginate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页处理
|
// 分页处理
|
||||||
const onPageChange = (page: number) => {
|
const onPageChange = (page: number) => {
|
||||||
searchForm.page = page
|
|
||||||
pagination.current = page
|
pagination.current = page
|
||||||
search()
|
filterAndPaginate()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPageSizeChange = (size: number) => {
|
const onPageSizeChange = (size: number) => {
|
||||||
searchForm.size = size
|
|
||||||
searchForm.page = 1
|
|
||||||
pagination.pageSize = size
|
pagination.pageSize = size
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
search()
|
filterAndPaginate()
|
||||||
}
|
|
||||||
|
|
||||||
// 操作方法
|
|
||||||
const openAddModal = () => {
|
|
||||||
Message.info('新增工作量记录功能开发中...')
|
|
||||||
}
|
|
||||||
|
|
||||||
const editRecord = (record: any) => {
|
|
||||||
Message.info(`编辑工作量记录: ${record.userName}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除操作(表格操作列)
|
||||||
const deleteRecord = (record: any) => {
|
const deleteRecord = (record: any) => {
|
||||||
Message.info(`删除工作量记录: ${record.userName}`)
|
const idx = allData.value.findIndex(item => item.taskId === record.taskId)
|
||||||
|
if (idx !== -1) {
|
||||||
|
allData.value.splice(idx, 1)
|
||||||
|
filterAndPaginate()
|
||||||
|
Message.success('任务已删除')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search()
|
fetchTaskList()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
|
@ -0,0 +1,509 @@
|
||||||
|
<template>
|
||||||
|
<div class="process-management">
|
||||||
|
<a-card title="制度提案管理" :bordered="false">
|
||||||
|
<template #extra>
|
||||||
|
<a-button type="primary" @click="handleAdd">
|
||||||
|
<template #icon>
|
||||||
|
<GiSvgIcon name="plus" />
|
||||||
|
</template>
|
||||||
|
提交制度提案
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
@page-change="handlePageChange"
|
||||||
|
@page-size-change="handlePageSizeChange"
|
||||||
|
>
|
||||||
|
<template #status="{ record }">
|
||||||
|
<a-tag :color="getStatusColor(record.status)">
|
||||||
|
{{ getStatusText(record.status) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #level="{ record }">
|
||||||
|
<a-tag :color="getLevelColor(record.level)">
|
||||||
|
{{ getLevelText(record.level) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #operations="{ record }">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="text" size="small" @click="handleView(record)">
|
||||||
|
查看详情
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-if="record.status === RegulationStatus.PUBLISHED"
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
已发布
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-if="record.publisherId === currentUser && record.status === RegulationStatus.DRAFT"
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="handleEdit(record)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a-button>
|
||||||
|
<a-popconfirm
|
||||||
|
v-if="record.publisherId === currentUser && record.status === RegulationStatus.DRAFT"
|
||||||
|
content="确定要删除这个提案吗?"
|
||||||
|
@ok="handleDelete(record)"
|
||||||
|
>
|
||||||
|
<a-button type="text" size="small" status="danger">
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 提案表单弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="modalVisible"
|
||||||
|
:title="modalTitle"
|
||||||
|
width="800px"
|
||||||
|
@ok="handleSubmit"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="提案标题" field="title">
|
||||||
|
<a-input v-model="formData.title" placeholder="请输入提案标题" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="提案类型" field="regulationType">
|
||||||
|
<a-select v-model="formData.regulationType" placeholder="请选择提案类型">
|
||||||
|
<a-option value="人事制度">人事制度</a-option>
|
||||||
|
<a-option value="财务制度">财务制度</a-option>
|
||||||
|
<a-option value="安全制度">安全制度</a-option>
|
||||||
|
<a-option value="设备制度">设备制度</a-option>
|
||||||
|
<a-option value="工作流程">工作流程</a-option>
|
||||||
|
<a-option value="其他制度">其他制度</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="适用范围" field="scope">
|
||||||
|
<a-input v-model="formData.scope" placeholder="请输入适用范围" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="制度级别" field="level">
|
||||||
|
<a-select v-model="formData.level" placeholder="请选择制度级别">
|
||||||
|
<a-option :value="RegulationLevel.LOW">低</a-option>
|
||||||
|
<a-option :value="RegulationLevel.MEDIUM">中</a-option>
|
||||||
|
<a-option :value="RegulationLevel.HIGH">高</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-form-item label="提案内容" field="content">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.content"
|
||||||
|
placeholder="请详细描述提案的具体内容"
|
||||||
|
:rows="6"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="备注" field="remark">
|
||||||
|
<a-textarea
|
||||||
|
v-model="formData.remark"
|
||||||
|
placeholder="请输入其他补充说明"
|
||||||
|
:rows="2"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 提案详情弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="detailModalVisible"
|
||||||
|
title="提案详情"
|
||||||
|
width="800px"
|
||||||
|
:footer="false"
|
||||||
|
>
|
||||||
|
<div class="proposal-detail" v-if="currentProposal">
|
||||||
|
<div class="detail-header">
|
||||||
|
<h3>{{ currentProposal.title }}</h3>
|
||||||
|
<div class="detail-meta">
|
||||||
|
<span>提案人: {{ currentProposal.publisherName }}</span>
|
||||||
|
<span>提案类型: {{ currentProposal.regulationType }}</span>
|
||||||
|
<span>适用范围: {{ currentProposal.scope }}</span>
|
||||||
|
<span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span>
|
||||||
|
<span>创建时间: {{ formatDate(currentProposal.createTime) }}</span>
|
||||||
|
<span>状态: <a-tag :color="getStatusColor(currentProposal.status)">{{ getStatusText(currentProposal.status) }}</a-tag></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="detail-content">
|
||||||
|
<h4>提案内容</h4>
|
||||||
|
<div class="content-text">{{ currentProposal.content }}</div>
|
||||||
|
|
||||||
|
<h4>备注</h4>
|
||||||
|
<div class="content-text">{{ currentProposal.remark || '暂无备注' }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="detail-footer">
|
||||||
|
<a-button
|
||||||
|
v-if="currentProposal.status === RegulationStatus.PUBLISHED"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
已自动发布
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import { useRegulationStore } from '@/stores/modules/regulation'
|
||||||
|
import { regulationApi } from '@/apis/regulation'
|
||||||
|
import {
|
||||||
|
RegulationStatus,
|
||||||
|
RegulationLevel,
|
||||||
|
type Regulation
|
||||||
|
} from '@/apis/regulation/type'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProcessManagement' })
|
||||||
|
|
||||||
|
// 表格列定义
|
||||||
|
const columns = [
|
||||||
|
{ title: '提案标题', dataIndex: 'title', key: 'title' },
|
||||||
|
{ title: '提案人', dataIndex: 'publisherName', key: 'publisherName' },
|
||||||
|
{ title: '提案类型', dataIndex: 'regulationType', key: 'regulationType' },
|
||||||
|
{ title: '状态', dataIndex: 'status', key: 'status', slotName: 'status' },
|
||||||
|
{ title: '级别', dataIndex: 'level', key: 'level', slotName: 'level' },
|
||||||
|
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime' },
|
||||||
|
{ title: '操作', key: 'operations', slotName: 'operations', width: 280 }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref<Regulation[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
showTotal: true,
|
||||||
|
showJumper: true,
|
||||||
|
showPageSize: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// 弹窗相关
|
||||||
|
const modalVisible = ref(false)
|
||||||
|
const modalTitle = ref('提交制度提案')
|
||||||
|
const formRef = ref()
|
||||||
|
const formData = reactive({
|
||||||
|
regulationId: '',
|
||||||
|
title: '',
|
||||||
|
regulationType: '',
|
||||||
|
content: '',
|
||||||
|
scope: '',
|
||||||
|
level: RegulationLevel.MEDIUM,
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentProposal = ref<Regulation | null>(null)
|
||||||
|
|
||||||
|
// 详情相关
|
||||||
|
const detailModalVisible = ref(false)
|
||||||
|
|
||||||
|
// 当前用户 - 应该从用户认证系统获取
|
||||||
|
const currentUser = ref('') // TODO: 从用户认证系统获取当前用户ID
|
||||||
|
|
||||||
|
// 制度管理store
|
||||||
|
const regulationStore = useRegulationStore()
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = {
|
||||||
|
title: [{ required: true, message: '请输入提案标题' }],
|
||||||
|
regulationType: [{ required: true, message: '请选择提案类型' }],
|
||||||
|
content: [{ required: true, message: '请输入提案内容' }],
|
||||||
|
scope: [{ required: true, message: '请输入适用范围' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态颜色
|
||||||
|
const getStatusColor = (status: RegulationStatus) => {
|
||||||
|
const colors = {
|
||||||
|
[RegulationStatus.DRAFT]: 'blue',
|
||||||
|
[RegulationStatus.VOTING]: 'orange',
|
||||||
|
[RegulationStatus.REJECTED]: 'red',
|
||||||
|
[RegulationStatus.PUBLISHED]: 'purple',
|
||||||
|
[RegulationStatus.APPROVED]: 'green',
|
||||||
|
[RegulationStatus.ARCHIVED]: 'gray'
|
||||||
|
}
|
||||||
|
return colors[status] || 'blue'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status: RegulationStatus) => {
|
||||||
|
const texts = {
|
||||||
|
[RegulationStatus.DRAFT]: '草稿',
|
||||||
|
[RegulationStatus.VOTING]: '投票中',
|
||||||
|
[RegulationStatus.REJECTED]: '已否决',
|
||||||
|
[RegulationStatus.PUBLISHED]: '已发布',
|
||||||
|
[RegulationStatus.APPROVED]: '已通过',
|
||||||
|
[RegulationStatus.ARCHIVED]: '已归档'
|
||||||
|
}
|
||||||
|
return texts[status] || '草稿'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
if (!dateString) return '-'
|
||||||
|
const date = new Date(dateString)
|
||||||
|
return date.toLocaleDateString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取级别颜色
|
||||||
|
const getLevelColor = (level: RegulationLevel) => {
|
||||||
|
const colors = {
|
||||||
|
[RegulationLevel.LOW]: 'blue',
|
||||||
|
[RegulationLevel.MEDIUM]: 'orange',
|
||||||
|
[RegulationLevel.HIGH]: 'red'
|
||||||
|
}
|
||||||
|
return colors[level] || 'blue'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取级别文本
|
||||||
|
const getLevelText = (level: RegulationLevel) => {
|
||||||
|
const texts = {
|
||||||
|
[RegulationLevel.LOW]: '低',
|
||||||
|
[RegulationLevel.MEDIUM]: '中',
|
||||||
|
[RegulationLevel.HIGH]: '高'
|
||||||
|
}
|
||||||
|
return texts[level] || '中'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取表格数据
|
||||||
|
const getTableData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const response = await regulationApi.getRegulationList({
|
||||||
|
page: pagination.current,
|
||||||
|
size: pagination.pageSize
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
tableData.value = response.data.records
|
||||||
|
pagination.total = response.data.total
|
||||||
|
pagination.current = response.data.current
|
||||||
|
} else {
|
||||||
|
Message.error('获取数据失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取制度列表失败:', error)
|
||||||
|
Message.error('获取数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增
|
||||||
|
const handleAdd = () => {
|
||||||
|
modalTitle.value = '提交制度提案'
|
||||||
|
modalVisible.value = true
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (record: Regulation) => {
|
||||||
|
modalTitle.value = '编辑制度提案'
|
||||||
|
modalVisible.value = true
|
||||||
|
Object.assign(formData, {
|
||||||
|
regulationId: record.regulationId,
|
||||||
|
title: record.title,
|
||||||
|
regulationType: record.regulationType,
|
||||||
|
content: record.content,
|
||||||
|
scope: record.scope,
|
||||||
|
level: record.level,
|
||||||
|
remark: record.remark
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看
|
||||||
|
const handleView = (record: Regulation) => {
|
||||||
|
currentProposal.value = record
|
||||||
|
detailModalVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = async (record: Regulation) => {
|
||||||
|
try {
|
||||||
|
await regulationApi.deleteProposal(record.regulationId)
|
||||||
|
Message.success('删除成功')
|
||||||
|
getTableData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除失败:', error)
|
||||||
|
Message.error('删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
await formRef.value.validate()
|
||||||
|
|
||||||
|
if (formData.regulationId) {
|
||||||
|
// 更新
|
||||||
|
await regulationApi.updateProposal(formData.regulationId, {
|
||||||
|
title: formData.title,
|
||||||
|
regulationType: formData.regulationType,
|
||||||
|
content: formData.content,
|
||||||
|
scope: formData.scope,
|
||||||
|
level: formData.level,
|
||||||
|
remark: formData.remark
|
||||||
|
})
|
||||||
|
Message.success('更新成功')
|
||||||
|
} else {
|
||||||
|
// 新增
|
||||||
|
await regulationApi.createProposal({
|
||||||
|
title: formData.title,
|
||||||
|
regulationType: formData.regulationType,
|
||||||
|
content: formData.content,
|
||||||
|
scope: formData.scope,
|
||||||
|
level: formData.level,
|
||||||
|
remark: formData.remark
|
||||||
|
})
|
||||||
|
Message.success('提案提交成功')
|
||||||
|
}
|
||||||
|
|
||||||
|
modalVisible.value = false
|
||||||
|
getTableData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作失败:', error)
|
||||||
|
Message.error('操作失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消
|
||||||
|
const handleCancel = () => {
|
||||||
|
modalVisible.value = false
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(formData, {
|
||||||
|
regulationId: '',
|
||||||
|
title: '',
|
||||||
|
regulationType: '',
|
||||||
|
content: '',
|
||||||
|
scope: '',
|
||||||
|
level: RegulationLevel.MEDIUM,
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页事件
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
pagination.current = page
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePageSizeChange = (pageSize: number) => {
|
||||||
|
pagination.pageSize = pageSize
|
||||||
|
pagination.current = 1
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.process-management {
|
||||||
|
.arco-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.proposal-detail {
|
||||||
|
.detail-header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
font-size: 14px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
h4 {
|
||||||
|
margin: 16px 0 8px 0;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-fill-1);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.detail-footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,103 @@
|
||||||
|
<template>
|
||||||
|
<GiPageLayout
|
||||||
|
:margin="true"
|
||||||
|
:default-collapsed="false"
|
||||||
|
:header-style="isDesktop ? { padding: 0, borderBottomWidth: 0 } : { borderBottomWidth: '1px' } "
|
||||||
|
>
|
||||||
|
<template v-if="isDesktop" #left>
|
||||||
|
<a-tabs v-model:active-key="activeKey" type="rounded" position="left" hide-content size="large" @change="change">
|
||||||
|
<a-tab-pane v-for="(item) in menuList" :key="item.key">
|
||||||
|
<template #title>
|
||||||
|
<div style="display: flex; align-items: center">
|
||||||
|
<GiSvgIcon :name="item.icon" :size="18" style="margin-right: 4px" />
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</template>
|
||||||
|
<template #header>
|
||||||
|
<a-tabs v-if="!isDesktop" v-model:active-key="activeKey" type="rounded" position="top" size="large" @change="change">
|
||||||
|
<a-tab-pane v-for="(item) in menuList" :key="item.key" :title="item.name">
|
||||||
|
<template #title>
|
||||||
|
<div style="display: flex; align-items: center">
|
||||||
|
<GiSvgIcon :name="item.icon" :size="18" style="margin-right: 4px" />
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</template>
|
||||||
|
<transition name="fade-slide" mode="out-in" appear>
|
||||||
|
<component :is="menuList.find((item) => item.key === activeKey)?.value"></component>
|
||||||
|
</transition>
|
||||||
|
</GiPageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import SystemRegulation from './system-regulation/index.vue'
|
||||||
|
import ProcessManagement from './process-management/index.vue'
|
||||||
|
import { useDevice } from '@/hooks'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ZhiduManagement' })
|
||||||
|
|
||||||
|
const { isDesktop } = useDevice()
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ name: '制度规范', key: 'system-regulation', icon: 'file-text', value: SystemRegulation, path: '/zhidu/system-regulation' },
|
||||||
|
{ name: '流程管理', key: 'process-management', icon: 'workflow', value: ProcessManagement, path: '/zhidu/process-management' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const menuList = computed(() => {
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
// 根据当前路由确定激活的标签页
|
||||||
|
const activeKey = computed(() => {
|
||||||
|
const currentPath = route.path
|
||||||
|
const menuItem = menuList.value.find(item => item.path === currentPath)
|
||||||
|
return menuItem ? menuItem.key : menuList.value[0].key
|
||||||
|
})
|
||||||
|
watch(
|
||||||
|
() => route.path,
|
||||||
|
() => {
|
||||||
|
// 路由变化时会自动更新activeKey
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
const change = (key: string | number) => {
|
||||||
|
const menuItem = menuList.value.find(item => item.key === key)
|
||||||
|
if (menuItem) {
|
||||||
|
router.push(menuItem.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gi_page {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tabs-nav-vertical.arco-tabs-nav-type-line .arco-tabs-tab) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px 16px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-fill-1);
|
||||||
|
|
||||||
|
.arco-tabs-tab-title {
|
||||||
|
&::before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.arco-tabs-tab-active {
|
||||||
|
background: rgba(var(--primary-6), 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,350 @@
|
||||||
|
<template>
|
||||||
|
<div class="system-regulation">
|
||||||
|
<a-card title="已发布制度确认" :bordered="false">
|
||||||
|
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
@page-change="onPageChange"
|
||||||
|
@page-size-change="onPageSizeChange"
|
||||||
|
>
|
||||||
|
<template #confirmStatus="{ record }">
|
||||||
|
<a-tag :color="record.confirmStatus === 'confirmed' ? 'green' : 'orange'">
|
||||||
|
{{ record.confirmStatus === 'confirmed' ? '已确认' : '待确认' }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #operations="{ record }">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="text" size="small" @click="handleView(record)">
|
||||||
|
查看详情
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-if="record.confirmStatus !== 'confirmed'"
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="handleConfirm(record)"
|
||||||
|
>
|
||||||
|
确认知晓
|
||||||
|
</a-button>
|
||||||
|
<a-button type="text" size="small" @click="handleDownload(record)">
|
||||||
|
下载
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 制度详情弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="detailModalVisible"
|
||||||
|
title="制度详情"
|
||||||
|
width="800px"
|
||||||
|
:footer="false"
|
||||||
|
>
|
||||||
|
<div class="regulation-detail" v-if="currentRegulation">
|
||||||
|
<div class="detail-header">
|
||||||
|
<h3>{{ currentRegulation.title }}</h3>
|
||||||
|
<div class="detail-meta">
|
||||||
|
<span>发布人: {{ currentRegulation.publisherName }}</span>
|
||||||
|
<span>发布时间: {{ currentRegulation.publishTime }}</span>
|
||||||
|
<span>生效日期: {{ currentRegulation.effectiveTime }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="detail-content">
|
||||||
|
<h4>制度内容</h4>
|
||||||
|
<div class="content-text">{{ currentRegulation.content }}</div>
|
||||||
|
|
||||||
|
<h4>适用范围</h4>
|
||||||
|
<div class="content-text">{{ currentRegulation.scope }}</div>
|
||||||
|
|
||||||
|
<h4>实施要求</h4>
|
||||||
|
<div class="content-text">{{ currentRegulation.requirements }}</div>
|
||||||
|
|
||||||
|
<h4>注意事项</h4>
|
||||||
|
<div class="content-text">{{ currentRegulation.notes }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<div class="detail-footer">
|
||||||
|
<a-button type="primary" @click="handleConfirm(currentRegulation)">
|
||||||
|
确认知晓并遵守
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="handleDownload(currentRegulation)">
|
||||||
|
下载制度文件
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<!-- 确认承诺弹窗 -->
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="confirmModalVisible"
|
||||||
|
title="制度确认承诺"
|
||||||
|
width="600px"
|
||||||
|
@ok="submitConfirm"
|
||||||
|
@cancel="confirmModalVisible = false"
|
||||||
|
>
|
||||||
|
<div class="confirm-content">
|
||||||
|
<p>我确认已仔细阅读并理解《{{ currentRegulation?.title }}》的全部内容,承诺:</p>
|
||||||
|
<ul>
|
||||||
|
<li>严格遵守该制度的各项规定</li>
|
||||||
|
<li>认真履行相关职责和义务</li>
|
||||||
|
<li>如有违反,愿意承担相应责任</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a-checkbox v-model="agreeTerms">
|
||||||
|
我已阅读并同意上述承诺
|
||||||
|
</a-checkbox>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import type { Regulation } from '@/apis/regulation/type'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import { useRegulationStore } from '@/stores/modules/regulation'
|
||||||
|
import { regulationApi } from '@/apis/regulation'
|
||||||
|
|
||||||
|
defineOptions({ name: 'SystemRegulation' })
|
||||||
|
|
||||||
|
// 表格列定义
|
||||||
|
const columns = [
|
||||||
|
{ title: '制度名称', dataIndex: 'title', key: 'title' },
|
||||||
|
{ title: '制度类型', dataIndex: 'regulationType', key: 'regulationType' },
|
||||||
|
{ title: '发布人', dataIndex: 'publisherName', key: 'publisherName' },
|
||||||
|
{ title: '发布时间', dataIndex: 'publishTime', key: 'publishTime' },
|
||||||
|
{ title: '生效日期', dataIndex: 'effectiveTime', key: 'effectiveTime' },
|
||||||
|
{ title: '确认状态', dataIndex: 'confirmStatus', key: 'confirmStatus', slotName: 'confirmStatus' },
|
||||||
|
{ title: '操作', key: 'operations', slotName: 'operations', width: 250 }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref<Regulation[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
|
showTotal: true,
|
||||||
|
showJumper: true,
|
||||||
|
showPageSize: true
|
||||||
|
})
|
||||||
|
|
||||||
|
// 弹窗相关
|
||||||
|
const detailModalVisible = ref(false)
|
||||||
|
const confirmModalVisible = ref(false)
|
||||||
|
const currentRegulation = ref<Regulation | null>(null)
|
||||||
|
const agreeTerms = ref(false)
|
||||||
|
|
||||||
|
// 制度管理store
|
||||||
|
const regulationStore = useRegulationStore()
|
||||||
|
|
||||||
|
// 获取表格数据
|
||||||
|
const getTableData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const response = await regulationApi.getPublishedRegulationList({
|
||||||
|
page: pagination.current,
|
||||||
|
size: pagination.pageSize,
|
||||||
|
status: "PUBLISHED"
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
tableData.value = response.data.records
|
||||||
|
pagination.pageSize = response.data.size
|
||||||
|
pagination.current = response.data.current
|
||||||
|
pagination.total = response.data.total
|
||||||
|
} else {
|
||||||
|
Message.error('获取数据失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取已发布制度列表失败:', error)
|
||||||
|
Message.error('获取数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页事件
|
||||||
|
const onPageChange = (page: number) => {
|
||||||
|
pagination.current = page
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPageSizeChange = (pageSize: number) => {
|
||||||
|
pagination.pageSize = pageSize
|
||||||
|
pagination.current = 1
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleView = (record: any) => {
|
||||||
|
currentRegulation.value = record
|
||||||
|
detailModalVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认知晓
|
||||||
|
const handleConfirm = (record: any) => {
|
||||||
|
currentRegulation.value = record
|
||||||
|
confirmModalVisible.value = true
|
||||||
|
agreeTerms.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载
|
||||||
|
const handleDownload = (record: any) => {
|
||||||
|
try {
|
||||||
|
// 创建制度文档内容
|
||||||
|
const content = `
|
||||||
|
制度名称:${record.title}
|
||||||
|
制度类型:${record.regulationType}
|
||||||
|
发布人:${record.publisherName}
|
||||||
|
发布时间:${record.publishTime}
|
||||||
|
生效日期:${record.effectiveTime}
|
||||||
|
|
||||||
|
制度内容:
|
||||||
|
${record.content}
|
||||||
|
|
||||||
|
适用范围:
|
||||||
|
${record.scope}
|
||||||
|
|
||||||
|
实施要求:
|
||||||
|
${record.requirements || '请按照制度要求执行'}
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
${record.notes || '请严格遵守制度规定'}
|
||||||
|
`.trim()
|
||||||
|
|
||||||
|
// 创建Blob对象
|
||||||
|
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' })
|
||||||
|
|
||||||
|
// 创建下载链接
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = `${record.title}.txt`
|
||||||
|
|
||||||
|
// 触发下载
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
// 清理
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
|
||||||
|
Message.success('制度文件下载成功')
|
||||||
|
} catch (error) {
|
||||||
|
Message.error('下载失败')
|
||||||
|
console.error('下载错误:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 提交确认
|
||||||
|
const submitConfirm = async () => {
|
||||||
|
if (!agreeTerms.value) {
|
||||||
|
Message.warning('请先同意承诺条款')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (currentRegulation.value) {
|
||||||
|
await regulationApi.confirmRegulation(currentRegulation.value.regulationId)
|
||||||
|
|
||||||
|
Message.success('确认成功,您已承诺遵守该制度')
|
||||||
|
confirmModalVisible.value = false
|
||||||
|
|
||||||
|
// 更新本地数据状态
|
||||||
|
const index = tableData.value.findIndex(item => item.regulationId === currentRegulation.value.regulationId)
|
||||||
|
if (index !== -1) {
|
||||||
|
tableData.value[index].confirmStatus = 'confirmed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('确认失败:', error)
|
||||||
|
Message.error('确认失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.system-regulation {
|
||||||
|
.arco-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.regulation-detail {
|
||||||
|
.detail-header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
h4 {
|
||||||
|
margin: 16px 0 8px 0;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
color: var(--color-text-2);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-fill-1);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-content {
|
||||||
|
p {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,4 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<GiPageLayout>
|
<GiPageLayout>
|
||||||
<div>
|
<div>
|
||||||
<a-radio-group v-model="viewType" type="button" size="small" style="margin-bottom: 16px;">
|
<a-radio-group v-model="viewType" type="button" size="small" style="margin-bottom: 16px;">
|
||||||
|
@ -9,13 +10,15 @@
|
||||||
<GiTable
|
<GiTable
|
||||||
v-show="viewType === 'table'"
|
v-show="viewType === 'table'"
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
row-key="id"
|
row-key="deptId"
|
||||||
:data="dataList"
|
:data="dataList"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:disabled-column-keys="['name']"
|
:disabled-column-keys="['name']"
|
||||||
|
:expanded-keys="expandedKeys"
|
||||||
|
@expand="onExpand"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
>
|
>
|
||||||
<template #expand-icon="{ expanded }">
|
<template #expand-icon="{ expanded }">
|
||||||
|
@ -49,6 +52,7 @@
|
||||||
<a-link v-permission="['system:dept:update']" title="修改" @click="onUpdate(record)">修改</a-link>
|
<a-link v-permission="['system:dept:update']" title="修改" @click="onUpdate(record)">修改</a-link>
|
||||||
<a-link
|
<a-link
|
||||||
v-permission="['system:dept:delete']"
|
v-permission="['system:dept:delete']"
|
||||||
|
:disabled="record.children && record.children.length > 0"
|
||||||
status="danger"
|
status="danger"
|
||||||
title="删除"
|
title="删除"
|
||||||
@click="onDelete(record)"
|
@click="onDelete(record)"
|
||||||
|
@ -69,14 +73,14 @@
|
||||||
:collapsable="true"
|
:collapsable="true"
|
||||||
:horizontal="false"
|
:horizontal="false"
|
||||||
:define-menus="menus"
|
:define-menus="menus"
|
||||||
:expand-all="true"
|
|
||||||
:default-expand-level="999"
|
:default-expand-level="999"
|
||||||
:props="{ id: 'deptId', parentId: 'parentId', label: 'deptName', children: 'children' }"
|
:props="{ id: 'deptId', parentId: 'parentId', label: 'deptName', children: 'children' }"
|
||||||
center
|
center
|
||||||
:node-add="handleAdd"
|
:node-add="handleAdd"
|
||||||
:node-delete="onDelete"
|
:node-delete="onDelete"
|
||||||
:node-edit="onUpdate"
|
:node-edit="onUpdate"
|
||||||
@on-expand-all="bool => nodeExpandAll = bool"
|
:expanded-keys="nodeExpandedKeys"
|
||||||
|
@node-click="(node) => toggleExpand(node.deptId)"
|
||||||
>
|
>
|
||||||
</Vue3TreeOrg>
|
</Vue3TreeOrg>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
|
@ -90,6 +94,7 @@
|
||||||
import 'vue3-tree-org/lib/vue3-tree-org.css'
|
import 'vue3-tree-org/lib/vue3-tree-org.css'
|
||||||
import { Vue3TreeOrg } from 'vue3-tree-org'
|
import { Vue3TreeOrg } from 'vue3-tree-org'
|
||||||
import type { TableInstance } from '@arco-design/web-vue'
|
import type { TableInstance } from '@arco-design/web-vue'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
import DeptAddModal from './DeptAddModal.vue'
|
import DeptAddModal from './DeptAddModal.vue'
|
||||||
import { type DeptQuery, type DeptResp, deleteDept, getDeptTree } from '@/apis/system/dept'
|
import { type DeptQuery, type DeptResp, deleteDept, getDeptTree } from '@/apis/system/dept'
|
||||||
import type GiTable from '@/components/GiTable/index.vue'
|
import type GiTable from '@/components/GiTable/index.vue'
|
||||||
|
@ -97,6 +102,8 @@ import { useDownload, useTable } from '@/hooks'
|
||||||
import { isMobile } from '@/utils'
|
import { isMobile } from '@/utils'
|
||||||
import has from '@/utils/has'
|
import has from '@/utils/has'
|
||||||
|
|
||||||
|
const $message = Message
|
||||||
|
|
||||||
defineOptions({ name: 'SystemDept' })
|
defineOptions({ name: 'SystemDept' })
|
||||||
|
|
||||||
const queryForm = reactive<DeptQuery>({})
|
const queryForm = reactive<DeptQuery>({})
|
||||||
|
@ -109,9 +116,21 @@ const {
|
||||||
} = useTable<DeptResp>(() => getDeptTree(queryForm), {
|
} = useTable<DeptResp>(() => getDeptTree(queryForm), {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
nextTick(() => {
|
if (isFirstLoad.value) {
|
||||||
tableRef.value?.tableRef?.expandAll(true)
|
// 初始全部展开:递归收集所有节点 id
|
||||||
})
|
const collectKeys = (nodes: DeptResp[]): string[] => {
|
||||||
|
let keys: string[] = []
|
||||||
|
nodes.forEach(node => {
|
||||||
|
keys.push(node.deptId)
|
||||||
|
if (node.children && node.children.length) {
|
||||||
|
keys = keys.concat(collectKeys(node.children))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
expandedKeys.value = collectKeys(tableData.value)
|
||||||
|
isFirstLoad.value = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// 查看视图类型
|
// 查看视图类型
|
||||||
|
@ -123,7 +142,9 @@ const menus = [
|
||||||
{ name: '删除部门', command: 'delete' },
|
{ name: '删除部门', command: 'delete' },
|
||||||
]
|
]
|
||||||
// 所有节点展开状态
|
// 所有节点展开状态
|
||||||
const nodeExpandAll = ref<boolean>(true)
|
// 表格视图展开的节点
|
||||||
|
const expandedKeys = ref<string[]>([])
|
||||||
|
const isFirstLoad = ref(true)
|
||||||
// 过滤树
|
// 过滤树
|
||||||
const searchData = (name: string) => {
|
const searchData = (name: string) => {
|
||||||
const loop = (data: DeptResp[]) => {
|
const loop = (data: DeptResp[]) => {
|
||||||
|
@ -180,6 +201,13 @@ const reset = () => {
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
const onDelete = (record: DeptResp) => {
|
const onDelete = (record: DeptResp) => {
|
||||||
|
// 检查是否存在子节点
|
||||||
|
if (record.children && record.children.length > 0) {
|
||||||
|
// 如果有子节点,显示提示信息
|
||||||
|
$message.warning('该部门存在子部门,无法直接删除')
|
||||||
|
return Promise.reject()
|
||||||
|
}
|
||||||
|
|
||||||
return handleDelete(() => deleteDept(record.deptId), {
|
return handleDelete(() => deleteDept(record.deptId), {
|
||||||
content: `是否确定删除部门「${record.deptName}」?`,
|
content: `是否确定删除部门「${record.deptName}」?`,
|
||||||
showModal: true,
|
showModal: true,
|
||||||
|
@ -204,6 +232,31 @@ const handleAdd = (record: DeptResp) => {
|
||||||
const onUpdate = (record: DeptResp) => {
|
const onUpdate = (record: DeptResp) => {
|
||||||
DeptAddModalRef.value?.onUpdate(record.deptId)
|
DeptAddModalRef.value?.onUpdate(record.deptId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onExpand = (expanded: boolean, record: DeptResp) => {
|
||||||
|
const key = record.deptId
|
||||||
|
if (expanded) {
|
||||||
|
if (!expandedKeys.value.includes(key)) {
|
||||||
|
expandedKeys.value.push(key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expandedKeys.value = expandedKeys.value.filter(k => k !== key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加一个方法来切换所有节点的展开/收缩状态
|
||||||
|
const toggleExpandAll = () => {
|
||||||
|
nodeExpandAll.value = !nodeExpandAll.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改: 添加响应式展开状态和切换方法
|
||||||
|
const nodeExpandedKeys = ref<string[]>([])
|
||||||
|
const toggleExpand = (deptId: string) => {
|
||||||
|
const index = nodeExpandedKeys.value.indexOf(deptId)
|
||||||
|
index > -1
|
||||||
|
? nodeExpandedKeys.value.splice(index, 1)
|
||||||
|
: nodeExpandedKeys.value.push(deptId)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
<a-radio :value="0">停用</a-radio>
|
<a-radio :value="0">停用</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="remark" label="备注">
|
<a-form-item field="remark" label="说明">
|
||||||
<a-textarea v-model="formData.remark" placeholder="请输入备注" allow-clear />
|
<a-textarea v-model="formData.remark" placeholder="请输入岗位说明" allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
|
@ -2,65 +2,276 @@
|
||||||
<a-drawer
|
<a-drawer
|
||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
title="岗位详情"
|
title="岗位详情"
|
||||||
width="500px"
|
width="620px"
|
||||||
:footer="false"
|
|
||||||
unmount-on-close
|
unmount-on-close
|
||||||
|
class="post-detail-drawer"
|
||||||
|
@close="() => visible = false"
|
||||||
>
|
>
|
||||||
<a-descriptions
|
<a-spin :loading="loading" class="detail-container">
|
||||||
:data="detailData"
|
<div class="detail-card">
|
||||||
:column="1"
|
<div class="detail-header">
|
||||||
:align="{ label: 'right' }"
|
<div class="post-name">{{ primaryInfo?.name || '-' }}</div>
|
||||||
label-style="width: 120px"
|
<a-tag class="status-tag" :color="getStatusColor(primaryInfo?.status)">
|
||||||
size="medium"
|
{{ getStatusText(primaryInfo?.status) }}
|
||||||
:loading="loading"
|
</a-tag>
|
||||||
border
|
</div>
|
||||||
>
|
|
||||||
<template #label="{ label }">{{ label }}</template>
|
<div class="detail-group">
|
||||||
<template #value="{ value }">
|
<div class="group-title">基本信息</div>
|
||||||
<span v-if="value !== undefined && value !== null">{{ value }}</span>
|
<div class="info-grid">
|
||||||
<span v-else>-</span>
|
<div class="info-item">
|
||||||
</template>
|
<div class="info-label">岗位ID</div>
|
||||||
</a-descriptions>
|
<div class="info-value">{{ primaryInfo?.id || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">岗位排序</div>
|
||||||
|
<div class="info-value">{{ primaryInfo?.sort || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="primaryInfo?.remark" class="detail-group">
|
||||||
|
<div class="group-title">岗位说明</div>
|
||||||
|
<div class="remark-container">
|
||||||
|
<div class="remark-content">{{ primaryInfo.remark }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-group">
|
||||||
|
<div class="group-title">时间信息</div>
|
||||||
|
<div class="info-grid">
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">创建时间</div>
|
||||||
|
<div class="info-value">{{ primaryInfo?.createTime || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">更新时间</div>
|
||||||
|
<div class="info-value">{{primaryInfo?.updateTime || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="footer-actions">
|
||||||
|
<a-button type="primary" @click="handleClose">关闭详情</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { nextTick, ref } from 'vue'
|
||||||
import { getPostDetail } from '@/apis/system/post'
|
import { getPostDetail } from '@/apis/system/post'
|
||||||
import { useLoading } from '@/hooks'
|
import { useLoading } from '@/hooks'
|
||||||
|
//import { formatDate } from '@/utils/date'
|
||||||
|
|
||||||
defineOptions({ name: 'PostDetailDrawer' })
|
defineOptions({ name: 'PostDetailDrawer' })
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const { loading, setLoading } = useLoading()
|
const { loading, setLoading } = useLoading()
|
||||||
const detailData = ref<Array<{ label: string; value: any }>>([])
|
const primaryInfo = ref<any>(null)
|
||||||
|
|
||||||
// 获取详情
|
// 获取详情
|
||||||
const getDetail = async (id: string) => {
|
const getDetail = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const { data } = await getPostDetail(id)
|
primaryInfo.value = null
|
||||||
if (data) {
|
|
||||||
detailData.value = [
|
const response = await getPostDetail(id)
|
||||||
{ label: '岗位名称', value: data.postName },
|
const data = response?.data || response
|
||||||
{ label: '岗位排序', value: data.postSort },
|
|
||||||
{ label: '状态', value: Number(data.status) === 1 ? '正常' : '停用' },
|
if (data && typeof data === 'object') {
|
||||||
{ label: '备注', value: data.remark },
|
primaryInfo.value = {
|
||||||
{ label: '创建时间', value: data.createTime },
|
id: data.postId ?? data.id,
|
||||||
{ label: '更新时间', value: data.updateTime },
|
name: data.postName ?? data.name,
|
||||||
]
|
sort: data.postSort,
|
||||||
|
status: data.status,
|
||||||
|
remark: data.remark,
|
||||||
|
createTime: data.createTime,
|
||||||
|
updateTime: data.updateTime,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('获取岗位详情失败:', error)
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status: number | string) => {
|
||||||
|
if (status === 1 || status === '1') return '正常'
|
||||||
|
if (status === 0 || status === '0') return '停用'
|
||||||
|
return '未知状态'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态标签颜色
|
||||||
|
const getStatusColor = (status: number | string) => {
|
||||||
|
if (status === 1 || status === '1') return 'rgb(82, 196, 26)'
|
||||||
|
if (status === 0 || status === '0') return 'rgb(245, 34, 45)'
|
||||||
|
return 'rgb(150, 150, 150)'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭抽屉
|
||||||
|
const handleClose = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
const onDetail = async (id: string) => {
|
const onDetail = async (id: string) => {
|
||||||
|
if (!id) return
|
||||||
visible.value = true
|
visible.value = true
|
||||||
|
await nextTick()
|
||||||
await getDetail(id)
|
await getDetail(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
onDetail,
|
onDetail,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.post-detail-drawer {
|
||||||
|
--primary-color: #3498db;
|
||||||
|
--light-bg: #f9fafc;
|
||||||
|
--border-color: #eaeaea;
|
||||||
|
--label-color: #666;
|
||||||
|
--value-color: #333;
|
||||||
|
--group-title-color: #555;
|
||||||
|
--group-bg: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-container {
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-name {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--value-color);
|
||||||
|
margin-right: 15px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
border: none;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-group {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
position: relative;
|
||||||
|
background-color: var(--group-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-group:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--group-title-color);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-title::before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 4px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
margin-right: 8px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: white;
|
||||||
|
padding: 12px 15px;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--label-color);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-weight: 500;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label::after {
|
||||||
|
content: ':';
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--value-color);
|
||||||
|
font-weight: 500;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remark-container {
|
||||||
|
padding: 16px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.remark-content {
|
||||||
|
color: var(--value-color);
|
||||||
|
line-height: 1.7;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<a-space>
|
<a-space>
|
||||||
|
<a-link v-permission="['system:post:query']" title="详情" @click="onDetail(record)">详情</a-link>
|
||||||
<a-link v-permission="['system:post:update']" title="修改" @click="onUpdate(record)">修改</a-link>
|
<a-link v-permission="['system:post:update']" title="修改" @click="onUpdate(record)">修改</a-link>
|
||||||
<a-link
|
<a-link
|
||||||
v-permission="['system:post:delete']"
|
v-permission="['system:post:delete']"
|
||||||
|
@ -45,11 +46,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TableColumnData, TableInstance } from '@arco-design/web-vue'
|
import type { TableColumnData } from '@arco-design/web-vue'
|
||||||
import PostAddModal from './PostAddModal.vue'
|
import PostAddModal from './PostAddModal.vue'
|
||||||
import PostDetailDrawer from './PostDetailDrawer.vue'
|
import PostDetailDrawer from './PostDetailDrawer.vue'
|
||||||
import { deletePost, pagePost,listPost } from '@/apis/system/post'
|
import { deletePost, listPost } from '@/apis/system/post'
|
||||||
import type { PostVO, PostPageQuery } from '@/apis/system/type'
|
import type { PostVO } from '@/apis/system/type'
|
||||||
import { useResetReactive, useTable } from '@/hooks'
|
import { useResetReactive, useTable } from '@/hooks'
|
||||||
import { isMobile } from '@/utils'
|
import { isMobile } from '@/utils'
|
||||||
import has from '@/utils/has'
|
import has from '@/utils/has'
|
||||||
|
@ -80,7 +81,7 @@ const queryFormColumns: ColumnItem[] = reactive([
|
||||||
props: {
|
props: {
|
||||||
options: [
|
options: [
|
||||||
{ label: '正常', value: 1 },
|
{ label: '正常', value: 1 },
|
||||||
{ label: '停用', value: 0 }
|
{ label: '停用', value: 0 },
|
||||||
],
|
],
|
||||||
placeholder: '请选择状态',
|
placeholder: '请选择状态',
|
||||||
},
|
},
|
||||||
|
@ -93,8 +94,8 @@ const {
|
||||||
pagination,
|
pagination,
|
||||||
search,
|
search,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
} = useTable((params) => listPost({
|
} = useTable((params) => listPost({
|
||||||
...queryForm,
|
...queryForm,
|
||||||
}), { immediate: true })
|
}), { immediate: true })
|
||||||
|
|
||||||
const tableColumns = ref<TableColumnData[]>([
|
const tableColumns = ref<TableColumnData[]>([
|
||||||
|
@ -105,50 +106,50 @@ const tableColumns = ref<TableColumnData[]>([
|
||||||
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
|
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
|
||||||
fixed: !isMobile() ? 'left' : undefined,
|
fixed: !isMobile() ? 'left' : undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '岗位名称',
|
title: '岗位名称',
|
||||||
dataIndex: 'postName',
|
dataIndex: 'postName',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
fixed: !isMobile() ? 'left' : undefined,
|
fixed: !isMobile() ? 'left' : undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '岗位排序',
|
title: '岗位排序',
|
||||||
dataIndex: 'postSort',
|
dataIndex: 'postSort',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true
|
tooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
slotName: 'status',
|
slotName: 'status',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 100
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '备注',
|
title: '说明',
|
||||||
dataIndex: 'remark',
|
dataIndex: 'remark',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true
|
tooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
sortable: {
|
sortable: {
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
slotName: 'action',
|
slotName: 'action',
|
||||||
width: 160,
|
width: 200,
|
||||||
fixed: !isMobile() ? 'right' : undefined,
|
fixed: !isMobile() ? 'right' : undefined,
|
||||||
show: has.hasPermOr(['system:post:update', 'system:post:delete']),
|
show: has.hasPermOr(['system:post:update', 'system:post:delete']),
|
||||||
},
|
},
|
||||||
|
@ -187,4 +188,4 @@ const onDetail = (record: PostVO) => {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
title="分配角色"
|
title="分配角色"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
:esc-to-close="false"
|
:esc-to-close="false"
|
||||||
:width="width >= 1100 ? 1100 : '100%'"
|
:width="width >= 1100 ? 1100 : '100%'"
|
||||||
draggable
|
draggable
|
||||||
@before-ok="save"
|
@before-ok="save"
|
||||||
@close="reset"
|
@close="reset"
|
||||||
>
|
>
|
||||||
<UserSelect v-if="visible" ref="UserSelectRef" v-model:value="selectedUsers" :role-id="dataId" @select-user="onSelectUser" />
|
<UserSelect v-if="visible" ref="UserSelectRef" v-model:value="selectedUsers" :role-id="dataId" @select-user="onSelectUser" />
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
import { Message } from '@arco-design/web-vue'
|
import { Message } from '@arco-design/web-vue'
|
||||||
import { useWindowSize } from '@vueuse/core'
|
import { useWindowSize } from '@vueuse/core'
|
||||||
import { assignToUsers } from '@/apis/system/role'
|
import { assignToUsers } from '@/apis/system/role'
|
||||||
|
// 根据角色分配用户
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'save-success'): void
|
(e: 'save-success'): void
|
||||||
|
|
|
@ -98,21 +98,11 @@ const columns: TableInstance['columns'] = [
|
||||||
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
|
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
|
||||||
fixed: !isMobile() ? 'left' : undefined,
|
fixed: !isMobile() ? 'left' : undefined,
|
||||||
},
|
},
|
||||||
{
|
{ title: '用户名', dataIndex: 'name', slotName: 'name', minWidth: 120, ellipsis: true, tooltip: true },
|
||||||
title: '昵称',
|
|
||||||
dataIndex: 'nickname',
|
|
||||||
slotName: 'nickname',
|
|
||||||
minWidth: 130,
|
|
||||||
ellipsis: true,
|
|
||||||
tooltip: true,
|
|
||||||
fixed: !isMobile() ? 'left' : undefined,
|
|
||||||
},
|
|
||||||
{ title: '用户名', dataIndex: 'username', slotName: 'username', minWidth: 120, ellipsis: true, tooltip: true },
|
|
||||||
{ title: '状态', dataIndex: 'status', slotName: 'status', align: 'center' },
|
|
||||||
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center' },
|
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center' },
|
||||||
|
{ title: '状态', dataIndex: 'status', slotName: 'status', align: 'center' },
|
||||||
{ title: '所属部门', dataIndex: 'deptName', minWidth: 140, ellipsis: true, tooltip: true },
|
{ title: '所属部门', dataIndex: 'deptName', minWidth: 140, ellipsis: true, tooltip: true },
|
||||||
{ title: '角色', dataIndex: 'roleNames', slotName: 'roleNames', minWidth: 165 },
|
{ title: '角色', dataIndex: 'roleNames', slotName: 'roleNames', minWidth: 165 },
|
||||||
{ title: '描述', dataIndex: 'description', minWidth: 130, ellipsis: true, tooltip: true },
|
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
|
@ -142,7 +132,7 @@ const onMulDelete = () => {
|
||||||
content: `是否确定取消分配角色给所选的${selectedKeys.value.length}个用户?`,
|
content: `是否确定取消分配角色给所选的${selectedKeys.value.length}个用户?`,
|
||||||
hideCancel: false,
|
hideCancel: false,
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
await unassignFromUsers(selectedKeys.value)
|
await unassignFromUsers(selectedKeys.value.map(id => String(id)))
|
||||||
Message.success('取消成功')
|
Message.success('取消成功')
|
||||||
search()
|
search()
|
||||||
},
|
},
|
||||||
|
@ -151,7 +141,7 @@ const onMulDelete = () => {
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
const onDelete = (record: RoleUserResp) => {
|
const onDelete = (record: RoleUserResp) => {
|
||||||
return handleDelete(() => unassignFromUsers([record.id]), {
|
return handleDelete(() => unassignFromUsers([String(record.id)]), {
|
||||||
content: `是否确定取消分配角色给用户「${record.nickname}(${record.username})」?`,
|
content: `是否确定取消分配角色给用户「${record.nickname}(${record.username})」?`,
|
||||||
successTip: '取消成功',
|
successTip: '取消成功',
|
||||||
showModal: true,
|
showModal: true,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
import RoleTree from './tree/index.vue'
|
import RoleTree from './tree/index.vue'
|
||||||
import Permission from './components/Permission.vue'
|
import Permission from './components/Permission.vue'
|
||||||
import RoleUser from './components/RoleUser.vue'
|
import RoleUser from './components/RoleUser.vue'
|
||||||
|
import {listRoleUserId} from "@/apis";
|
||||||
|
|
||||||
defineOptions({ name: 'SystemRole' })
|
defineOptions({ name: 'SystemRole' })
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ const save = async () => {
|
||||||
try {
|
try {
|
||||||
const isInvalid = await formRef.value?.formRef?.validate()
|
const isInvalid = await formRef.value?.formRef?.validate()
|
||||||
if (isInvalid) return false
|
if (isInvalid) return false
|
||||||
await updateUserRole({ roleIds: form.roleIds }, dataId.value)
|
await updateUserRole({ roleIds: form.roleIds.map(id => String(id)) }, dataId.value)
|
||||||
Message.success('分配成功')
|
Message.success('分配成功')
|
||||||
emit('save-success')
|
emit('save-success')
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -93,7 +93,7 @@ const handleSubmit = async () => {
|
||||||
|
|
||||||
await bindUserRole({
|
await bindUserRole({
|
||||||
userId: props.userData.userId,
|
userId: props.userData.userId,
|
||||||
roleIds: selectedRoles.value
|
roleIds: selectedRoles.value.map(id => String(id))
|
||||||
})
|
})
|
||||||
|
|
||||||
Message.success('角色分配成功')
|
Message.success('角色分配成功')
|
||||||
|
|
|
@ -313,17 +313,17 @@ const columns: TableInstance['columns'] = [
|
||||||
},
|
},
|
||||||
{ title: '账号', dataIndex: 'account', minWidth: 140, ellipsis: true, tooltip: true },
|
{ title: '账号', dataIndex: 'account', minWidth: 140, ellipsis: true, tooltip: true },
|
||||||
{ title: '员工编码', dataIndex: 'userCode', minWidth: 120, ellipsis: true, tooltip: true },
|
{ title: '员工编码', dataIndex: 'userCode', minWidth: 120, ellipsis: true, tooltip: true },
|
||||||
{ title: '在职状态', dataIndex: 'userStatus', slotName: 'userStatus', align: 'center', width: 100 },
|
|
||||||
{ title: '员工性质', dataIndex: 'userType', slotName: 'userType', align: 'center', width: 100 },
|
|
||||||
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center', width: 80 },
|
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center', width: 80 },
|
||||||
{ title: '所属部门', dataIndex: 'deptName', minWidth: 180, ellipsis: true, tooltip: true },
|
|
||||||
{ title: '角色', dataIndex: 'roleIds', slotName: 'roleIds', minWidth: 165 },
|
|
||||||
{ title: '手机号', dataIndex: 'mobile', minWidth: 170, ellipsis: true, tooltip: true },
|
{ title: '手机号', dataIndex: 'mobile', minWidth: 170, ellipsis: true, tooltip: true },
|
||||||
{ title: '邮箱', dataIndex: 'email', minWidth: 170, ellipsis: true, tooltip: true },
|
{ title: '所属部门', dataIndex: 'deptName', minWidth: 180, ellipsis: true, tooltip: true },
|
||||||
{ title: '入职日期', dataIndex: 'hiredate', width: 120, ellipsis: true, tooltip: true },
|
|
||||||
{ title: '出生日期', dataIndex: 'birthdate', width: 120, ellipsis: true, tooltip: true, show: false },
|
|
||||||
{ title: '学历', dataIndex: 'educationLabel', width: 100, ellipsis: true, tooltip: true, show: false },
|
{ title: '学历', dataIndex: 'educationLabel', width: 100, ellipsis: true, tooltip: true, show: false },
|
||||||
{ title: '专业', dataIndex: 'majorField', width: 120, ellipsis: true, tooltip: true, show: false },
|
{ title: '专业', dataIndex: 'majorField', width: 120, ellipsis: true, tooltip: true, show: false },
|
||||||
|
{ title: '在职状态', dataIndex: 'userStatus', slotName: 'userStatus', align: 'center', width: 100 },
|
||||||
|
{ title: '员工性质', dataIndex: 'userType', slotName: 'userType', align: 'center', width: 100 },
|
||||||
|
{ title: '角色', dataIndex: 'roleName', slotName: 'roleName', minWidth: 185 },
|
||||||
|
{ title: '邮箱', dataIndex: 'email', slotName: 'email', minWidth: 170, ellipsis: true, tooltip: true },
|
||||||
|
{ title: '入职日期', dataIndex: 'hiredate', width: 120, ellipsis: true, tooltip: true },
|
||||||
|
{ title: '出生日期', dataIndex: 'birthdate', width: 120, ellipsis: true, tooltip: true, show: false },
|
||||||
{ title: '工作方向', dataIndex: 'workField', width: 120, ellipsis: true, tooltip: true, show: false },
|
{ title: '工作方向', dataIndex: 'workField', width: 120, ellipsis: true, tooltip: true, show: false },
|
||||||
{ title: '身份证', dataIndex: 'identityCard', width: 180, ellipsis: true, tooltip: true, show: false },
|
{ title: '身份证', dataIndex: 'identityCard', width: 180, ellipsis: true, tooltip: true, show: false },
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,25 +17,25 @@
|
||||||
</template>
|
</template>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<span style="margin-right: 10px">{{ userInfo.nickname }}</span>
|
<span style="margin-right: 10px">{{ userInfo.name }}</span>
|
||||||
<icon-edit :size="16" class="btn" @click="onUpdate" />
|
<icon-edit :size="16" class="btn" @click="onUpdate" />
|
||||||
</div>
|
</div>
|
||||||
<div class="id">
|
<div class="id">
|
||||||
<GiSvgIcon name="id" :size="16" />
|
<GiSvgIcon name="id" :size="16" />
|
||||||
<span>{{ userInfo.id }}</span>
|
<span>{{ userInfo.userId }}</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<a-descriptions :column="4" size="large">
|
<a-descriptions :column="4" size="large">
|
||||||
<a-descriptions-item :span="4">
|
<a-descriptions-item :span="4">
|
||||||
<template #label> <icon-user /><span style="margin-left: 5px">用户名</span></template>
|
<template #label> <icon-user /><span style="margin-left: 5px">用户名</span></template>
|
||||||
{{ userInfo.username }}
|
{{ userInfo.account }}
|
||||||
<icon-man v-if="userInfo.gender === 1" style="color: #19bbf1" />
|
<icon-man v-if="userInfo.gender === 1" style="color: #19bbf1" />
|
||||||
<icon-woman v-else-if="userInfo.gender === 2" style="color: #fa7fa9" />
|
<icon-woman v-else-if="userInfo.gender === 2" style="color: #fa7fa9" />
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :span="4">
|
<a-descriptions-item :span="4">
|
||||||
<template #label> <icon-phone /><span style="margin-left: 5px">手机</span></template>
|
<template #label> <icon-phone /><span style="margin-left: 5px">手机</span></template>
|
||||||
{{ userInfo.phone || '暂无' }}
|
{{ userInfo.mobile || '暂无' }}
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :span="4">
|
<a-descriptions-item :span="4">
|
||||||
<template #label> <icon-email /><span style="margin-left: 5px">邮箱</span></template>
|
<template #label> <icon-email /><span style="margin-left: 5px">邮箱</span></template>
|
||||||
|
@ -47,12 +47,12 @@
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
<a-descriptions-item :span="4">
|
<a-descriptions-item :span="4">
|
||||||
<template #label> <icon-user-group /><span style="margin-left: 5px">角色</span></template>
|
<template #label> <icon-user-group /><span style="margin-left: 5px">角色</span></template>
|
||||||
{{ userInfo.roles.join(',') }}
|
{{ userInfo.roles?.map(role => role.roleName).join(', ') || '暂无' }}
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">注册于 {{ userInfo.registrationDate }}</div>
|
<div class="footer">注册于 {{ userInfo.createTime }}</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<a-modal v-model:visible="visible" title="上传头像" :width="width >= 400 ? 400 : '100%'" :footer="false" draggable @close="reset">
|
<a-modal v-model:visible="visible" title="上传头像" :width="width >= 400 ? 400 : '100%'" :footer="false" draggable @close="reset">
|
||||||
|
@ -102,19 +102,22 @@ import { uploadAvatar } from '@/apis/system'
|
||||||
import 'vue-cropper/dist/index.css'
|
import 'vue-cropper/dist/index.css'
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
import getAvatar from '@/utils/avatar'
|
import getAvatar from '@/utils/avatar'
|
||||||
|
import XG_DEBUG from 'xgplayer/es/utils/debug'
|
||||||
|
import config = XG_DEBUG.config
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const userInfo = computed(() => userStore.userInfo)
|
const userInfo = computed(() => userStore.userInfo)
|
||||||
|
|
||||||
const avatar = {
|
const avatar = computed(() => ({
|
||||||
uid: '-2',
|
uid: '-2',
|
||||||
name: 'avatar.png',
|
name: 'avatar.png',
|
||||||
url: userInfo.value.avatar,
|
url: userInfo.value.avatar || getAvatar(userInfo.value.avatar, undefined),
|
||||||
}
|
}))
|
||||||
const avatarList = ref<FileItem[]>([avatar])
|
|
||||||
const fileRef = ref(reactive({ name: 'avatar.png' }))
|
const avatarList = computed<FileItem[]>(() => [avatar.value])
|
||||||
const options: cropperOptions = reactive({
|
const fileRef = ref<File | null>(null)
|
||||||
|
const options = reactive<cropperOptions>({
|
||||||
img: '',
|
img: '',
|
||||||
autoCrop: true,
|
autoCrop: true,
|
||||||
autoCropWidth: 160,
|
autoCropWidth: 160,
|
||||||
|
@ -128,13 +131,14 @@ const options: cropperOptions = reactive({
|
||||||
outputType: 'png',
|
outputType: 'png',
|
||||||
})
|
})
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
|
|
||||||
// 打开裁剪框
|
// 打开裁剪框
|
||||||
const onBeforeUpload = (file: File): boolean => {
|
const onBeforeUpload = (file: File): boolean => {
|
||||||
fileRef.value = file
|
fileRef.value = file
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
options.img = reader.result
|
options.img = reader.result as string
|
||||||
}
|
}
|
||||||
visible.value = true
|
visible.value = true
|
||||||
return false
|
return false
|
||||||
|
|
Loading…
Reference in New Issue