Files
zyt/admin/src/views/asset/user/index.vue
T
long 07018598ad add
素材分发 增加用户备注
add_asset_user_remark.sql
2026-06-05 12:02:35 +08:00

279 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="asset-user-container">
<!-- 搜索区域 -->
<el-card class="!border-none" shadow="never">
<el-form class="ls-form" :model="searchData" inline>
<el-form-item class="w-[280px]" label="手机号">
<el-input
placeholder="请输入手机号"
v-model="searchData.phone"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 列表区域 -->
<el-card class="!border-none mt-4" shadow="never">
<div class="mb-4">
<el-button type="primary" @click="handleAdd">新增账号</el-button>
</div>
<el-table :data="tableData" v-loading="loading">
<!-- <el-table-column prop="id" label="ID" width="80" /> -->
<el-table-column prop="phone" label="手机号" />
<el-table-column label="备注" min-width="200">
<template #default="{ row }">
<div class="flex items-center gap-1 min-w-0">
<span class="truncate text-gray-600" :title="row.remark || ''">
{{ row.remark || '—' }}
</span>
<el-tooltip content="编辑备注" placement="top">
<el-icon class="shrink-0 cursor-pointer text-gray-400 hover:text-primary" @click="openQuickRemark(row)">
<Edit />
</el-icon>
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" width="180" />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-switch
v-model="row.status"
:active-value="1"
:inactive-value="0"
active-text="正常"
inactive-text="禁用"
inline-prompt
@change="handleStatusChange(row)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-4 flex justify-end">
<el-pagination
v-model:current-page="queryParams.page_no"
v-model:page-size="queryParams.page_size"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="getList"
@current-change="getList"
/>
</div>
</el-card>
<!-- 编辑/新增弹窗 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px" destroy-on-close>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="手机号" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入手机号(作为登录账号)" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="formData.password" placeholder="为空则默认为 123456" show-password />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="formData.remark"
type="textarea"
:rows="3"
maxlength="500"
show-word-limit
placeholder="可填写用户相关信息,仅管理员可见"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
</template>
</el-dialog>
<!-- 快捷备注 -->
<el-dialog v-model="remarkDialogVisible" title="快捷备注" width="420px" destroy-on-close>
<div class="text-sm text-gray-500 mb-3">账号{{ remarkTargetPhone }}</div>
<el-input
v-model="remarkDraft"
type="textarea"
:rows="4"
maxlength="500"
show-word-limit
placeholder="可填写用户相关信息,仅管理员可见"
/>
<template #footer>
<el-button @click="remarkDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="remarkSaving" @click="saveQuickRemark">保存</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Edit } from '@element-plus/icons-vue'
import { apiAssetUserList, apiAssetUserAdd, apiAssetUserEdit, apiAssetUserDelete } from '@/api/asset'
const loading = ref(false)
const tableData = ref([])
const total = ref(0)
const searchData = reactive({
phone: ''
})
const queryParams = reactive<any>({
page_no: 1,
page_size: 15
})
const dialogVisible = ref(false)
const dialogTitle = ref('')
const submitLoading = ref(false)
const formRef = ref()
const remarkDialogVisible = ref(false)
const remarkSaving = ref(false)
const remarkDraft = ref('')
const remarkTargetId = ref<number | string>('')
const remarkTargetPhone = ref('')
const formData = reactive({
id: '',
phone: '',
password: '',
remark: '',
status: 1
})
const rules = {
phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }]
}
const getList = async () => {
loading.value = true
try {
const params = { ...queryParams, ...searchData }
const res = await apiAssetUserList(params)
tableData.value = res.lists
total.value = res.count
} catch (e) {
console.error(e)
} finally {
loading.value = false
}
}
const handleSearch = () => {
queryParams.page_no = 1
getList()
}
const handleReset = () => {
searchData.phone = ''
queryParams.page_no = 1
getList()
}
const handleStatusChange = async (row: any) => {
try {
await apiAssetUserEdit({ id: row.id, status: row.status })
ElMessage.success(row.status === 1 ? '已启用' : '已禁用')
} catch (e) {
// 失败时回滚状态
row.status = row.status === 1 ? 0 : 1
console.error(e)
}
}
const handleAdd = () => {
dialogTitle.value = '新增账号'
Object.assign(formData, { id: '', phone: '', password: '', remark: '', status: 1 })
dialogVisible.value = true
}
const handleEdit = (row: any) => {
dialogTitle.value = '编辑账号'
Object.assign(formData, { id: row.id, phone: row.phone, password: '', remark: row.remark || '', status: row.status })
dialogVisible.value = true
}
const openQuickRemark = (row: any) => {
remarkTargetId.value = row.id
remarkTargetPhone.value = row.phone || ''
remarkDraft.value = row.remark || ''
remarkDialogVisible.value = true
}
const saveQuickRemark = async () => {
if (!remarkTargetId.value) return
remarkSaving.value = true
try {
await apiAssetUserEdit({ id: remarkTargetId.value, remark: remarkDraft.value })
const target = tableData.value.find((item: any) => item.id === remarkTargetId.value)
if (target) {
target.remark = remarkDraft.value
}
ElMessage.success('备注已保存')
remarkDialogVisible.value = false
} catch (e) {
console.error(e)
} finally {
remarkSaving.value = false
}
}
const handleDelete = async (row: any) => {
try {
await ElMessageBox.confirm('确定要删除该账号及其关联资源吗?', '提示', { type: 'warning' })
await apiAssetUserDelete({ id: row.id })
ElMessage.success('删除成功')
getList()
} catch (e) {
// canceled
}
}
const submitForm = async () => {
if (!formRef.value) return
await formRef.value.validate(async (valid: boolean) => {
if (valid) {
submitLoading.value = true
try {
if (formData.id) {
await apiAssetUserEdit(formData)
} else {
await apiAssetUserAdd(formData)
}
ElMessage.success('操作成功')
dialogVisible.value = false
getList()
} catch (e) {
console.error(e)
} finally {
submitLoading.value = false
}
}
})
}
onMounted(() => {
getList()
})
</script>