myuser.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="120px">
  4. <el-form-item :label="t('myuser.username')" prop="username">
  5. <el-input
  6. v-model="queryParams.username"
  7. :placeholder="t('myuser.pleaseEnterUsername')"
  8. clearable
  9. @keyup.enter="handleQuery"
  10. />
  11. </el-form-item>
  12. <!-- <el-form-item label="用戶暱稱" prop="nickname">-->
  13. <!-- <el-input-->
  14. <!-- v-model="queryParams.nickname"-->
  15. <!-- placeholder="請輸入用戶暱稱"-->
  16. <!-- clearable-->
  17. <!-- @keyup.enter="handleQuery"-->
  18. <!-- />-->
  19. <!-- </el-form-item>-->
  20. <el-form-item :label="t('myuser.phone')" prop="phone">
  21. <el-input
  22. v-model="queryParams.phone"
  23. :placeholder="t('myuser.pleaseEnterPhone')"
  24. clearable
  25. @keyup.enter="handleQuery"
  26. />
  27. </el-form-item>
  28. <!-- <el-form-item label="是否為代理" prop="isAgent">-->
  29. <!-- <el-select v-model="queryParams.isAgent" placeholder="請選擇是否為代理" clearable style="width: 240px">-->
  30. <!-- <el-option-->
  31. <!-- label="是"-->
  32. <!-- :value="true"-->
  33. <!-- />-->
  34. <!-- <el-option-->
  35. <!-- label="否"-->
  36. <!-- :value="false"-->
  37. <!-- />-->
  38. <!-- </el-select>-->
  39. <!-- </el-form-item>-->
  40. <!-- <el-form-item label="狀態" prop="status">-->
  41. <!-- <el-select v-model="queryParams.status" placeholder="用戶狀態" clearable style="width: 240px">-->
  42. <!-- <el-option-->
  43. <!-- v-for="dict in sys_normal_disable"-->
  44. <!-- :key="dict.value"-->
  45. <!-- :label="dict.label"-->
  46. <!-- :value="dict.value"-->
  47. <!-- />-->
  48. <!-- </el-select>-->
  49. <!-- </el-form-item>-->
  50. <!-- <el-form-item label="所屬代理ID" prop="agentId">-->
  51. <!-- <el-input-->
  52. <!-- v-model="queryParams.agentId"-->
  53. <!-- placeholder="請輸入所屬代理ID"-->
  54. <!-- clearable-->
  55. <!-- @keyup.enter="handleQuery"-->
  56. <!-- />-->
  57. <!-- </el-form-item>-->
  58. <el-form-item>
  59. <el-button type="primary" icon="Search" @click="handleQuery">{{ t('common.search') }}</el-button>
  60. <el-button icon="Refresh" @click="resetQuery">{{ t('common.reset') }}</el-button>
  61. </el-form-item>
  62. </el-form>
  63. <!-- <el-row :gutter="10" class="mb8">-->
  64. <!-- <el-col :span="1.5">-->
  65. <!-- <el-button-->
  66. <!-- type="primary"-->
  67. <!-- plain-->
  68. <!-- icon="Plus"-->
  69. <!-- @click="handleAdd"-->
  70. <!-- v-hasPermi="['system:loanuser:add']"-->
  71. <!-- >新增</el-button>-->
  72. <!-- </el-col>-->
  73. <!-- <el-col :span="1.5">-->
  74. <!-- <el-button-->
  75. <!-- type="success"-->
  76. <!-- plain-->
  77. <!-- icon="Edit"-->
  78. <!-- :disabled="single"-->
  79. <!-- @click="handleUpdate"-->
  80. <!-- v-hasPermi="['system:loanuser:edit']"-->
  81. <!-- >修改</el-button>-->
  82. <!-- </el-col>-->
  83. <!-- <el-col :span="1.5">-->
  84. <!-- <el-button-->
  85. <!-- type="danger"-->
  86. <!-- plain-->
  87. <!-- icon="Delete"-->
  88. <!-- :disabled="multiple"-->
  89. <!-- @click="handleDelete"-->
  90. <!-- v-hasPermi="['system:loanuser:remove']"-->
  91. <!-- >刪除</el-button>-->
  92. <!-- </el-col>-->
  93. <!-- <el-col :span="1.5">-->
  94. <!-- <el-button-->
  95. <!-- type="warning"-->
  96. <!-- plain-->
  97. <!-- icon="Download"-->
  98. <!-- @click="handleExport"-->
  99. <!-- v-hasPermi="['system:loanuser:export']"-->
  100. <!-- >匯出</el-button>-->
  101. <!-- </el-col>-->
  102. <!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>-->
  103. <!-- </el-row>-->
  104. <el-table v-loading="loading" :data="loanuserList" @selection-change="handleSelectionChange">
  105. <el-table-column type="selection" width="50" align="center" />
  106. <el-table-column :label="t('myuser.userId')" align="center" prop="loanUserId" />
  107. <el-table-column :label="t('myuser.userName')" align="center" prop="username" :show-overflow-tooltip="true" />
  108. <el-table-column :label="t('myuser.nickname')" align="center" prop="nickname" :show-overflow-tooltip="true" />
  109. <el-table-column :label="t('myuser.avatar')" align="center" prop="avatar" width="100">
  110. <template #default="{ row }">
  111. <image-preview :src="getImageUrl(row.avatar)" :width="40" :height="40"/>
  112. </template>
  113. </el-table-column>
  114. <el-table-column :label="t('myuser.phone')" align="center" prop="phone" width="120" />
  115. <el-table-column :label="t('myuser.contactUploadStatus')" align="center" prop="upContact">
  116. <template #default="{ row }">
  117. <span>{{ upText(row.upContact) }}</span>
  118. </template>
  119. </el-table-column>
  120. <el-table-column :label="t('myuser.smsUploadStatus')" align="center" prop="upSms">
  121. <template #default="{ row }">
  122. <span>{{ upText(row.upSms) }}</span>
  123. </template>
  124. </el-table-column>
  125. <el-table-column :label="t('myuser.callUploadStatus')" align="center" prop="upCall">
  126. <template #default="{ row }">
  127. <span>{{ upText(row.upCall) }}</span>
  128. </template>
  129. </el-table-column>
  130. <el-table-column :label="t('myuser.positionUploadStatus')" align="center" prop="upPosition">
  131. <template #default="{ row }">
  132. <span>{{ upText(row.upPosition) }}</span>
  133. </template>
  134. </el-table-column>
  135. <el-table-column :label="t('myuser.imageUploadStatus')" align="center" prop="upImage">
  136. <template #default="{ row }">
  137. <span>{{ upText(row.upImage) }}</span>
  138. </template>
  139. </el-table-column>
  140. <el-table-column :label="t('myuser.agent')" align="center" prop="isAgent">
  141. <template #default="{ row }">
  142. <span>{{ row.isAgent ? t('myuser.yes') : t('myuser.no') }}</span>
  143. </template>
  144. </el-table-column>
  145. <el-table-column :label="t('myuser.agentId')" align="center" prop="agentId" />
  146. <el-table-column :label="t('myuser.status')" align="center" prop="status">
  147. <template #default="{ row }">
  148. <dict-tag :options="sys_normal_disable" :value="row.status"/>
  149. </template>
  150. </el-table-column>
  151. <el-table-column :label="t('myuser.createTime')" align="center" prop="createTime" width="160">
  152. <template #default="{ row }">
  153. <span>{{ proxy.parseTime(row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
  154. </template>
  155. </el-table-column>
  156. <!-- <el-table-column label="更新時間" align="center" prop="updateTime" width="180">-->
  157. <!-- <template #default="{ row }">-->
  158. <!-- <span>{{ parseTime(row.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>-->
  159. <!-- </template>-->
  160. <!-- </el-table-column>-->
  161. <el-table-column :label="t('myuser.operation')" align="center" width="140" class-name="small-padding fixed-width">
  162. <template #default="{ row }">
  163. <el-tooltip :content="t('myuser.view')" placement="top">
  164. <el-button link type="primary" icon="View" @click.stop="handleView(row)"></el-button>
  165. </el-tooltip>
  166. </template>
  167. </el-table-column>
  168. </el-table>
  169. <pagination
  170. v-show="total>0"
  171. :total="total"
  172. v-model:page="queryParams.pageNum"
  173. v-model:limit="queryParams.pageSize"
  174. @pagination="getList"
  175. />
  176. <!-- 新增或修改会员对话框 -->
  177. <el-dialog :title="title" v-model="open" width="600px" append-to-body>
  178. <el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
  179. <el-form-item :label="t('myuser.userInfo')" prop="username">
  180. <el-input v-model="form.username" :disabled="isUpdate || isView" :placeholder="t('myuser.pleaseEnterUserInfo')" />
  181. </el-form-item>
  182. <el-form-item :label="t('myuser.userNickname')" prop="nickname">
  183. <el-input v-model="form.nickname" :disabled="isView" :placeholder="t('myuser.pleaseEnterUserNickname')" />
  184. </el-form-item>
  185. <el-form-item :label="t('myuser.avatar')" prop="avatar">
  186. <image-preview :src="getImageUrl(form.avatar)" :limit="1" :width="80" :height="80" />
  187. </el-form-item>
  188. <el-form-item :label="t('myuser.phoneNumber')" prop="phone">
  189. <el-input v-model="form.phone" :disabled="isView" :placeholder="t('myuser.pleaseEnterPhoneNumber')" />
  190. </el-form-item>
  191. <el-form-item :label="t('myuser.agent')" prop="isAgent">
  192. <el-radio-group v-model="form.isAgent" :disabled="isView">
  193. <el-radio
  194. key="true"
  195. :label="true"
  196. >{{ t('myuser.yes') }}</el-radio>
  197. <el-radio
  198. key="false"
  199. :label="false"
  200. >{{ t('myuser.no') }}</el-radio>
  201. </el-radio-group>
  202. </el-form-item>
  203. <el-form-item :label="t('myuser.status')" prop="status">
  204. <el-radio-group v-model="form.status" :disabled="isView">
  205. <el-radio
  206. v-for="dict in statusOptions"
  207. :key="dict.value"
  208. :label="parseInt(dict.value)"
  209. >{{ dict.label }}</el-radio>
  210. </el-radio-group>
  211. </el-form-item>
  212. </el-form>
  213. <template #footer>
  214. <div class="dialog-footer">
  215. <!-- <el-button type="primary" :disabled="isView" @click="submitForm">确 定</el-button>-->
  216. <el-button @click="cancel">{{ t('common.cancel') }}</el-button>
  217. </div>
  218. </template>
  219. </el-dialog>
  220. </div>
  221. </template>
  222. <script setup name="Loanuser">
  223. import { ref, reactive, computed, getCurrentInstance, onMounted, nextTick } from 'vue'
  224. import { getMyAgentMember } from "@/api/system/myuser.js"
  225. import { ElMessageBox, ElMessage } from 'element-plus'
  226. import { isExternal } from '@/utils/validate'
  227. import { useI18n } from '@/composables/useI18n'
  228. const { t } = useI18n()
  229. const { proxy } = getCurrentInstance()
  230. const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sys_normal_disable")
  231. // 状态选项(国际化)
  232. const statusOptions = computed(() => {
  233. if (!sys_normal_disable.value || !Array.isArray(sys_normal_disable.value)) {
  234. return []
  235. }
  236. return sys_normal_disable.value.map(dict => {
  237. // 根据字典值返回对应的翻译
  238. if (dict.value === '0' || dict.value === 0) {
  239. return { ...dict, label: t('myuser.statusNormal') }
  240. } else if (dict.value === '1' || dict.value === 1) {
  241. return { ...dict, label: t('myuser.statusDisable') }
  242. }
  243. return dict
  244. })
  245. })
  246. // 獲取文件路徑前綴
  247. const filePath = import.meta.env.VITE_APP_FILE_PATH || ''
  248. // 獲取完整的圖片URL
  249. const getImageUrl = (url) => {
  250. if (!url) return ''
  251. // 如果是外部鏈接,直接返回
  252. if (isExternal(url)) {
  253. return url
  254. }
  255. // 如果已經包含文件路徑前綴,直接返回
  256. if (filePath && url.startsWith(filePath)) {
  257. return url
  258. }
  259. // 在前面加上文件路徑前綴
  260. return filePath ? filePath + url : url
  261. }
  262. // 響應式數據
  263. const loading = ref(true)
  264. const ids = ref([])
  265. const single = ref(true)
  266. const multiple = ref(true)
  267. const showSearch = ref(true)
  268. const total = ref(0)
  269. const loanuserList = ref([])
  270. const title = ref("")
  271. const open = ref(false)
  272. const openUserPassword = ref(false)
  273. const isUpdate = ref(false)
  274. const isView = ref(false)
  275. const adminPassword = ref('')
  276. // 查询参数(对齐 index.vue:pageNum/pageSize)
  277. const queryParams = reactive({
  278. pageNum: 1,
  279. pageSize: 10,
  280. username: null,
  281. nickname: null,
  282. phone: null,
  283. status: null,
  284. isAgent: null,
  285. agentId: null
  286. })
  287. // 表单参数
  288. const form = ref({})
  289. // 表单校验
  290. const rules = computed(() => ({
  291. username: [
  292. { required: true, message: t('myuser.usernameRequired'), trigger: "blur" }
  293. ],
  294. nickname: [
  295. { required: true, message: t('myuser.nicknameRequired'), trigger: "blur" }
  296. ],
  297. password: [
  298. { required: true, message: t('myuser.passwordRequired'), trigger: "blur" }
  299. ],
  300. phone: [
  301. { required: true, message: t('myuser.phoneRequired'), trigger: "blur" }
  302. ],
  303. status: [
  304. { required: true, message: t('myuser.statusRequired'), trigger: "change" }
  305. ],
  306. isAgent: [
  307. { required: true, message: t('myuser.agentRequired'), trigger: "change" }
  308. ],
  309. adminPassword: [{ required: true, message: t('myuser.adminPasswordRequired'), trigger: "blur" }],
  310. }))
  311. // 获取ref引用
  312. const queryFormRef = ref()
  313. const formRef = ref()
  314. const formpasswordRef = ref()
  315. onMounted(() => {
  316. getList()
  317. })
  318. /** 查询会员管理列表 */
  319. const getList = () => {
  320. loading.value = true
  321. const params = {
  322. pageNumber: queryParams.pageNum,
  323. pageSize: queryParams.pageSize,
  324. username: queryParams.username,
  325. nickname: queryParams.nickname,
  326. phone: queryParams.phone,
  327. status: queryParams.status,
  328. isAgent: queryParams.isAgent,
  329. agentId: queryParams.agentId,
  330. }
  331. getMyAgentMember(params).then(response => {
  332. loanuserList.value = response.data.records
  333. total.value = response.data.total
  334. loading.value = false
  335. console.log(loanuserList)
  336. })
  337. }
  338. const upText = (type) => {
  339. switch (type) {
  340. case true:
  341. return t('myuser.uploaded')
  342. case false:
  343. return t('myuser.rejected')
  344. default:
  345. return type
  346. }
  347. }
  348. /** 重设密码按钮操作 */
  349. const handleResetPwd = (row) => {
  350. proxy.$prompt(t('myuser.resetPasswordPrompt', { username: row.username }), t('login.tip'), {
  351. confirmButtonText: t('common.confirm'),
  352. cancelButtonText: t('common.cancel'),
  353. closeOnClickModal: false,
  354. inputPattern: /^.{5,20}$/,
  355. inputErrorMessage: t('myuser.passwordLengthError'),
  356. inputValidator: (value) => {
  357. if (/<|>|"|'|\||\\/.test(value)) {
  358. return t('myuser.invalidChars')
  359. }
  360. },
  361. }).then(({ value }) => {
  362. // resetUserPwd(row.loanUserId, value).then(response => {
  363. // proxy.$modal.msgSuccess("修改成功,新密碼是:" + value)
  364. // })
  365. }).catch(() => {})
  366. }
  367. // 取消按钮
  368. const cancel = () => {
  369. open.value = false
  370. reset()
  371. isView.value = false
  372. }
  373. // 表单重设
  374. const reset = () => {
  375. form.value = {
  376. loanUserId: null,
  377. username: null,
  378. nickname: null,
  379. password: null,
  380. avatar: null,
  381. phone: null,
  382. status: null,
  383. uniqueidentifier: null,
  384. delFlag: null,
  385. createTime: null,
  386. updateTime: null,
  387. isAgent: false,
  388. }
  389. if (formRef.value) {
  390. formRef.value.resetFields()
  391. }
  392. }
  393. /** 搜索按钮操作 */
  394. const handleQuery = () => {
  395. queryParams.pageNum = 1
  396. getList()
  397. }
  398. /** 重置按钮操作 */
  399. const resetQuery = () => {
  400. queryFormRef.value.resetFields()
  401. handleQuery()
  402. }
  403. // 多选框选中资料
  404. const handleSelectionChange = (selection) => {
  405. ids.value = selection.map(item => item.loanUserId)
  406. single.value = selection.length !== 1
  407. multiple.value = !selection.length
  408. }
  409. /** 新增按钮操作 */
  410. const handleAdd = () => {
  411. reset()
  412. open.value = true
  413. isUpdate.value = false
  414. isView.value = false
  415. title.value = t('myuser.addMember')
  416. nextTick(() => {
  417. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  418. })
  419. }
  420. /** 修改按钮操作 */
  421. const handleUpdate = (row) => {
  422. reset()
  423. const loanUserId = row.loanUserId || ids.value
  424. // 直接使用表格行数据打开对话框,后续如需从后端拉取明细,可替换为接口填充
  425. form.value = { ...row }
  426. open.value = true
  427. isUpdate.value = true
  428. isView.value = false
  429. title.value = t('myuser.editMember')
  430. nextTick(() => {
  431. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  432. })
  433. }
  434. /** 查看按钮操作 */
  435. const handleView = (row) => {
  436. reset()
  437. form.value = { ...row }
  438. isUpdate.value = false
  439. isView.value = true
  440. open.value = true
  441. title.value = t('myuser.viewMember')
  442. nextTick(() => {
  443. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  444. })
  445. }
  446. const handleUpdatePasswrod = (row) => {
  447. const loanUserId = row.loanUserId || ids.value
  448. // getLoanuser(loanUserId).then(response => {
  449. // form.value = response.data
  450. // openUserPassword.value = true
  451. // })
  452. }
  453. const submitChangePassword = (row) => {
  454. const loanUserIds = row.loanUserId || ids.value
  455. ElMessageBox.confirm(t('myuser.resetPasswordConfirm')).then(() => {
  456. // return delLoanuser(loanUserIds)
  457. }).then(() => {
  458. getList()
  459. ElMessage.success(t('myuser.resetPasswordSuccess'))
  460. }).catch(() => {})
  461. }
  462. /** 提交按钮 */
  463. const submitForm = () => {
  464. formRef.value.validate(valid => {
  465. if (valid) {
  466. if (form.value.loanUserId != null) {
  467. // updateLoanuser(form.value).then(response => {
  468. // proxy.$modal.msgSuccess("修改成功")
  469. // open.value = false
  470. // getList()
  471. // })
  472. } else {
  473. // addLoanuser(form.value).then(response => {
  474. // proxy.$modal.msgSuccess("新增成功")
  475. // open.value = false
  476. // getList()
  477. // })
  478. }
  479. }
  480. })
  481. }
  482. /** 删除按钮操作 */
  483. const handleDelete = (row) => {
  484. const loanUserIds = row.loanUserId || ids.value
  485. ElMessageBox.confirm(t('myuser.deleteConfirm', { id: loanUserIds })).then(() => {
  486. // return delLoanuser(loanUserIds)
  487. }).then(() => {
  488. getList()
  489. ElMessage.success(t('myuser.deleteSuccess'))
  490. }).catch(() => {})
  491. }
  492. /** 导出按钮操作 */
  493. const handleExport = () => {
  494. proxy.download('system/loanuser/export', {
  495. pageNumber: queryParams.pageNum,
  496. pageSize: queryParams.pageSize,
  497. username: queryParams.username,
  498. nickname: queryParams.nickname,
  499. phone: queryParams.phone,
  500. status: queryParams.status,
  501. isAgent: queryParams.isAgent,
  502. agentId: queryParams.agentId,
  503. }, `loanuser_${new Date().getTime()}.xlsx`)
  504. }
  505. </script>