Compare commits

...

13 Commits

6 changed files with 214 additions and 124 deletions

View File

@ -38,6 +38,7 @@
"mitt": "^3.0.1", "mitt": "^3.0.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "3.0.2", "pinia": "3.0.2",
"qrcode-vue3": "^1.7.1",
"screenfull": "6.0.2", "screenfull": "6.0.2",
"vue": "3.5.13", "vue": "3.5.13",
"vue-cropper": "1.1.1", "vue-cropper": "1.1.1",

View File

@ -72,12 +72,11 @@ export const userAllCustomerAll = () => {
} }
// 解绑 // 解绑
export const deviceUnbind = (params:any) => {
export const deviceUnbind = (data:any) => {
return request({ return request({
url: '/api/device/unbind', url: '/api/device/unbind',
method: 'post', method: 'GET',
data params
}) })
} }
// 撤回 // 撤回

View File

@ -12,7 +12,7 @@
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button>
</div> </div>
<!-- 表格 --> <!-- 表格 -->
<el-table v-loading="bindingLoading" :data="boundDevices" style="width: 100%; margin-top: 20px;" height="400"> <el-table v-loading="bindingLoading" :data="boundDevices" style="margin-top: 20px;">
<el-table-column prop="deviceName" label="设备名称" /> <el-table-column prop="deviceName" label="设备名称" />
<el-table-column prop="devicePic" label="设备图片"> <el-table-column prop="devicePic" label="设备图片">
<template #default="scope"> <template #default="scope">
@ -21,14 +21,14 @@
<img :src="scope.row.devicePic" style="width: 40px; height: 40px; cursor: pointer;" <img :src="scope.row.devicePic" style="width: 40px; height: 40px; cursor: pointer;"
class="hover:opacity-80 transition-opacity" /> class="hover:opacity-80 transition-opacity" />
</template> </template>
<img :src="scope.row.devicePic" style="max-width: 600px; max-height: 600px;" /> <img :src="scope.row.devicePic" />
</el-popover> </el-popover>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="deviceMac" label="设备MAC" /> <el-table-column prop="deviceMac" label="设备MAC" />
<el-table-column prop="deviceImei" label="设备IMEI" /> <el-table-column prop="deviceImei" label="设备IMEI" />
<el-table-column prop="typeName" label="设备类型" /> <el-table-column prop="typeName" label="设备类型" />
<el-table-column prop="createTime" label="绑定日期" /> <el-table-column prop="bindingTime" label="绑定日期" />
<el-table-column label="操作" width="100" align="center"> <el-table-column label="操作" width="100" align="center">
<template #default="scope"> <template #default="scope">
<el-button type="danger" plain @click="handleUnbind(scope.row)">解绑</el-button> <el-button type="danger" plain @click="handleUnbind(scope.row)">解绑</el-button>

View File

@ -9,10 +9,10 @@
<el-input v-model="queryParams.blurry" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" /> <el-input v-model="queryParams.blurry" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="客户状态" prop="status"> <el-form-item label="客户状态" prop="status">
<el-select v-model="queryParams.enabled" clearable placeholder="客户状态" class="filter-item"> <el-select v-model="queryParams.status" clearable placeholder="客户状态" class="filter-item">
<el-option label="全部" :value="''" /> <el-option label="全部" :value="''" />
<el-option label="启用" :value="true" /> <el-option label="启用" :value="0" />
<el-option label="禁用" :value="false" /> <el-option label="禁用" :value="1" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间" style="width: 308px"> <el-form-item label="创建时间" style="width: 308px">
@ -53,10 +53,10 @@
<el-table-column type="selection" width="50" align="center" /> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="客户名称" align="center" prop="nickName" /> <el-table-column label="客户名称" align="center" prop="nickName" />
<el-table-column label="客户账号" align="center" prop="userName" :show-overflow-tooltip="true" /> <el-table-column label="客户账号" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="客户状态" align="center" prop="enabled"> <el-table-column label="客户状态" align="center" prop="status">
<template #default="scope"> <template #default="scope">
<div @click="handleStatusChange(scope.row)"> <div @click="handleStatusChange(scope.row)">
<el-switch v-model="scope.row.enabled" /> <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" />
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -104,7 +104,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item v-if="form.customerId === ''" label="账号密码" prop="password"> <el-form-item v-if="form.customerId === ''" label="账号密码" prop="password">
<el-input v-model="form.password" placeholder="请输入账号密码" /> <el-input v-model="form.password" placeholder="请输入账号密码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -121,22 +121,48 @@
<script setup name="User" lang="ts"> <script setup name="User" lang="ts">
import api from '@/api/customerManagement'; import api from '@/api/customerManagement';
import { UserForm, UserQuery, UserVO } from '@/api/customerManagement/types';
import { to } from 'await-to-js'; import { to } from 'await-to-js';
import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElRow, ElCol, ElButton, ElCard, ElSelect, ElOption, ElDatePicker, ElTable, ElTableColumn, ElTooltip, ElSwitch } from 'element-plus';
// 定义接口
interface UserVO {
customerId: string | number;
nickName: string;
userName: string;
status: string;
createTime: string;
userId: number;
}
interface UserForm extends UserVO {
password?: string;
enabled?: boolean;
}
interface UserQuery {
pageNum: number;
pageSize: number;
blurry: string;
status: string;
enabled: string;
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const customerList = ref<UserVO[]>(); const customerList = ref<UserVO[]>();
const loading = ref(true); const loading = ref(true);
const showSearch = ref(true); const showSearch = ref(true);
const ids = ref<Array<number | string>>([]); const ids = ref<UserVO[]>([]);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const dateRange = ref<[DateModelType, DateModelType]>(['', '']); const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
const initPassword = ref<string>(''); const initPassword = ref<string>('');
const queryFormRef = ref<ElFormInstance>(); const queryFormRef = ref<InstanceType<typeof ElForm>>();
const userFormRef = ref<ElFormInstance>(); const userFormRef = ref<InstanceType<typeof ElForm>>();
const formDialogRef = ref<ElDialogInstance>(); const formDialogRef = ref<InstanceType<typeof ElDialog>>();
const loadingIng = ref(false) const loadingIng = ref(false)
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
title: '' title: ''
@ -144,19 +170,27 @@ const dialog = reactive<DialogOption>({
const initFormData: UserForm = { const initFormData: UserForm = {
userName: '', userName: '',
nickName: undefined, nickName: '',
password: '', password: '',
enabled: true, enabled: true,
customerId: '' customerId: '',
status: '',
createTime: '',
userId: 0,
}; };
const initData: PageData<UserForm, UserQuery> = { const initData: {
form: UserForm,
queryParams: UserQuery,
rules: any
} = {
form: { ...initFormData }, form: { ...initFormData },
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
blurry: '', blurry: '',
enabled: '', enabled: '',
status: ''
}, },
rules: { rules: {
nickName: [ nickName: [
@ -171,14 +205,22 @@ const initData: PageData<UserForm, UserQuery> = {
trigger: 'blur' trigger: 'blur'
} }
], ],
password: [ password: [
{ required: true, message: '请输入账号密码', trigger: 'blur' }, { required: true, message: '请输入账号密码', trigger: 'blur' },
{
min: 5,
max: 20,
message: '用户密码长度必须介于 5 和 20 之间',
trigger: 'blur'
},
{ pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur' }
], ],
} }
}; };
const data = reactive<PageData<UserForm, UserQuery>>(initData); const data = reactive(initData);
const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data); const { queryParams, form, rules } = toRefs(data);
/** 查询用户列表 */ /** 查询用户列表 */
const getList = async () => { const getList = async () => {
@ -198,28 +240,24 @@ const handleQuery = () => {
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
dateRange.value = ['', '']; dateRange.value = ['', ''];
queryFormRef.value?.resetFields();
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1;
queryParams.value.status=''
handleQuery(); handleQuery();
}; };
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (row?: UserVO) => { const handleDelete = async (row?: UserVO) => {
// 批量删除逻辑 const customerIds = row ? [row.customerId] : ids.value.map(item => item.customerId);
let arrey = ids.value.map((item) => item.customerId); const nickNames = row ? row.nickName : ids.value.map(item => item.nickName).join(',');
if (!row) { const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + nickNames + '"的数据项?', '系统提示', {
const [err] = await to(proxy?.$modal.confirm(`是否确认删除选中的 ${ids.value.length} 条数据?`) as any); confirmButtonText: '确定',
if (!err) { cancelButtonText: '取消',
await api.deleteCustomer(arrey); type: 'warning'
await getList(); }) as any);
proxy?.$modal.msgSuccess('删除成功');
}
return;
}
// 单行删除逻辑
const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + row.nickName + '"的数据项?') as any);
if (!err) { if (!err) {
await api.deleteCustomer([row.customerId]); await api.deleteCustomer(customerIds);
await getList(); await getList();
proxy?.$modal.msgSuccess('删除成功'); proxy?.$modal.msgSuccess('删除成功');
} }
@ -227,25 +265,33 @@ const handleDelete = async (row?: UserVO) => {
/** 用户状态修改 */ /** 用户状态修改 */
const handleStatusChange = async (row: any) => { const handleStatusChange = async (row: any) => {
console.log(row, '33333333'); const originalStatus = row.status;
const newStatus = row.enabled; // 获取新的状态值(取反) const actionText = row.status == 0 ? '启用' : '停用';
const text = newStatus ? '启用' : '停用';
try { try {
await proxy?.$modal.confirm(`确认要${text}"${row.nickName}"客户吗?`); await proxy?.$modal.confirm(`确认要${actionText}"${row.nickName}"客户吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
await api.updateCustomer({ await api.updateCustomer({
customerId: row.customerId, customerId: row.customerId,
enabled: newStatus enabled: originalStatus == 0 ? true : false
}); });
proxy?.$modal.msgSuccess(text + '成功'); proxy?.$modal.msgSuccess(actionText + '成功');
await getList(); await getList();
} catch (err) { } catch (err) {
row.enabled = !newStatus; // 回滚状态 if (err == 'cancel') {
console.log(err, 'errr');
proxy?.$modal.msgWarning('操作已取消');
await getList();
}
} }
}; };
/** 选择条数 */ /** 选择条数 */
const handleSelectionChange = (selection: UserVO[]) => { const handleSelectionChange = (selection: UserVO[]) => {
ids.value = selection.map((item) => item); ids.value = selection;
single.value = selection.length != 1; single.value = selection.length != 1;
multiple.value = !selection.length; multiple.value = !selection.length;
}; };
@ -277,11 +323,10 @@ const handleUpdate = async (row?: UserForm) => {
dialog.title = '修改客户'; dialog.title = '修改客户';
try { try {
if (row) { if (row) {
// 从行内按钮调用,直接使用行数据
Object.assign(form.value, row); Object.assign(form.value, row);
} else { } else {
const customerId = ids.value[0]; const selectedId = ids.value[0];
Object.assign(form.value, customerId); Object.assign(form.value, selectedId);
} }
} catch (error) { } catch (error) {
dialog.visible = false; dialog.visible = false;
@ -290,15 +335,17 @@ const handleUpdate = async (row?: UserForm) => {
/** 提交按钮 */ /** 提交按钮 */
const submitForm = () => { const submitForm = () => {
userFormRef.value?.validate(async (valid: boolean) => { userFormRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {
loadingIng.value = true loadingIng.value = true;
form.value.customerId ? await api.updateCustomer(form.value) : await api.addCustomer(form.value); try {
proxy?.$modal.msgSuccess('操作成功'); form.value.customerId ? await api.updateCustomer(form.value) : await api.addCustomer(form.value);
dialog.visible = false; proxy?.$modal.msgSuccess('操作成功');
await getList(); dialog.visible = false;
loadingIng.value = false await getList();
} finally {
loadingIng.value = false;
}
} }
}); });
}; };
@ -317,11 +364,10 @@ const closeDialog = () => {
const resetForm = () => { const resetForm = () => {
userFormRef.value?.resetFields(); userFormRef.value?.resetFields();
userFormRef.value?.clearValidate(); userFormRef.value?.clearValidate();
form.value.customerId = undefined; form.value.customerId = '';
}; };
onMounted(() => { onMounted(() => {
getList(); // 初始化列表数据 getList(); // 初始化列表数据
}); });
</script> </script>

View File

@ -136,42 +136,58 @@
<script setup name="User" lang="ts"> <script setup name="User" lang="ts">
import api from '@/api/equipmentManagement/deviceType/index'; import api from '@/api/equipmentManagement/deviceType/index';
import { UserForm, deviceTypeQuery, deviceTypeVO } from '@/api/equipmentManagement/deviceType/types'; import { deviceTypeQuery } from '@/api/equipmentManagement/deviceType/types';
import { UserQuery, UserVO } from '@/api/system/user/types'; import { to } from 'await-to-js';
import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElRow, ElCol, ElButton, ElCard, ElSelect, ElOption, ElDatePicker, ElTable, ElTableColumn, ElTooltip, ElSwitch } from 'element-plus';
interface deviceTypeVO {
id: string | number;
typeName: string;
isSupportBle: boolean;
locateMode: string;
communicationMode: string;
createTime: string;
createByName: string;
}
interface DeviceTypeForm extends deviceTypeVO {
// 可能有其他字段
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const deviceTypeList = ref<deviceTypeVO[]>(); const deviceTypeList = ref<deviceTypeVO[]>();
import { to } from 'await-to-js';
const loading = ref(true); const loading = ref(true);
const showSearch = ref(true); const showSearch = ref(true);
const ids = ref<Array<number | string>>([]); const ids = ref<deviceTypeVO[]>([]);
const single = ref(true); const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const initPassword = ref<string>(''); const queryFormRef = ref<InstanceType<typeof ElForm>>();
const queryFormRef = ref<ElFormInstance>(); const userFormRef = ref<InstanceType<typeof ElForm>>();
const userFormRef = ref<ElFormInstance>(); const formDialogRef = ref<InstanceType<typeof ElDialog>>();
const formDialogRef = ref<ElDialogInstance>();
const loadingIng = ref(false) const loadingIng = ref(false)
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
title: '' title: ''
}); });
const initFormData: UserForm = { const initFormData: DeviceTypeForm = {
typeName: '', typeName: '',
isSupportBle: '', isSupportBle: false,
locateMode: '', locateMode: '',
communicationMode: '', communicationMode: '',
id: '' id: '',
createTime: '',
createByName: '',
}; };
const initData: PageData<UserForm, deviceTypeQuery> = { const initData = {
form: { ...initFormData }, form: { ...initFormData },
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
typeName: '', typeName: '',
}, },
rules: { rules: {
typeName: [ typeName: [
@ -185,8 +201,15 @@ const initData: PageData<UserForm, deviceTypeQuery> = {
], ],
} }
}; };
const data = reactive<PageData<UserForm, UserQuery>>(initData);
const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data); const data = reactive<{
form: DeviceTypeForm,
queryParams: deviceTypeQuery,
rules: any
}>(initData);
const { queryParams, form, rules } = toRefs(data);
/** 查询用户列表 */ /** 查询用户列表 */
const getList = async () => { const getList = async () => {
loading.value = true; loading.value = true;
@ -196,7 +219,6 @@ const getList = async () => {
total.value = res.total; total.value = res.total;
}; };
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1;
@ -204,42 +226,34 @@ const handleQuery = () => {
}; };
/** 重置按钮操作 */ /** 重置按钮操作 */
const resetQuery = () => { const resetQuery = () => {
queryParams.value.typeName = '' queryFormRef.value?.resetFields();
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1;
getList(); getList();
}; };
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (row?: UserVO) => { const handleDelete = async (row?: deviceTypeVO) => {
// 批量删除逻辑 const deviceTypeIds = row ? [row.id] : ids.value.map(item => item.id);
let arrey = ids.value.map((item) => item.id); const typeNames = row ? row.typeName : ids.value.map(item => item.typeName).join(',');
if (!row) { const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + typeNames + '"的数据项?', '系统提示', {
const [err] = await to(proxy?.$modal.confirm(`是否确认删除选中的 ${ids.value.length} 条数据?`) as any); confirmButtonText: '确定',
if (!err) { cancelButtonText: '取消',
await api.deleteDeviceType(arrey); type: 'warning'
await getList(); }) as any);
proxy?.$modal.msgSuccess('删除成功');
}
return;
}
// 单行删除逻辑
const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + row.typeName + '"的数据项?') as any);
if (!err) { if (!err) {
await api.deleteDeviceType([row.id]); await api.deleteDeviceType(deviceTypeIds);
await getList(); await getList();
proxy?.$modal.msgSuccess('删除成功'); proxy?.$modal.msgSuccess('删除成功');
} }
}; };
/** 选择条数 */ /** 选择条数 */
const handleSelectionChange = (selection: UserVO[]) => { const handleSelectionChange = (selection: deviceTypeVO[]) => {
ids.value = selection.map((item) => item); ids.value = selection;
single.value = selection.length != 1; single.value = selection.length != 1;
multiple.value = !selection.length; multiple.value = !selection.length;
}; };
/** 重置操作表单 */ /** 重置操作表单 */
const reset = () => { const reset = () => {
form.value = { ...initFormData }; form.value = { ...initFormData };
@ -256,21 +270,19 @@ const handleAdd = async () => {
reset(); reset();
dialog.visible = true; dialog.visible = true;
dialog.title = '新增设备类型'; dialog.title = '新增设备类型';
form.value.password = initPassword.value.toString();
}; };
/** 修改按钮操作 */ /** 修改按钮操作 */
const handleUpdate = async (row?: UserForm) => { const handleUpdate = async (row?: DeviceTypeForm) => {
reset(); reset();
dialog.visible = true; dialog.visible = true;
dialog.title = '修改设备类型'; dialog.title = '修改设备类型';
try { try {
if (row) { if (row) {
// 从行内按钮调用,直接使用行数据
Object.assign(form.value, row); Object.assign(form.value, row);
} else { } else {
const customerId = ids.value[0]; const selectedId = ids.value[0];
Object.assign(form.value, customerId); Object.assign(form.value, selectedId);
} }
} catch (error) { } catch (error) {
dialog.visible = false; dialog.visible = false;
@ -282,11 +294,14 @@ const submitForm = () => {
userFormRef.value?.validate(async (valid: boolean) => { userFormRef.value?.validate(async (valid: boolean) => {
if (valid) { if (valid) {
loadingIng.value = true; loadingIng.value = true;
form.value.id ? await api.updateDeviceType(form.value) : await api.addDeviceType(form.value); try {
proxy?.$modal.msgSuccess('操作成功'); form.value.id ? await api.updateDeviceType(form.value) : await api.addDeviceType(form.value);
dialog.visible = false; proxy?.$modal.msgSuccess('操作成功');
await getList(); dialog.visible = false;
loadingIng.value = false; await getList();
} finally {
loadingIng.value = false;
}
} }
}); });
}; };
@ -297,7 +312,6 @@ const submitForm = () => {
const closeDialog = () => { const closeDialog = () => {
dialog.visible = false; dialog.visible = false;
resetForm(); resetForm();
loadingIng.value = false;
}; };
/** /**
@ -306,11 +320,11 @@ const closeDialog = () => {
const resetForm = () => { const resetForm = () => {
userFormRef.value?.resetFields(); userFormRef.value?.resetFields();
userFormRef.value?.clearValidate(); userFormRef.value?.clearValidate();
form.value.customerId = undefined; form.value.id = '';
}; };
onMounted(() => { onMounted(() => {
getList(); // 初始化列表数据 getList(); // 初始化列表数据
}); });
</script> </script>

View File

@ -116,7 +116,7 @@
<el-tooltip v-if="scope.row.id !== 1 && scope.row.deviceStatus == 1" content="修改" placement="top"> <el-tooltip v-if="scope.row.id !== 1 && scope.row.deviceStatus == 1" content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip v-if="scope.row.id !== 1" content="删除" placement="top"> <el-tooltip v-if="!scope.row.customerName && scope.row.deviceStatus == 1" content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip v-if="scope.row.deviceStatus == 1 && !scope.row.customerName" content="分配" placement="top"> <el-tooltip v-if="scope.row.deviceStatus == 1 && !scope.row.customerName" content="分配" placement="top">
@ -129,6 +129,9 @@
placement="top"> placement="top">
<el-button link type="primary" icon="Refresh" @click="handleUnbind(scope.row)"></el-button> <el-button link type="primary" icon="Refresh" @click="handleUnbind(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip v-if="scope.row.deviceImei" content="查看二维码" placement="top">
<el-button link type="primary" icon="Postcard" @click="showQrCode(scope.row)"></el-button>
</el-tooltip>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -271,10 +274,23 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- IMEI 二维码弹窗 -->
<el-dialog v-model="qrCodeDialogVisible" title="设备IMEI二维码" width="20%" append-to-body>
<div style="text-align: center;">
<QRCodeVue3 :value="qrCodeValue" :size="100" />
<p style="margin-top: 10px;">{{ qrCodeValue }}</p>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="qrCodeDialogVisible = false">关闭</el-button>
</div>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup name="User" lang="ts"> <script setup name="User" lang="ts">
import QRCodeVue3 from 'qrcode-vue3';
import api from '@/api/equipmentManagement/device/index'; import api from '@/api/equipmentManagement/device/index';
import { deviceForm, deviceQuery, deviceVO, deviceTypeOption } from '@/api/equipmentManagement/device/types'; import { deviceForm, deviceQuery, deviceVO, deviceTypeOption } from '@/api/equipmentManagement/device/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -305,6 +321,8 @@ const loadingIng = ref(false)
const assignCustomerId = ref(); //分配客户id const assignCustomerId = ref(); //分配客户id
const batchAssignCustomerId = ref() //批量分配客户id const batchAssignCustomerId = ref() //批量分配客户id
const customerList = ref() const customerList = ref()
const qrCodeDialogVisible = ref(false);
const qrCodeValue = ref('');
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
title: '' title: ''
@ -371,7 +389,7 @@ const handleDelete = async (row?: deviceVO) => {
// 批量删除逻辑 // 批量删除逻辑
let arrey = ids.value.map((item) => item.id); let arrey = ids.value.map((item) => item.id);
if (!row) { if (!row) {
const [err] = await to(proxy?.$modal.confirm(`是否确认删除选中的 ${ids.value.length} 条数据?`)); const [err] = await to(proxy?.$modal.confirm(`是否确认删除选中的 ${ids.value.length} 条数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }));
if (!err) { if (!err) {
await api.deleteDevice(arrey); await api.deleteDevice(arrey);
await getList(); await getList();
@ -380,7 +398,7 @@ const handleDelete = async (row?: deviceVO) => {
return; return;
} }
// 单行删除逻辑 // 单行删除逻辑
const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + row.deviceName + '"的数据项?')); const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + row.deviceName + '"的数据项?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }));
if (!err) { if (!err) {
await api.deleteDevice([row.id]); await api.deleteDevice([row.id]);
await getList(); await getList();
@ -405,12 +423,15 @@ const handleUnbind = (row) => {
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
api.deviceUnbind(row).then(res => { let data = {
if (res.code === 0) { id: row.id
proxy?.$modal.msgSuccess('解绑成功') }
api.deviceUnbind(data).then(res => {
if (res.code == 200) {
proxy?.$modal.msgSuccess(res.msg)
getList(); // 初始化列表数据 getList(); // 初始化列表数据
} else { } else {
proxy?.$modal.msgError(res.msg || '解绑失败') proxy?.$modal.msgError(res.msg)
} }
}) })
}).catch(() => { }).catch(() => {
@ -425,7 +446,7 @@ const handleWithdraw = (row: any) => {
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
api.withdrawDevice([row.id]).then(res => { api.withdrawDevice([row.id]).then(res => {
if (res.code === 0) { if (res.code === 200) {
proxy?.$modal.msgSuccess('撤回成功') proxy?.$modal.msgSuccess('撤回成功')
getList(); // 初始化列表数据 getList(); // 初始化列表数据
} else { } else {
@ -480,6 +501,8 @@ const handleUpdate = async (row?: deviceForm) => {
getDeviceType(); getDeviceType();
try { try {
if (row) { if (row) {
// 使用 nextTick 确保对话框完全渲染后再设置表单值
await nextTick();
Object.assign(form.value, row); Object.assign(form.value, row);
form.value.image = row.devicePic form.value.image = row.devicePic
// 编辑时根据已有值显示字段 // 编辑时根据已有值显示字段
@ -531,7 +554,7 @@ const handleDeviceTypeChange = async (deviceTypeId: string | number) => {
return; return;
} }
const res = await api.getCommunicationMode({ id: deviceTypeId }); const res = await api.getCommunicationMode({ id: deviceTypeId });
if (res.code === 0 && res.data) { if (res.code == 200 && res.data) {
communicationModeInfo.value = res.data; communicationModeInfo.value = res.data;
// 根据通讯方式确定显示哪个字段 // 根据通讯方式确定显示哪个字段
if (res.data.communicationMode == '1') { // 蓝牙设备 - 显示MAC if (res.data.communicationMode == '1') { // 蓝牙设备 - 显示MAC
@ -622,7 +645,7 @@ const submitForm = async () => {
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
} }
}); });
if (res.code == 0) { if (res.code == 200) {
proxy?.$modal.msgSuccess('操作成功'); proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false; dialog.visible = false;
loadingIng.value = false; loadingIng.value = false;
@ -652,6 +675,13 @@ const closeDialog = () => {
resetForm(); resetForm();
}; };
const showQrCode = (row: any) => {
if (row.deviceImei) {
qrCodeValue.value = row.deviceImei;
qrCodeDialogVisible.value = true;
}
};
/** /**
* 重置表单 * 重置表单
*/ */
@ -663,7 +693,7 @@ const resetForm = () => {
// 设备类型 // 设备类型
const getDeviceType = () => { const getDeviceType = () => {
api.deviceTypeAll().then(res => { api.deviceTypeAll().then(res => {
if (res.code == 0) { if (res.code == 200) {
deviceTypeOptions.value = res.data deviceTypeOptions.value = res.data
} }
}).catch(err => { }).catch(err => {
@ -673,7 +703,7 @@ const getDeviceType = () => {
// 客户下拉框 // 客户下拉框
const getAllCustomerAll = () => { const getAllCustomerAll = () => {
api.userAllCustomerAll().then(res => { api.userAllCustomerAll().then(res => {
if (res.code == 0) { if (res.code == 200) {
customerList.value = res.data customerList.value = res.data
} }
}) })
@ -699,7 +729,7 @@ const handleAssignConfirm = () => {
deviceIds: [assignRow.value.id] deviceIds: [assignRow.value.id]
} }
api.deviceAssignCustomer(data).then((res) => { api.deviceAssignCustomer(data).then((res) => {
if (res.code == 0) { if (res.code == 200) {
loadingIng.value = false; loadingIng.value = false;
const customer = customerList.value.find(c => c.id === assignCustomerId.value) const customer = customerList.value.find(c => c.id === assignCustomerId.value)
const customerName = customer ? customer.nickName : `ID: ${assignCustomerId.value}` const customerName = customer ? customer.nickName : `ID: ${assignCustomerId.value}`
@ -733,7 +763,7 @@ const handleBatchImport = () => {
const downloadTemplate = () => { const downloadTemplate = () => {
// 这里可用 window.open 或 a 标签下载模板 // 这里可用 window.open 或 a 标签下载模板
const link = document.createElement('a'); const link = document.createElement('a');
link.href = 'http://fuyuanshen.com:81/images/excel/equipmenttemplate.xlsx'; link.href = 'https://fuyuanshen.com/fys/Equipmentimporttemplate/EquipmentImportTemplate.xlsx';
link.download = '设备数据导入模板.xlsx'; // 可选:指定下载文件名 link.download = '设备数据导入模板.xlsx'; // 可选:指定下载文件名
link.style.display = 'none'; // 隐藏标签 link.style.display = 'none'; // 隐藏标签
document.body.appendChild(link); document.body.appendChild(link);
@ -751,7 +781,7 @@ const beforeImportUpload = (file: any) => {
//添加tokenf方法head_upload 直接返回 getBearerToken() //添加tokenf方法head_upload 直接返回 getBearerToken()
const head_upload = () => getBearerToken(); const head_upload = () => getBearerToken();
const handleImportSuccess = (response: any) => { const handleImportSuccess = (response: any) => {
if (response.code === 0) { if (response.code == 200) {
importResult.value.isShow = true importResult.value.isShow = true
if (response.data) { if (response.data) {
importResult.value.succeed = response.data.successCount || 0 importResult.value.succeed = response.data.successCount || 0
@ -785,7 +815,7 @@ const handleBatchAssignConfirm = () => {
deviceIds: selectedIds // 选中的设备ID数组 deviceIds: selectedIds // 选中的设备ID数组
} }
api.deviceAssignCustomer(data).then((res) => { api.deviceAssignCustomer(data).then((res) => {
if (res.code == 0) { if (res.code == 200) {
batchAssignDialogVisible.value = false batchAssignDialogVisible.value = false
getList(); getList();
return proxy?.$modal.msgSuccess(`分配成功`) return proxy?.$modal.msgSuccess(`分配成功`)