index.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. <template>
  2. <div class="hc-layout-box">
  3. <div class="hc-layout-left-box">
  4. <div class="user-avatar-box">
  5. <div v-loading="avatarLoading" class="user-avatar">
  6. <img :src="userInfo.avatar || avatarPng" alt="">
  7. <div class="user-avatar-upload">
  8. <el-upload
  9. :accept="accept" :action="action" :before-upload="beforeUpload" :data="upData"
  10. :headers="getTokenHeader()" :on-error="uploadError" :on-success="uploadFinish"
  11. :show-file-list="false" class="upload-dom"
  12. >
  13. <HcIcon fill name="camera" />
  14. </el-upload>
  15. </div>
  16. </div>
  17. <div class="user-name truncate">{{ userInfo.real_name || '游客' }}</div>
  18. </div>
  19. <div class="user-menu-box">
  20. <el-scrollbar>
  21. <HcMenuSimple :datas="menuOptions" :keys="menuKey" @change="handleMenuValue" />
  22. </el-scrollbar>
  23. </div>
  24. </div>
  25. <div class="hc-layout-content-box">
  26. <HcNewCard
  27. v-if="menuKey !== 'log' && menuKey !== 'recycle'" :title="menuItem.label" :ui="basicHight ? 'basic-hight' : ''"
  28. scrollbar
  29. >
  30. <template #extra>
  31. <span
  32. v-if="menuKey === 'basic' && !basicFormEdit" class="text-link"
  33. @click="basicFormEditClick"
  34. >编辑</span>
  35. <span
  36. v-if="menuKey === 'project'" class="text-link"
  37. @click="setDefaultProjectClick"
  38. >设置默认项目</span>
  39. </template>
  40. <template v-if="menuKey === 'basic'">
  41. <el-form
  42. ref="formUserRef" :model="formUserModel" :rules="formUserRules" label-position="top"
  43. size="large"
  44. >
  45. <el-row :gutter="20">
  46. <el-col :span="12">
  47. <el-form-item label="用户名称">
  48. <el-input v-model="formUserModel.real_name" disabled />
  49. </el-form-item>
  50. </el-col>
  51. <el-col :span="12">
  52. <el-form-item label="登录账号">
  53. <el-input v-model="formUserModel.account" disabled placeholder="" />
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="12">
  57. <el-form-item label="身份证号">
  58. <el-input v-model="formUserModel.idNumber" disabled placeholder="" />
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="12">
  62. <el-form-item :prop="basicFormEdit ? 'phone' : ''" label="绑定手机">
  63. <el-input
  64. v-model="formUserModel.phone" :disabled="!basicHight"
  65. placeholder="请输入绑定手机"
  66. />
  67. </el-form-item>
  68. </el-col>
  69. <el-col :span="12">
  70. <el-form-item label="所属角色">
  71. <el-input v-model="formUserModel.roleName" disabled placeholder="" />
  72. </el-form-item>
  73. </el-col>
  74. <el-col :span="12">
  75. <el-form-item label="所属部门">
  76. <el-input v-model="formUserModel.deptId" disabled placeholder="" />
  77. </el-form-item>
  78. </el-col>
  79. <el-col :span="12">
  80. <el-form-item label="CA签字体">
  81. <el-image
  82. v-if="formUserModel?.signatureUrl" :initial-index="0"
  83. :preview-src-list="[formUserModel?.signatureUrl]" :src="formUserModel?.signatureUrl"
  84. fit="cover" style="height: 60px"
  85. />
  86. <span v-else class="text-zinc-400">无CA签字体</span>
  87. </el-form-item>
  88. </el-col>
  89. </el-row>
  90. </el-form>
  91. </template>
  92. <template v-if="menuKey === 'password'">
  93. <el-form
  94. ref="formUserPassRef" :model="formUserPassModel" :rules="formUserPassRules" label-position="top"
  95. size="large" style="max-width: 400px; margin: auto;"
  96. >
  97. <el-form-item label="原始密码" prop="oldPassword">
  98. <el-input
  99. v-model="formUserPassModel.oldPassword" placeholder="请输入原始密码"
  100. show-password type="password"
  101. />
  102. </el-form-item>
  103. <el-form-item label="新的密码" prop="newPassword">
  104. <el-input
  105. v-model="formUserPassModel.newPassword" placeholder="请输入新的密码"
  106. show-password type="password"
  107. />
  108. </el-form-item>
  109. <el-form-item label="确认新密码" prop="newPassword1">
  110. <el-input
  111. v-model="formUserPassModel.newPassword1" placeholder="请输入确认新密码"
  112. show-password type="password"
  113. />
  114. </el-form-item>
  115. </el-form>
  116. </template>
  117. <template v-if="menuKey === 'project'">
  118. <el-menu :default-active="projectKey" class="hc-project-menu" unique-opened>
  119. <el-sub-menu v-for="item in projectContractArr" :index="item.id">
  120. <template #title>
  121. <HcIcon class="hc-menu-icon" name="folder-2" />
  122. <span>{{ item?.name }}</span>
  123. </template>
  124. <el-menu-item
  125. v-for="items in item?.contractInfoList ?? []" :index="items?.id"
  126. @click="projectMenuValue(item, items)"
  127. >
  128. <HcIcon v-if="projectKey === items?.id" class="hc-menu-icon" fill name="star" />
  129. <span>{{ items?.name }}</span>
  130. </el-menu-item>
  131. </el-sub-menu>
  132. </el-menu>
  133. </template>
  134. </HcNewCard>
  135. <div v-if="basicFormEdit" class="hc-card-foot-box">
  136. <el-button :loading="saveUserLoading" hc-btn type="primary" @click="saveUserInfoClick">
  137. <HcIcon name="save" />
  138. <span>保存</span>
  139. </el-button>
  140. <el-button hc-btn @click="cancelUserClick">
  141. <HcIcon name="close" />
  142. <span>取消</span>
  143. </el-button>
  144. </div>
  145. <HcNewCard v-if="menuKey === 'log'" :title="menuItem.label">
  146. <template #search>
  147. <div class="flex items-center">
  148. <div class="w-32">
  149. <el-select
  150. v-model="searchLogForm.operationModule" clearable placeholder="业务模块"
  151. @change="BusinessModuleValue"
  152. >
  153. <el-option
  154. v-for="item in operationModuleData" :key="item.value"
  155. :label="item?.dictValue" :value="item?.dictKey"
  156. />
  157. </el-select>
  158. </div>
  159. <div class="w-32 ml-2">
  160. <el-select
  161. v-model="searchLogForm.operationView" clearable placeholder="页面"
  162. @change="OperationViewValue"
  163. >
  164. <el-option
  165. v-for="item in operationViewData" :key="item.value" :label="item?.dictValue"
  166. :value="item?.dictKey"
  167. />
  168. </el-select>
  169. </div>
  170. <div class="w-40 ml-2">
  171. <el-select v-model="searchLogForm.operationType" clearable placeholder="操作类型">
  172. <el-option
  173. v-for="item in operationTypeData" :key="item.value" :label="item?.dictValue"
  174. :value="item?.dictKey"
  175. />
  176. </el-select>
  177. </div>
  178. <div class="w-20 ml-2">
  179. <el-select v-model="searchLogForm.operationMedium" clearable placeholder="设备">
  180. <el-option
  181. v-for="item in deviceData" :key="item.value" :label="item?.label"
  182. :value="item?.value"
  183. />
  184. </el-select>
  185. </div>
  186. <div class="w-20 ml-2">
  187. <el-select v-model="searchLogForm.createUser" clearable placeholder="操作人">
  188. <el-option
  189. v-for="item in userListData" :key="item.userId" :label="item?.userName"
  190. :value="item?.userId"
  191. />
  192. </el-select>
  193. </div>
  194. <div class="w-64 ml-2">
  195. <HcDatePicker :dates="betweenTime" clearable @change="betweenDateUpdate" />
  196. </div>
  197. <div class="w-60 ml-2">
  198. <el-input
  199. v-model="searchLogForm.queryValue" clearable placeholder="请输入名称关键词检索"
  200. @keyup="keyUpEvent"
  201. />
  202. </div>
  203. <div class="ml-2">
  204. <el-button type="primary" @click="searchClick">
  205. <HcIcon name="search-2" />
  206. <span>搜索</span>
  207. </el-button>
  208. </div>
  209. </div>
  210. </template>
  211. <HcTable :column="logTableColumn" :datas="logTableData" :loading="logTableLoading" is-new :index-style="{ width: 60 }">
  212. <template #operationContent="{ row }">
  213. <div class="text-link text-cut" @click="tableOperationContent(row)">
  214. {{ row?.operationContent }}
  215. </div>
  216. </template>
  217. </HcTable>
  218. <template #action>
  219. <HcPages :pages="searchLogForm" @change="pageLogChange" />
  220. </template>
  221. </HcNewCard>
  222. <HcNewCard v-if="menuKey === 'recycle'" action-size="lg">
  223. <template #header>
  224. <div class="mr-5">{{ menuItem.label }}</div>
  225. <HcNewSwitch :datas="userTypeTab" :keys="userTypeKey" size="default" @change="userTypeChange" />
  226. </template>
  227. <template #extra>
  228. <HcNewSwitch :datas="tabTypeTab" :keys="tabTypeKey" size="default" @change="tabTypeChange" />
  229. </template>
  230. <HcTable
  231. ref="recycleTableRef" :column="recycleTableColumn" :datas="recycleTableData" :loading="recycleTableLoading"
  232. is-new :index-style="{ width: 60 }" is-check :check-style="{ width: 29 }"
  233. @selection-change="recycleTableSelectionChange"
  234. />
  235. <template #action>
  236. <div class="foot-recycle">
  237. <el-button
  238. :disabled="userTypeKey === '2'" :loading="recycleBtnLoading" hc-btn type="primary"
  239. @click="recycleBtnClick"
  240. >
  241. <HcIcon fill name="reply" />
  242. <span>恢复</span>
  243. </el-button>
  244. <HcPages :pages="searchRecycleForm" @change="pageRecycleChange" />
  245. </div>
  246. </template>
  247. </HcNewCard>
  248. </div>
  249. <!-- 日志内容 -->
  250. <hc-new-dialog v-model="operationContentModal" title="日志内容" widths="38rem">
  251. <!-- {{ operationContent }} -->
  252. <div v-html="saveData" />
  253. </hc-new-dialog>
  254. </div>
  255. </template>
  256. <script setup>
  257. import { onMounted, ref } from 'vue'
  258. import { useAppStore } from '~src/store'
  259. import userApi from '~api/userInfo/index'
  260. import { useRoute, useRouter } from 'vue-router'
  261. import avatarPng from '~src/assets/images/avatar.png'
  262. import { getTokenHeader } from '~src/api/request/header'
  263. import { arrIndex, formValidate, getArrValue, isPhone } from 'js-fast-way'
  264. import { getContractUserList } from '~api/other'
  265. import md5 from 'js-md5'
  266. //初始变量
  267. const router = useRouter()
  268. const useRoutes = useRoute()
  269. const useAppState = useAppStore()
  270. //全局变量信息
  271. const userInfo = ref(useAppState.getUserInfo)
  272. const projectId = ref(useAppState.getProjectId)
  273. const contractId = ref(useAppState.getContractId)
  274. const projectContractArr = ref(useAppState.getProjectContract)
  275. //路由参数数据
  276. const routerQuery = useRoutes?.query
  277. let MenuType = routerQuery?.MenuType || 'basic'
  278. //上传组件参数
  279. const action = '/api/blade-resource/oss/endpoint/put-file'
  280. const accept = 'image/png,image/jpg,image/jpeg'
  281. const upData = ref({})
  282. //上传前
  283. const avatarLoading = ref(false)
  284. const beforeUpload = () => {
  285. avatarLoading.value = true
  286. return true
  287. }
  288. //上传完成
  289. const uploadFinish = async (res) => {
  290. const link = res?.data?.link ?? ''
  291. const user_id = userInfo.value?.user_id ?? ''
  292. if (link) {
  293. const { error, code } = await userApi.updateUserInfo({ avatar: link, id: user_id })
  294. if (!error && code === 200) {
  295. avatarLoading.value = false
  296. userInfo.value.avatar = link
  297. window?.$message?.success('更换头像成功')
  298. useAppState.setUserInfo(userInfo.value)
  299. } else {
  300. avatarLoading.value = false
  301. }
  302. } else {
  303. window?.$message?.warning('上传头像异常,请稍后再试')
  304. avatarLoading.value = false
  305. }
  306. }
  307. //上传失败
  308. const uploadError = () => {
  309. avatarLoading.value = false
  310. window?.$message?.warning('上传头像失败')
  311. }
  312. //左侧菜单
  313. const menuKey = ref(MenuType)
  314. const menuItem = ref({})
  315. const menuOptions = ref([
  316. { key: 'basic', label: '基础信息', icon: 'user-3' },
  317. { key: 'password', label: '密码设置', icon: 'lock-unlock' },
  318. { key: 'project', label: '参建项目', icon: 'folder-2' },
  319. { key: 'log', label: '操作日志', icon: 'file-mark' },
  320. { key: 'recycle', label: '回收站', icon: 'delete-bin-5' },
  321. ])
  322. //获取菜单对象数据
  323. const menuObjItem = () => {
  324. const index = arrIndex(menuOptions.value, 'key', menuKey.value)
  325. menuItem.value = menuOptions.value[index]
  326. }
  327. //菜单被点击
  328. const handleMenuValue = (item) => {
  329. menuItem.value = item
  330. menuKey.value = item?.key
  331. router.push({
  332. path: useRoutes.path,
  333. query: {
  334. MenuType: item?.key,
  335. },
  336. })
  337. getPageTypeData(item?.key)
  338. }
  339. //获取用户列表
  340. const userListData = ref([])
  341. const getUserListData = async () => {
  342. const { data } = await getContractUserList({
  343. contractId: contractId.value,
  344. })
  345. userListData.value = getArrValue(data)
  346. }
  347. //渲染完成
  348. onMounted(() => {
  349. menuObjItem()
  350. getPageTypeData(menuKey.value)
  351. getUserListData()
  352. })
  353. //根据类型,获取相关数据
  354. const getPageTypeData = (key) => {
  355. //编辑状态
  356. if (key === 'password') {
  357. basicFormEdit.value = true
  358. basicHight.value = true
  359. } else {
  360. basicFormEdit.value = false
  361. basicHight.value = false
  362. }
  363. //请求数据
  364. if (key === 'basic') {
  365. queryCurrentUserData()
  366. } else if (key === 'project') {
  367. getDefaultProject()
  368. } else if (key === 'log') {
  369. queryBusinessModule()
  370. queryOperationView()
  371. operationTypeStatus()
  372. getLogTableData()
  373. } else if (key === 'recycle') {
  374. getRecycleTableData()
  375. }
  376. }
  377. //是否编辑
  378. const basicFormEdit = ref(false)
  379. const basicHight = ref(false)
  380. //基础信息表单
  381. const formUserRef = ref(null)
  382. const formUserModel = ref(userInfo.value)
  383. const formUserRules = {
  384. phone: {
  385. required: true,
  386. validator: (rule, value, callback) => {
  387. if (!value) {
  388. callback(new Error('请输入手机号'))
  389. } else if (!isPhone(value)) {
  390. callback(new Error('手机号码格式错误'))
  391. } else {
  392. callback()
  393. }
  394. },
  395. trigger: 'blur',
  396. },
  397. }
  398. //获取用户信息
  399. const queryCurrentUserData = async () => {
  400. const { error, code, data } = await userApi.queryCurrentUserData()
  401. if (!error && code === 200) {
  402. formUserModel.value.deptId = data?.deptId || ''
  403. formUserModel.value.idNumber = data?.idNumber || ''
  404. formUserModel.value.roleName = data?.roleName || ''
  405. formUserModel.value.signatureUrl = data?.signatureUrl || ''
  406. }
  407. }
  408. //切换编辑模式
  409. const basicFormEditClick = () => {
  410. basicFormEdit.value = true
  411. basicHight.value = true
  412. }
  413. //保存数据
  414. const saveUserLoading = ref(false)
  415. const saveUserInfoClick = () => {
  416. const key = menuKey.value
  417. if (key === 'basic') {
  418. saveUserInfoData()
  419. } else if (key === 'password') {
  420. saveUpdatePassword()
  421. }
  422. }
  423. //取消修改
  424. const cancelUserClick = () => {
  425. const key = menuKey.value
  426. if (key === 'basic') {
  427. basicFormEdit.value = false
  428. basicHight.value = false
  429. } else {
  430. console.log('我也不知道这个点了干什么,反正UI图上有,至于有什么作用,不知道。。')
  431. }
  432. }
  433. //保存用户信息
  434. const saveUserInfoData = async () => {
  435. const { phone, user_id } = formUserModel.value
  436. if (phone && isPhone(phone)) {
  437. saveUserLoading.value = true
  438. const { error, code } = await userApi.updateUserInfo({
  439. phone: phone,
  440. id: user_id,
  441. })
  442. if (!error && code === 200) {
  443. saveUserLoading.value = false
  444. window?.$message?.success('保存成功')
  445. userInfo.value.phone = phone
  446. useAppState.setUserInfo(userInfo.value)
  447. } else {
  448. saveUserLoading.value = false
  449. }
  450. }
  451. }
  452. //密码设置表单
  453. const formUserPassRef = ref(null)
  454. const formUserPassModel = ref({ oldPassword: '', newPassword: '', newPassword1: '' })
  455. const formUserPassRules = {
  456. oldPassword: {
  457. required: true,
  458. trigger: 'blur',
  459. message: '请输入原始密码',
  460. },
  461. newPassword: {
  462. required: true,
  463. validator(rule, value, callback) {
  464. const pass = formUserPassModel.value.newPassword1
  465. if (!value) {
  466. callback(new Error('请输入新的密码'))
  467. } else if (pass && value !== pass) {
  468. callback(new Error('新的密码和确认新密码不一致'))
  469. }
  470. callback()
  471. },
  472. trigger: 'blur',
  473. },
  474. newPassword1: {
  475. required: true,
  476. validator(rule, value, callback) {
  477. const pass = formUserPassModel.value.newPassword
  478. if (!value) {
  479. callback(new Error('请输入确认新密码'))
  480. } else if (pass && value !== pass) {
  481. callback(new Error('新的密码和确认新密码不一致'))
  482. }
  483. callback()
  484. },
  485. trigger: 'blur',
  486. },
  487. }
  488. //更新密码
  489. const saveUpdatePassword = async () => {
  490. const res = await formValidate(formUserPassRef.value)
  491. if (res) {
  492. const form = formUserPassModel.value
  493. saveUserLoading.value = true
  494. const { error, code } = await userApi.updatePassword({
  495. oldPassword: md5(form?.oldPassword),
  496. newPassword: md5(form?.newPassword),
  497. newPassword1: md5(form?.newPassword1),
  498. plaintextPassword: form?.newPassword,
  499. })
  500. if (!error && code === 200) {
  501. saveUserLoading.value = false
  502. window?.$message?.success('密码修改成功')
  503. formUserPassModel.value = {
  504. oldPassword: '',
  505. newPassword: '',
  506. newPassword1: '',
  507. }
  508. } else {
  509. saveUserLoading.value = false
  510. }
  511. }
  512. }
  513. //获取默认项目
  514. const projectKey = ref(null)
  515. const getDefaultProject = async () => {
  516. const { error, code, data } = await userApi.getDefaultProject()
  517. if (!error && code === 200) {
  518. projectKey.value = data['contractId']
  519. }
  520. }
  521. //项目被选择
  522. const menuProjectId = ref('')
  523. const menuContractId = ref('')
  524. const projectMenuValue = (item, items) => {
  525. menuProjectId.value = item?.id
  526. menuContractId.value = items?.id
  527. projectKey.value = items?.id
  528. }
  529. //设置为默认项目
  530. const setDefaultProjectClick = async () => {
  531. const pid = menuProjectId.value, cid = menuContractId.value
  532. if (pid && cid) {
  533. const { error, code } = await userApi.setDefaultProject({
  534. projectId: pid,
  535. contractId: cid,
  536. })
  537. if (!error && code === 200) {
  538. window?.$message?.success('设置成功')
  539. }
  540. } else {
  541. window?.$message?.warning('请先在下方选择一个项目合同段')
  542. }
  543. }
  544. //搜索和分页数据
  545. const searchLogForm = ref({
  546. operationModule: null, operationView: null, operationType: null, operationMedium: null,
  547. queryValue: null, startTime: null, endTime: null,
  548. current: 1, size: 10, total: 0, createUser:null,
  549. })
  550. //业务模块
  551. const operationModuleData = ref([])
  552. const queryBusinessModule = async () => {
  553. const { error, code, data } = await userApi.queryBusinessModule()
  554. if (!error && code === 200) {
  555. operationModuleData.value = data
  556. } else {
  557. operationModuleData.value = []
  558. }
  559. }
  560. const BusinessModuleValue = () => {
  561. searchLogForm.value.operationView = null
  562. searchLogForm.value.operationType = null
  563. queryOperationView()
  564. operationTypeStatus()
  565. }
  566. //页面
  567. const operationViewData = ref([])
  568. const queryOperationView = async () => {
  569. const { error, code, data } = await userApi.queryOperationView({
  570. businessModule: searchLogForm.value?.operationModule || '',
  571. })
  572. if (!error && code === 200) {
  573. operationViewData.value = data
  574. } else {
  575. operationViewData.value = []
  576. }
  577. }
  578. const OperationViewValue = () => {
  579. searchLogForm.value.operationType = null
  580. operationTypeStatus()
  581. }
  582. //操作类型
  583. const operationTypeData = ref([])
  584. const operationTypeStatus = async () => {
  585. const { error, code, data } = await userApi.queryOperationTypeList({
  586. businessModule: searchLogForm.value?.operationModule || '',
  587. operationView: searchLogForm.value?.operationView || '',
  588. })
  589. if (!error && code === 200) {
  590. operationTypeData.value = data
  591. } else {
  592. operationTypeData.value = []
  593. }
  594. }
  595. //设备
  596. const deviceData = ref([{ label: 'APP', value: 'APP' }, { label: 'PC', value: 'PC' }])
  597. //表格数据
  598. const logTableColumn = ref([
  599. { key: 'operationModule', name: '业务模块', width: '180' },
  600. { key: 'operationTypeValue', name: '操作类型', width: '220' },
  601. { key: 'operationMedium', name: '设备', align: 'center', width: '80' },
  602. { key: 'operationContent', name: '操作内容' },
  603. { key: 'createUserName', name: '操作人', align: 'center', width: '120' },
  604. { key: 'createTime', name: '操作时间', align: 'center', width: '180' },
  605. ])
  606. const logTableData = ref([])
  607. //日期时间被选择
  608. const betweenTime = ref(null)
  609. const betweenDateUpdate = ({ val, arr }) => {
  610. betweenTime.value = arr
  611. searchLogForm.value.startTime = val?.start
  612. searchLogForm.value.endTime = val?.end
  613. }
  614. //回车搜索
  615. const keyUpEvent = (e) => {
  616. if (e.key === 'Enter') {
  617. searchLogForm.value.current = 1
  618. getLogTableData()
  619. }
  620. }
  621. //搜索
  622. const searchClick = () => {
  623. searchLogForm.value.current = 1
  624. getLogTableData()
  625. }
  626. //分页被点击
  627. const pageLogChange = ({ current, size }) => {
  628. searchLogForm.value.current = current
  629. searchLogForm.value.size = size
  630. getLogTableData()
  631. }
  632. //获取数据
  633. const logTableLoading = ref(false)
  634. const getLogTableData = async () => {
  635. logTableLoading.value = true
  636. const { error, code, data } = await userApi.getOperationLog({
  637. projectId: projectId.value,
  638. contractId: contractId.value,
  639. ...searchLogForm.value,
  640. })
  641. logTableLoading.value = false
  642. if (!error && code === 200) {
  643. logTableData.value = getArrValue(data['records'])
  644. searchLogForm.value.total = data.total || 0
  645. } else {
  646. logTableData.value = []
  647. searchLogForm.value.total = 0
  648. }
  649. }
  650. //查看日志内容
  651. const operationContentModal = ref(false)
  652. const operationContent = ref('')
  653. const saveData = ref('')
  654. const tableOperationContent = (row) => {
  655. operationContent.value = row['operationContent'] ?? ''
  656. saveData.value = row['saveData']
  657. operationContentModal.value = true
  658. }
  659. //个人和全部切换
  660. const userTypeKey = ref('1')
  661. const userTypeTab = ref([{ key: '1', name: '个人' }, { key: '2', name: '全部' }])
  662. const userTypeChange = (item) => {
  663. userTypeKey.value = item?.key
  664. if (item?.key === '1') {
  665. searchRecycleForm.value.createUserName = ''
  666. } else {
  667. searchRecycleForm.value.createUserName = 'ALL'
  668. }
  669. getRecycleTableData()
  670. }
  671. //结构类型tab数据和相关处理
  672. const tabTypeKey = ref('1')
  673. const tabTypeTab = ref([
  674. { key: '1', name: '文件资料' },
  675. { key: '2', name: '工程划分' },
  676. ])
  677. const tabTypeChange = (item) => {
  678. tabTypeKey.value = item?.key
  679. tabTypeKey.value = item?.key
  680. searchRecycleForm.value.current = 1
  681. searchRecycleForm.value.delType = item?.key
  682. getRecycleTableData()
  683. }
  684. //搜索和分页数据
  685. const searchRecycleForm = ref({
  686. projectId: projectId.value, contractId: contractId.value, createUserName: '',
  687. delType: tabTypeKey.value, current: 1, size: 20, total: 0,
  688. })
  689. //表格数据
  690. const recycleTableRef = ref(null)
  691. const recycleTableColumn = ref([
  692. { key: 'fileName', name: '删除内容' },
  693. { key: 'position', name: '父节点名称' },
  694. { key: 'createUserName', name: '操作人' },
  695. { key: 'operationTime', name: '删除时间', align: 'center', width: '180' },
  696. ])
  697. const recycleTableLoading = ref(false)
  698. const recycleTableData = ref(null)
  699. //分页被点击
  700. const pageRecycleChange = ({ current, size }) => {
  701. searchRecycleForm.value.current = current
  702. searchRecycleForm.value.size = size
  703. getRecycleTableData()
  704. }
  705. //获取数据
  706. const getRecycleTableData = async () => {
  707. const { error, code, data } = await userApi.queryRecycleBinList({
  708. projectId: projectId.value,
  709. contractId: contractId.value,
  710. delType: tabTypeKey.value,
  711. ...searchRecycleForm.value,
  712. })
  713. if (!error && code === 200) {
  714. recycleTableData.value = getArrValue(data['records'])
  715. searchRecycleForm.value.total = data.total || 0
  716. } else {
  717. recycleTableData.value = []
  718. searchRecycleForm.value.total = 0
  719. }
  720. }
  721. //多选
  722. const RecycleCheckedKeys = ref([])
  723. const recycleTableSelectionChange = (val) => {
  724. RecycleCheckedKeys.value = val
  725. }
  726. //恢复
  727. const recycleBtnLoading = ref(false)
  728. const recycleBtnClick = async () => {
  729. const rows = RecycleCheckedKeys.value
  730. if (rows.length > 0) {
  731. //请求数据
  732. recycleBtnLoading.value = true
  733. const { error, code } = await userApi.recycleBinRegain({
  734. projectId: projectId.value,
  735. contractId: contractId.value,
  736. delType: tabTypeKey.value,
  737. regainIds: rows,
  738. })
  739. recycleBtnLoading.value = false
  740. if (!error && code === 200) {
  741. window?.$message?.success('操作成功')
  742. searchRecycleForm.value.current = 1
  743. getRecycleTableData()
  744. }
  745. } else {
  746. window.$message?.warning('请先勾选要恢复的数据')
  747. }
  748. }
  749. </script>
  750. <style lang="scss" scoped>
  751. @import "../../styles/user/index.scss";
  752. </style>
  753. <style lang="scss">
  754. .user-avatar-upload .upload-dom, .upload-dom .el-upload {
  755. height: 100%;
  756. width: 100%;
  757. }
  758. </style>