Commit bdeac9846c3e3a8d010cf2b1aeb253fba2482ee0

Authored by sqy
1 parent 6000cf9a

'feat:设备分配客户,oem按钮调整,地图铆钉不显示,账号问题'

... ... @@ -136,3 +136,35 @@ export const saveDeviceToken = (data) => {
136 136 }
137 137 );
138 138 };
  139 +
  140 +// 获取当前租户下的客户列表
  141 +export const getCustomerList = (params) => {
  142 + return defHttp.get({
  143 + url: '/user/customers/' + params.organizationId,
  144 + });
  145 +};
  146 +
  147 +// 分配客户或
  148 +export const dispatchCustomer = (data) => {
  149 + const { customerId, tbDeviceId } = data;
  150 + return defHttp.post(
  151 + {
  152 + url: `/customer/${customerId}/device/${tbDeviceId}`,
  153 + },
  154 + {
  155 + joinPrefix: false,
  156 + }
  157 + );
  158 +};
  159 +// 取消分配客户
  160 +export const cancelDispatchCustomer = (data) => {
  161 + const { customerId, tbDeviceId } = data;
  162 + return defHttp.delete(
  163 + {
  164 + url: `/customer/${customerId}/device/${tbDeviceId}`,
  165 + },
  166 + {
  167 + joinPrefix: false,
  168 + }
  169 + );
  170 +};
... ...
... ... @@ -12,3 +12,10 @@ export function isAdmin(role: string) {
12 12 return false;
13 13 }
14 14 }
  15 +// 按钮级权限控制,只针对客户
  16 +export function authBtn(role: string): boolean {
  17 + if (role === RoleEnum.CUSTOMER_USER) {
  18 + return false;
  19 + }
  20 + return true;
  21 +}
... ...
... ... @@ -329,6 +329,7 @@
329 329 data: dataArray.filter((item1) => item1[2] === item),
330 330 };
331 331 });
  332 + console.log(dataArray);
332 333 // 设置数据;
333 334 setOptions({
334 335 tooltip: {
... ...
1 1 import { formatToDateTime } from '/@/utils/dateUtil';
2 2 import { FormSchema } from '/@/components/Form';
3 3 import { BasicColumn } from '/@/components/Table';
4   -
5 4 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
6   -
  5 +import { getCustomerList } from '/@/api/device/deviceManager';
7 6 export const columns: BasicColumn[] = [
8 7 {
9 8 title: '设备名称',
... ... @@ -287,3 +286,19 @@ export const statusType = (type: string): string => {
287 286 return '激活未确认';
288 287 }
289 288 };
  289 +
  290 +export const customerForm: FormSchema[] = [
  291 + {
  292 + field: 'customerId',
  293 + label: '分配客户',
  294 + component: 'ApiSelect',
  295 + componentProps: {
  296 + api: getCustomerList,
  297 + immediate: false,
  298 + labelField: 'realName',
  299 + valueField: 'customerId',
  300 + },
  301 + required: true,
  302 + colProps: { span: 12 },
  303 + },
  304 +];
... ...
... ... @@ -24,7 +24,6 @@ export const columns: BasicColumn[] = [
24 24 slots: { customRender: 'deviceProfile' },
25 25 ellipsis: true,
26 26 },
27   -
28 27 {
29 28 title: '所属组织',
30 29 dataIndex: 'organizationDTO.name',
... ...
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="registerModal"
  5 + title="将设备分配给客户"
  6 + :canFullscreen="false"
  7 + centered
  8 + @ok="dispatchCustomer"
  9 + :minHeight="150"
  10 + okText="分配"
  11 + >
  12 + <BasicForm @register="registerForm" />
  13 + </BasicModal>
  14 +</template>
  15 +
  16 +<script lang="ts">
  17 + import { defineComponent } from 'vue';
  18 + import { BasicModal, useModalInner } from '/@/components/Modal';
  19 + import { BasicForm, useForm } from '/@/components/Form';
  20 + import { customerForm } from '../../config/detail.config';
  21 + import { dispatchCustomer as dispatchCustomerApi } from '/@/api/device/deviceManager';
  22 + export default defineComponent({
  23 + name: 'AlarmDetailModal',
  24 + components: {
  25 + BasicModal,
  26 + BasicForm,
  27 + },
  28 + emits: ['reload', 'register'],
  29 + setup(_, { emit }) {
  30 + let record = {};
  31 + const [registerModal, { closeModal }] = useModalInner((data: any) => {
  32 + const { organizationId } = data;
  33 + record = data;
  34 + updateSchema([
  35 + {
  36 + field: 'customerId',
  37 + componentProps: {
  38 + params: { organizationId },
  39 + },
  40 + },
  41 + ]);
  42 + });
  43 + const [registerForm, { validate, getFieldsValue, updateSchema, resetFields }] = useForm({
  44 + labelWidth: 100,
  45 + showActionButtonGroup: false,
  46 + schemas: customerForm,
  47 + });
  48 + // 分配客户
  49 + const dispatchCustomer = async () => {
  50 + await validate();
  51 + const { customerId } = getFieldsValue();
  52 + await dispatchCustomerApi({ ...record, customerId });
  53 + closeModal();
  54 + resetFields();
  55 + emit('reload');
  56 + };
  57 +
  58 + return {
  59 + registerModal,
  60 + registerForm,
  61 + dispatchCustomer,
  62 + };
  63 + },
  64 + });
  65 +</script>
... ...
... ... @@ -11,7 +11,12 @@
11 11 :customRequest="customUpload"
12 12 :before-upload="beforeUpload"
13 13 >
14   - <img v-if="devicePic" :src="devicePic" alt="avatar" />
  14 + <img
  15 + v-if="devicePic"
  16 + :src="devicePic"
  17 + alt="avatar"
  18 + style="width: 6.25rem; height: 6.25rem"
  19 + />
15 20 <div v-else>
16 21 <PlusOutlined />
17 22 <div class="ant-upload-text">图片上传</div>
... ... @@ -76,7 +81,6 @@
76 81 [Divider.name]: Divider,
77 82 Upload,
78 83 EnvironmentTwoTone,
79   - // LoadingOutlined,
80 84 PlusOutlined,
81 85 Modal,
82 86 [Form.name]: Form,
... ... @@ -175,7 +179,8 @@
175 179 if (!wrapEl) return;
176 180 let preMarker = null;
177 181 const map = new BMap.Map(wrapEl);
178   - let myIcon = new BMap.Icon('/src/assets/images/wz.png', new BMap.Size(20, 30));
  182 + const icon = '/src/assets/images/wz.png';
  183 + let myIcon = new BMap.Icon(icon, new BMap.Size(20, 30));
179 184 const point = new BMap.Point(Number(longitude), Number(latitude));
180 185 let marker = new BMap.Marker(point, { icon: myIcon });
181 186 if (marker) {
... ...
... ... @@ -8,7 +8,7 @@
8 8 />
9 9 <BasicTable @register="registerTable" class="w-5/6 xl:w-4/5">
10 10 <template #toolbar>
11   - <a-button type="primary" @click="handleCreate"> 新增设备 </a-button>
  11 + <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button>
12 12 </template>
13 13 <template #deviceProfile="{ record }">
14 14 <a-button type="link" class="ml-2" @click="goDeviceProfile">
... ... @@ -50,6 +50,23 @@
50 50 <template #action="{ record }">
51 51 <TableAction
52 52 :actions="[
  53 + record.customerId
  54 + ? {
  55 + tooltip: '取消分配给客户',
  56 + icon: 'mdi:account-arrow-left',
  57 + ifShow: authBtn(role),
  58 + popConfirm: {
  59 + title: '是否取消分配给客户',
  60 + confirm: handleCancelDispatchCustomer.bind(null, record),
  61 + },
  62 + }
  63 + : {
  64 + icon: 'mdi:account-arrow-right',
  65 + tooltip: '分配给客户',
  66 + ifShow: authBtn(role),
  67 + onClick: handleDispatchCustomer.bind(null, record),
  68 + },
  69 +
53 70 {
54 71 label: '详情',
55 72 icon: 'ant-design:eye-outlined',
... ... @@ -58,11 +75,13 @@
58 75 {
59 76 label: '编辑',
60 77 icon: 'clarity:note-edit-line',
  78 + ifShow: authBtn(role),
61 79 onClick: handleEdit.bind(null, record),
62 80 },
63 81 {
64 82 label: '删除',
65 83 icon: 'ant-design:delete-outlined',
  84 + ifShow: authBtn(role),
66 85 color: 'error',
67 86 popConfirm: {
68 87 title: '是否确认删除',
... ... @@ -74,7 +93,8 @@
74 93 </template>
75 94 </BasicTable>
76 95 <DeviceDetailDrawer @register="registerDetailDrawer" />
77   - <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" />
  96 + <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleSuccess" />
  97 + <CustomerModal @register="registerCustomerModal" @reload="handleSuccess" />
78 98 </PageWrapper>
79 99 </div>
80 100 </template>
... ... @@ -85,7 +105,7 @@
85 105 import { columns, searchFormSchema } from './config/device.data';
86 106 import { Tag } from 'ant-design-vue';
87 107 import { useMessage } from '/@/hooks/web/useMessage';
88   - import { deleteDevice, devicePage } from '/@/api/device/deviceManager';
  108 + import { deleteDevice, devicePage, cancelDispatchCustomer } from '/@/api/device/deviceManager';
89 109 import { PageEnum } from '/@/enums/pageEnum';
90 110 import { useGo } from '/@/hooks/web/usePage';
91 111 import { PageWrapper } from '/@/components/Page';
... ... @@ -95,7 +115,11 @@
95 115 import DeviceModal from './cpns/modal/DeviceModal.vue';
96 116 import { useDrawer } from '/@/components/Drawer';
97 117 import DeviceDetailDrawer from './cpns/modal/DeviceDetailDrawer.vue';
  118 + import CustomerModal from './cpns/modal/CustomerModal.vue';
98 119
  120 + import { USER_INFO_KEY } from '/@/enums/cacheEnum';
  121 + import { getAuthCache } from '/@/utils/auth';
  122 + import { authBtn } from '/@/enums/roleEnum';
99 123 export default defineComponent({
100 124 name: 'DeviceManagement',
101 125 components: {
... ... @@ -106,6 +130,7 @@
106 130 Tag,
107 131 DeviceModal,
108 132 DeviceDetailDrawer,
  133 + CustomerModal,
109 134 },
110 135 setup(_) {
111 136 const { createMessage } = useMessage();
... ... @@ -114,6 +139,7 @@
114 139 const searchInfo = reactive<Recordable>({});
115 140 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
116 141 const [registerModal, { openModal }] = useModal();
  142 + const [registerCustomerModal, { openModal: openCustomerModal }] = useModal();
117 143 const [registerDetailDrawer, { openDrawer }] = useDrawer();
118 144 const [registerTable, { reload }] = useTable({
119 145 title: '设备列表',
... ... @@ -130,22 +156,32 @@
130 156 showIndexColumn: false,
131 157 searchInfo: searchInfo,
132 158 actionColumn: {
133   - width: 200,
  159 + width: 250,
134 160 title: '操作',
135 161 dataIndex: 'action',
136 162 slots: { customRender: 'action' },
137 163 fixed: 'right',
138 164 },
139 165 });
140   - const handleReload = () => {
141   - handleSuccess();
142   - };
  166 +
  167 + const userInfo: any = getAuthCache(USER_INFO_KEY);
  168 + const role: string = userInfo.roles[0];
143 169
144 170 function handleCreate() {
145 171 openModal(true, {
146 172 isUpdate: false,
147 173 });
148 174 }
  175 + // 分配客户
  176 + function handleDispatchCustomer(record: Recordable) {
  177 + openCustomerModal(true, record);
  178 + }
  179 + // 取消分配客户
  180 + async function handleCancelDispatchCustomer(record: Recordable) {
  181 + console.log('record', record);
  182 + await cancelDispatchCustomer({ ...record, customerId: '' });
  183 + handleSuccess();
  184 + }
149 185
150 186 function handleDetail(record: Recordable) {
151 187 const { id, tbDeviceId } = record;
... ... @@ -191,12 +227,16 @@
191 227 goDeviceProfile,
192 228 handleSelect,
193 229 registerModal,
194   - handleReload,
195 230 registerDetailDrawer,
196 231 DeviceTypeEnum,
197 232 DeviceState,
198 233 searchInfo,
199 234 organizationIdTreeRef,
  235 + handleDispatchCustomer,
  236 + handleCancelDispatchCustomer,
  237 + registerCustomerModal,
  238 + authBtn,
  239 + role,
200 240 };
201 241 },
202 242 });
... ...
... ... @@ -41,7 +41,7 @@ export const columns: BasicColumn[] = [
41 41 customRender: ({ record }) => {
42 42 const status = record.readStatus;
43 43 const enable = status == 0 ? '未读' : status == 1 ? '已读' : '其他';
44   - const color = enable == '未读' ? 'green' : enable == '已读' ? 'yellow' : 'red';
  44 + const color = enable == '未读' ? 'yellow' : enable == '已读' ? 'green' : 'red';
45 45 const text = enable == '未读' ? '未读' : enable == '已读' ? '已读' : '其他';
46 46 return h(Tag, { color }, () => text);
47 47 },
... ...
... ... @@ -21,6 +21,7 @@
21 21 name: 'AccountDetail',
22 22 components: { PageWrapper, Description },
23 23 setup() {
  24 + console.log(123);
24 25 const route = useRoute();
25 26 const go = useGo();
26 27 const { setTitle, close } = useTabs();
... ...
... ... @@ -90,7 +90,7 @@
90 90 setModalProps({ confirmLoading: true });
91 91 await SaveOrUpdateUserInfo(values, unref(isUpdate));
92 92 closeModal();
93   - emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
  93 + emit('success');
94 94 createMessage.success(unref(isUpdate) ? '编辑成功' : '新增成功');
95 95 } finally {
96 96 setModalProps({ confirmLoading: false });
... ...
... ... @@ -88,7 +88,7 @@
88 88 const { createMessage } = useMessage();
89 89 let searchInfo = reactive<Recordable>({});
90 90 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
91   - const [registerTable, { reload, updateTableDataRecord }] = useTable({
  91 + const [registerTable, { reload }] = useTable({
92 92 title: '账号列表',
93 93 api: getAccountList,
94 94 rowKey: 'id',
... ... @@ -131,14 +131,8 @@
131 131 });
132 132 }
133 133
134   - function handleSuccess({ isUpdate, values }) {
135   - if (isUpdate) {
136   - // 演示不刷新表格直接更新内部数据。
137   - // 注意:updateTableDataRecord要求表格的rowKey属性为string并且存在于每一行的record的keys中
138   - updateTableDataRecord(values.id, values);
139   - } else {
140   - reload();
141   - }
  134 + function handleSuccess() {
  135 + reload();
142 136 }
143 137
144 138 function handleSelect(organization) {
... ...
... ... @@ -79,7 +79,7 @@
79 79 @click="handleUpdateInfo"
80 80 size="large"
81 81 type="primary"
82   - style="margin-top: 20px; background-color: #2950f7; border-radius: 5px"
  82 + style="margin-top: 20px; border-radius: 5px"
83 83 >保存信息</a-button
84 84 >
85 85 </div>
... ...
... ... @@ -79,7 +79,7 @@
79 79 @click="handleUpdateInfo"
80 80 size="large"
81 81 type="primary"
82   - style="margin-top: 20px; background-color: #2950f7; border-radius: 5px"
  82 + style="margin-top: 20px; border-radius: 5px"
83 83 >保存信息</a-button
84 84 >
85 85 </div>
... ...
... ... @@ -32,7 +32,7 @@
32 32 @click="handleUpdateInfo"
33 33 size="large"
34 34 type="primary"
35   - style="margin-top: 20px; background-color: #2950f7; border-radius: 5px"
  35 + style="margin-top: 20px; border-radius: 5px"
36 36 >更新基本信息</a-button
37 37 >
38 38 </div>
... ...
... ... @@ -81,6 +81,7 @@
81 81 record,
82 82 isUpdate: true,
83 83 });
  84 + console.log(record);
84 85 }
85 86
86 87 async function handleDelete(record: Recordable) {
... ...