myuser.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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, locale } = 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. // 访问 locale.value 来建立响应式依赖,确保语言切换时重新计算
  234. const currentLocale = locale.value
  235. if (!sys_normal_disable.value || !Array.isArray(sys_normal_disable.value)) {
  236. return []
  237. }
  238. return sys_normal_disable.value.map(dict => {
  239. // 根据字典值返回对应的翻译
  240. if (dict.value === '0' || dict.value === 0) {
  241. return { ...dict, label: t('myuser.statusNormal') }
  242. } else if (dict.value === '1' || dict.value === 1) {
  243. return { ...dict, label: t('myuser.statusDisable') }
  244. }
  245. return dict
  246. })
  247. })
  248. // 獲取文件路徑前綴
  249. const filePath = import.meta.env.VITE_APP_FILE_PATH || ''
  250. // 獲取完整的圖片URL
  251. const getImageUrl = (url) => {
  252. if (!url) return ''
  253. // 如果是外部鏈接,直接返回
  254. if (isExternal(url)) {
  255. return url
  256. }
  257. // 如果已經包含文件路徑前綴,直接返回
  258. if (filePath && url.startsWith(filePath)) {
  259. return url
  260. }
  261. // 在前面加上文件路徑前綴
  262. return filePath ? filePath + url : url
  263. }
  264. // 響應式數據
  265. const loading = ref(true)
  266. const ids = ref([])
  267. const single = ref(true)
  268. const multiple = ref(true)
  269. const showSearch = ref(true)
  270. const total = ref(0)
  271. const loanuserList = ref([])
  272. const title = ref("")
  273. const open = ref(false)
  274. const openUserPassword = ref(false)
  275. const isUpdate = ref(false)
  276. const isView = ref(false)
  277. const adminPassword = ref('')
  278. // 查询参数(对齐 index.vue:pageNum/pageSize)
  279. const queryParams = reactive({
  280. pageNum: 1,
  281. pageSize: 10,
  282. username: null,
  283. nickname: null,
  284. phone: null,
  285. status: null,
  286. isAgent: null,
  287. agentId: null
  288. })
  289. // 表单参数
  290. const form = ref({})
  291. // 表单校验
  292. const rules = computed(() => {
  293. // 访问 locale.value 来建立响应式依赖,确保语言切换时重新计算
  294. const currentLocale = locale.value
  295. return {
  296. username: [
  297. { required: true, message: t('myuser.usernameRequired'), trigger: "blur" }
  298. ],
  299. nickname: [
  300. { required: true, message: t('myuser.nicknameRequired'), trigger: "blur" }
  301. ],
  302. password: [
  303. { required: true, message: t('myuser.passwordRequired'), trigger: "blur" }
  304. ],
  305. phone: [
  306. { required: true, message: t('myuser.phoneRequired'), trigger: "blur" }
  307. ],
  308. status: [
  309. { required: true, message: t('myuser.statusRequired'), trigger: "change" }
  310. ],
  311. isAgent: [
  312. { required: true, message: t('myuser.agentRequired'), trigger: "change" }
  313. ],
  314. adminPassword: [{ required: true, message: t('myuser.adminPasswordRequired'), trigger: "blur" }],
  315. }
  316. })
  317. // 获取ref引用
  318. const queryFormRef = ref()
  319. const formRef = ref()
  320. const formpasswordRef = ref()
  321. onMounted(() => {
  322. getList()
  323. })
  324. /** 查询会员管理列表 */
  325. const getList = () => {
  326. loading.value = true
  327. const params = {
  328. pageNumber: queryParams.pageNum,
  329. pageSize: queryParams.pageSize,
  330. username: queryParams.username,
  331. nickname: queryParams.nickname,
  332. phone: queryParams.phone,
  333. status: queryParams.status,
  334. isAgent: queryParams.isAgent,
  335. agentId: queryParams.agentId,
  336. }
  337. getMyAgentMember(params).then(response => {
  338. loanuserList.value = response.data.records
  339. total.value = response.data.total
  340. loading.value = false
  341. console.log(loanuserList)
  342. })
  343. }
  344. const upText = (type) => {
  345. // 访问 locale.value 来建立响应式依赖,确保语言切换时重新计算
  346. const currentLocale = locale.value
  347. switch (type) {
  348. case true:
  349. return t('myuser.uploaded')
  350. case false:
  351. return t('myuser.rejected')
  352. default:
  353. return type
  354. }
  355. }
  356. /** 重设密码按钮操作 */
  357. const handleResetPwd = (row) => {
  358. proxy.$prompt(t('myuser.resetPasswordPrompt', { username: row.username }), t('login.tip'), {
  359. confirmButtonText: t('common.confirm'),
  360. cancelButtonText: t('common.cancel'),
  361. closeOnClickModal: false,
  362. inputPattern: /^.{5,20}$/,
  363. inputErrorMessage: t('myuser.passwordLengthError'),
  364. inputValidator: (value) => {
  365. if (/<|>|"|'|\||\\/.test(value)) {
  366. return t('myuser.invalidChars')
  367. }
  368. },
  369. }).then(({ value }) => {
  370. // resetUserPwd(row.loanUserId, value).then(response => {
  371. // proxy.$modal.msgSuccess("修改成功,新密碼是:" + value)
  372. // })
  373. }).catch(() => {})
  374. }
  375. // 取消按钮
  376. const cancel = () => {
  377. open.value = false
  378. reset()
  379. isView.value = false
  380. }
  381. // 表单重设
  382. const reset = () => {
  383. form.value = {
  384. loanUserId: null,
  385. username: null,
  386. nickname: null,
  387. password: null,
  388. avatar: null,
  389. phone: null,
  390. status: null,
  391. uniqueidentifier: null,
  392. delFlag: null,
  393. createTime: null,
  394. updateTime: null,
  395. isAgent: false,
  396. }
  397. if (formRef.value) {
  398. formRef.value.resetFields()
  399. }
  400. }
  401. /** 搜索按钮操作 */
  402. const handleQuery = () => {
  403. queryParams.pageNum = 1
  404. getList()
  405. }
  406. /** 重置按钮操作 */
  407. const resetQuery = () => {
  408. queryFormRef.value.resetFields()
  409. handleQuery()
  410. }
  411. // 多选框选中资料
  412. const handleSelectionChange = (selection) => {
  413. ids.value = selection.map(item => item.loanUserId)
  414. single.value = selection.length !== 1
  415. multiple.value = !selection.length
  416. }
  417. /** 新增按钮操作 */
  418. const handleAdd = () => {
  419. reset()
  420. open.value = true
  421. isUpdate.value = false
  422. isView.value = false
  423. title.value = t('myuser.addMember')
  424. nextTick(() => {
  425. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  426. })
  427. }
  428. /** 修改按钮操作 */
  429. const handleUpdate = (row) => {
  430. reset()
  431. const loanUserId = row.loanUserId || ids.value
  432. // 直接使用表格行数据打开对话框,后续如需从后端拉取明细,可替换为接口填充
  433. form.value = { ...row }
  434. open.value = true
  435. isUpdate.value = true
  436. isView.value = false
  437. title.value = t('myuser.editMember')
  438. nextTick(() => {
  439. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  440. })
  441. }
  442. /** 查看按钮操作 */
  443. const handleView = (row) => {
  444. reset()
  445. form.value = { ...row }
  446. isUpdate.value = false
  447. isView.value = true
  448. open.value = true
  449. title.value = t('myuser.viewMember')
  450. nextTick(() => {
  451. if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
  452. })
  453. }
  454. const handleUpdatePasswrod = (row) => {
  455. const loanUserId = row.loanUserId || ids.value
  456. // getLoanuser(loanUserId).then(response => {
  457. // form.value = response.data
  458. // openUserPassword.value = true
  459. // })
  460. }
  461. const submitChangePassword = (row) => {
  462. const loanUserIds = row.loanUserId || ids.value
  463. ElMessageBox.confirm(t('myuser.resetPasswordConfirm')).then(() => {
  464. // return delLoanuser(loanUserIds)
  465. }).then(() => {
  466. getList()
  467. ElMessage.success(t('myuser.resetPasswordSuccess'))
  468. }).catch(() => {})
  469. }
  470. /** 提交按钮 */
  471. const submitForm = () => {
  472. formRef.value.validate(valid => {
  473. if (valid) {
  474. if (form.value.loanUserId != null) {
  475. // updateLoanuser(form.value).then(response => {
  476. // proxy.$modal.msgSuccess("修改成功")
  477. // open.value = false
  478. // getList()
  479. // })
  480. } else {
  481. // addLoanuser(form.value).then(response => {
  482. // proxy.$modal.msgSuccess("新增成功")
  483. // open.value = false
  484. // getList()
  485. // })
  486. }
  487. }
  488. })
  489. }
  490. /** 删除按钮操作 */
  491. const handleDelete = (row) => {
  492. const loanUserIds = row.loanUserId || ids.value
  493. ElMessageBox.confirm(t('myuser.deleteConfirm', { id: loanUserIds })).then(() => {
  494. // return delLoanuser(loanUserIds)
  495. }).then(() => {
  496. getList()
  497. ElMessage.success(t('myuser.deleteSuccess'))
  498. }).catch(() => {})
  499. }
  500. /** 导出按钮操作 */
  501. const handleExport = () => {
  502. proxy.download('system/loanuser/export', {
  503. pageNumber: queryParams.pageNum,
  504. pageSize: queryParams.pageSize,
  505. username: queryParams.username,
  506. nickname: queryParams.nickname,
  507. phone: queryParams.phone,
  508. status: queryParams.status,
  509. isAgent: queryParams.isAgent,
  510. agentId: queryParams.agentId,
  511. }, `loanuser_${new Date().getTime()}.xlsx`)
  512. }
  513. </script>