Commit 2ef6cb196f588d42ca07805468582ac9d63630a8
Merge branch 'dev-fix-ww' into 'main_dev'
fix: 修复teambation BUG See merge request yunteng/thingskit-front!554
Showing
16 changed files
with
102 additions
and
139 deletions
... | ... | @@ -3,24 +3,32 @@ import { Rule } from '/@/components/Form'; |
3 | 3 | export { default as JSONEditor } from './index.vue'; |
4 | 4 | |
5 | 5 | export const parseStringToJSON = <T = Recordable>(value: string) => { |
6 | + let valid = false; | |
6 | 7 | try { |
7 | 8 | const json = JSON.parse(value) as T; |
8 | - return { json, valid: true }; | |
9 | + typeof json === 'object' ? (valid = true) : (valid = false); | |
10 | + return { json, valid }; | |
9 | 11 | } catch (error) { |
10 | - return { json: null, valid: false }; | |
12 | + return { json: null, valid }; | |
11 | 13 | } |
12 | 14 | }; |
13 | 15 | |
14 | -export const JSONEditorValidator = (message = 'json格式校验失败'): Rule[] => { | |
16 | +export const JSONEditorValidator = ( | |
17 | + message = 'JSON格式校验失败', | |
18 | + noEmpty = false, | |
19 | + emptyMessage = 'JSON不能为空对象' | |
20 | +): Rule[] => { | |
15 | 21 | return [ |
16 | 22 | { |
17 | 23 | validateTrigger: 'blur', |
18 | 24 | validator(_rule: Rule, value: any, _callback: Fn) { |
19 | - const { valid } = parseStringToJSON(value); | |
25 | + const { valid, json } = parseStringToJSON(value); | |
20 | 26 | if (valid) { |
27 | + if (noEmpty && json && !Object.keys(json).length) return Promise.reject(emptyMessage); | |
21 | 28 | return Promise.resolve(); |
29 | + } else { | |
30 | + return Promise.reject(message); | |
22 | 31 | } |
23 | - return Promise.reject(message); | |
24 | 32 | }, |
25 | 33 | }, |
26 | 34 | ]; | ... | ... |
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | defineProps<{ |
19 | 19 | value?: string; |
20 | 20 | options?: JSONEditorOptions; |
21 | + height?: number; | |
21 | 22 | }>(), |
22 | 23 | { |
23 | 24 | options: () => |
... | ... | @@ -26,6 +27,7 @@ |
26 | 27 | mainMenuBar: false, |
27 | 28 | statusBar: false, |
28 | 29 | } as JSONEditorOptions), |
30 | + height: 150, | |
29 | 31 | } |
30 | 32 | ); |
31 | 33 | |
... | ... | @@ -106,7 +108,7 @@ |
106 | 108 | </script> |
107 | 109 | |
108 | 110 | <template> |
109 | - <div class="p-2 bg-gray-200"> | |
111 | + <div class="p-2 bg-gray-200" :style="{ height: `${height - 16}px` }"> | |
110 | 112 | <div ref="jsonEditorElRef" class="jsoneditor"></div> |
111 | 113 | </div> |
112 | 114 | </template> | ... | ... |
1 | 1 | <script setup lang="ts"> |
2 | 2 | import { List, Card, Button, PaginationProps, Tooltip } from 'ant-design-vue'; |
3 | 3 | import { ReloadOutlined } from '@ant-design/icons-vue'; |
4 | - import { onMounted, reactive, ref, unref } from 'vue'; | |
4 | + import { computed, onMounted, reactive, ref, unref } from 'vue'; | |
5 | 5 | import { OrganizationIdTree, useResetOrganizationTree } from '../common/organizationIdTree'; |
6 | 6 | import { |
7 | 7 | bigScreenCancelPublish, |
... | ... | @@ -30,6 +30,8 @@ |
30 | 30 | import { ViewTypeNameEnum } from '../common/ShareModal/config'; |
31 | 31 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
32 | 32 | import { ViewType } from '../visual/board/config/panelDetail'; |
33 | + import { useUserStore } from '/@/store/modules/user'; | |
34 | + import { RoleEnum } from '/@/enums/roleEnum'; | |
33 | 35 | |
34 | 36 | const listColumn = ref(5); |
35 | 37 | |
... | ... | @@ -173,6 +175,11 @@ |
173 | 175 | return `${origin}${largeDesignerPrefix}/#/share/preview/${record.id}/${record.publicId}`; |
174 | 176 | }; |
175 | 177 | |
178 | + const userStore = useUserStore(); | |
179 | + const hasPublicInterfacePermission = computed(() => { | |
180 | + return userStore.getUserInfo.roles![0] !== RoleEnum.CUSTOMER_USER; | |
181 | + }); | |
182 | + | |
176 | 183 | const { clipboardRef, isSuccessRef } = useCopyToClipboard(); |
177 | 184 | const handleCreateShareUrl = (record: BigScreenCenterItemsModel) => { |
178 | 185 | clipboardRef.value = createShareUrl(record); |
... | ... | @@ -214,7 +221,7 @@ |
214 | 221 | <Authority :value="ConfigurationPermission.CREATE"> |
215 | 222 | <Button type="primary" @click="handleCreateOrUpdate()">新增大屏</Button> |
216 | 223 | </Authority> |
217 | - <Authority :value="ConfigurationPermission.CREATE"> | |
224 | + <Authority v-if="hasPublicInterfacePermission" :value="ConfigurationPermission.CREATE"> | |
218 | 225 | <Button type="primary" @click="handleCreateOrUpdatePublicApi()">公共接口管理</Button> |
219 | 226 | </Authority> |
220 | 227 | <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" /> | ... | ... |
1 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
2 | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | 3 | import { deviceProfile, getGatewayDevice } from '/@/api/device/deviceManager'; |
4 | 4 | import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const'; |
5 | +import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; | |
6 | +import { JSONEditor } from '/@/components/CodeEditor'; | |
7 | +useComponentRegister('JSONEditor', JSONEditor); | |
5 | 8 | |
6 | 9 | export enum TypeEnum { |
7 | 10 | IS_GATEWAY = 'GATEWAY', |
... | ... | @@ -751,6 +754,7 @@ export const CommandSchemas = (transportType: TransportTypeEnum): FormSchema[] = |
751 | 754 | minRows: 6, |
752 | 755 | }, |
753 | 756 | }, |
757 | + colProps: { span: 20 }, | |
754 | 758 | dynamicRules: () => { |
755 | 759 | return [ |
756 | 760 | { |
... | ... | @@ -770,11 +774,17 @@ export const CommandSchemas = (transportType: TransportTypeEnum): FormSchema[] = |
770 | 774 | { |
771 | 775 | field: 'commandValue', |
772 | 776 | label: '请输入命令内容', |
773 | - slot: 'commandSlot', | |
774 | - component: 'InputTextArea', | |
775 | - show: ({ model }) => { | |
777 | + component: 'JSONEditor', | |
778 | + colProps: { span: 20 }, | |
779 | + changeEvent: 'update:value', | |
780 | + valueField: 'value', | |
781 | + rules: [...JSONEditorValidator()], | |
782 | + ifShow: ({ model }) => { | |
776 | 783 | return model['valueType'] === 'json'; |
777 | 784 | }, |
785 | + componentProps: { | |
786 | + height: 250, | |
787 | + }, | |
778 | 788 | }, |
779 | 789 | ]; |
780 | 790 | }; | ... | ... |
1 | 1 | <template> |
2 | - <div style="background-color: #f0f2f5"> | |
2 | + <div class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700"> | |
3 | 3 | <BasicTable @register="registerTable"> |
4 | 4 | <template #tbDeviceName="{ record }"> |
5 | 5 | <div style="color: #619eff" class="cursor-pointer" @click="handleGetTbDeviceId(record)"> | ... | ... |
1 | 1 | <template> |
2 | 2 | <div class="tabs-detail"> |
3 | - <div class="mt-4"> | |
4 | - <BasicForm @register="registerForm"> | |
5 | - <template #commandSlot> | |
6 | - <div class="flex"> | |
7 | - <div ref="jsoneditorRef" style="height: 100%; width: 100%"></div> | |
8 | - <a-button style="margin: -5px 0" type="text" @click="handlePremitter">格式化</a-button> | |
9 | - <Tooltip title='{"method":"methodThingskit","params":{"pin":7,"value":1}}' class="ml-2"> | |
10 | - <QuestionCircleOutlined style="font-size: 1rem" /> | |
11 | - </Tooltip> | |
12 | - </div> | |
13 | - </template> | |
14 | - </BasicForm> | |
15 | - <Space class="w-full justify-end" justify="end"> | |
16 | - <Button :disabled="disable" type="primary" @click="handleOk" class="mr-2">确定</Button> | |
3 | + <div> | |
4 | + <BasicForm @register="registerForm" /> | |
5 | + <Space class="w-full justify-end py-2" justify="end"> | |
6 | + <Button :loading="loading" type="primary" @click="handleOk" class="mr-2">确定</Button> | |
17 | 7 | <Button type="default" @click="handleCancel" class="mr-2">重置</Button> |
18 | 8 | </Space> |
19 | 9 | </div> |
20 | 10 | </div> |
21 | 11 | </template> |
22 | 12 | <script lang="ts"> |
23 | - import { defineComponent, ref, onMounted, unref, nextTick } from 'vue'; | |
13 | + import { defineComponent, ref } from 'vue'; | |
24 | 14 | import { BasicForm, useForm } from '/@/components/Form'; |
25 | 15 | import { CommandSchemas } from '../../config/data'; |
26 | 16 | import { commandIssuanceApi } from '/@/api/device/deviceManager'; |
27 | 17 | import { useMessage } from '/@/hooks/web/useMessage'; |
28 | 18 | import { Button } from '/@/components/Button'; |
29 | - import jsoneditor from 'jsoneditor'; | |
30 | - import 'jsoneditor/dist/jsoneditor.min.css'; | |
31 | - import { QuestionCircleOutlined } from '@ant-design/icons-vue'; | |
32 | - import { Space, Tooltip } from 'ant-design-vue'; | |
19 | + import { Space } from 'ant-design-vue'; | |
33 | 20 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
34 | 21 | import { TransportTypeEnum } from '../../../profiles/components/TransportDescript/const'; |
35 | - | |
36 | - interface CommandParams { | |
37 | - additionalInfo: Recordable; | |
38 | - cmdType: string; | |
39 | - method: string; | |
40 | - params: string | Recordable; | |
41 | - persistent: boolean; | |
42 | - } | |
22 | + import { parseStringToJSON } from '/@/components/CodeEditor/src/JSONEditor'; | |
43 | 23 | |
44 | 24 | export default defineComponent({ |
45 | - components: { BasicForm, Button, QuestionCircleOutlined, Tooltip, Space }, | |
25 | + components: { BasicForm, Button, Space }, | |
46 | 26 | props: { |
47 | 27 | deviceDetail: { |
48 | 28 | type: Object as PropType<DeviceRecord>, |
... | ... | @@ -52,8 +32,7 @@ |
52 | 32 | emits: ['register'], |
53 | 33 | setup(props) { |
54 | 34 | const { createMessage } = useMessage(); |
55 | - const jsonData = ref<CommandParams>({} as unknown as CommandParams); | |
56 | - const disable = ref(false); | |
35 | + const loading = ref(false); | |
57 | 36 | |
58 | 37 | const [registerForm, { getFieldsValue, validate, resetFields }] = useForm({ |
59 | 38 | labelWidth: 120, |
... | ... | @@ -63,78 +42,35 @@ |
63 | 42 | labelAlign: 'right', |
64 | 43 | showSubmitButton: false, |
65 | 44 | showResetButton: false, |
66 | - wrapperCol: { | |
67 | - span: 12, | |
68 | - }, | |
69 | 45 | }); |
70 | - // json 以及初始化JSON | |
71 | - const jsoneditorRef = ref(); | |
72 | - const jsonValue = ref({}); | |
73 | - const jsonInstance = ref(); | |
74 | - onMounted(() => { | |
75 | - nextTick(() => { | |
76 | - let options = { | |
77 | - mode: 'code', | |
78 | - mainMenuBar: false, | |
79 | - statusBar: false, | |
80 | - }; | |
81 | - let editor = new jsoneditor(jsoneditorRef.value, options); | |
82 | - editor.set(jsonValue.value); | |
83 | - jsonInstance.value = editor; | |
84 | - }); | |
85 | - }); | |
86 | - const handlePremitter = () => { | |
87 | - const value = unref(jsonInstance).get(); | |
88 | - if (!value) return; | |
89 | - return unref(jsonInstance).set(value); | |
90 | - }; | |
46 | + | |
91 | 47 | const handleCancel = () => { |
92 | 48 | resetFields(); |
93 | - unref(jsonInstance).set({}); | |
94 | 49 | }; |
50 | + | |
95 | 51 | const handleOk = async () => { |
96 | - disable.value = true; | |
52 | + loading.value = true; | |
97 | 53 | try { |
98 | 54 | // 验证 |
99 | 55 | const valid = await validate(); |
100 | 56 | if (!valid) return; |
101 | 57 | // 收集表单数据 |
102 | 58 | const field = getFieldsValue(); |
103 | - let passStatus = false; | |
59 | + let command = { | |
60 | + persistent: true, | |
61 | + method: 'methodThingskit', | |
62 | + params: field.commandText, | |
63 | + }; | |
104 | 64 | if (field.valueType === 'json') { |
105 | - const getJson = unref(jsonInstance).get(); | |
106 | - if (Object.prototype.isPrototypeOf(getJson) && Object.keys(getJson).length === 0) { | |
107 | - createMessage.error('命令内容不能为空'); | |
108 | - passStatus = true; | |
109 | - } | |
110 | - if (getJson === '') { | |
111 | - passStatus = true; | |
112 | - createMessage.error('命令内容不能为空'); | |
113 | - } | |
114 | - jsonData.value.params = getJson; | |
115 | - } else { | |
116 | - jsonData.value.params = field.commandText; | |
117 | - if (!jsonData.value.params) { | |
118 | - createMessage.error('命令内容不能为空'); | |
119 | - passStatus = true; | |
120 | - } | |
121 | - if ( | |
122 | - jsonData.value.params == '""' || | |
123 | - jsonData.value.params == "''" || | |
124 | - jsonData.value.params == '“”' | |
125 | - ) { | |
126 | - createMessage.error('命令内容不能为空'); | |
127 | - passStatus = true; | |
128 | - } | |
65 | + const { json } = parseStringToJSON(field.commandValue); | |
66 | + command.params = json; | |
129 | 67 | } |
130 | - jsonData.value.persistent = true; | |
131 | - jsonData.value.method = 'methodThingskit'; | |
132 | - if (passStatus) return; | |
133 | - commandIssuanceApi(field.commandType, props.deviceDetail.tbDeviceId, jsonData.value) | |
68 | + | |
69 | + commandIssuanceApi(field.commandType, props.deviceDetail.tbDeviceId, command) | |
134 | 70 | .then((res) => { |
135 | 71 | if (!res) return; |
136 | 72 | createMessage.success('命令下发成功'); |
137 | - disable.value = true; | |
73 | + loading.value = true; | |
138 | 74 | // 请求 |
139 | 75 | handleCancel(); |
140 | 76 | }) |
... | ... | @@ -146,25 +82,20 @@ |
146 | 82 | }) |
147 | 83 | .finally(() => { |
148 | 84 | setTimeout(() => { |
149 | - disable.value = false; | |
85 | + loading.value = false; | |
150 | 86 | }, 300); |
151 | 87 | }); |
152 | 88 | } catch (e) { |
89 | + throw e; | |
153 | 90 | } finally { |
154 | - //这里捕获json插件的错误 | |
155 | - disable.value = false; | |
91 | + loading.value = false; | |
156 | 92 | } |
157 | 93 | }; |
158 | 94 | return { |
159 | 95 | registerForm, |
160 | 96 | handleCancel, |
161 | 97 | handleOk, |
162 | - disable, | |
163 | - jsonData, | |
164 | - jsoneditorRef, | |
165 | - jsonValue, | |
166 | - jsonInstance, | |
167 | - handlePremitter, | |
98 | + loading, | |
168 | 99 | }; |
169 | 100 | }, |
170 | 101 | }); | ... | ... |
... | ... | @@ -53,7 +53,7 @@ |
53 | 53 | </script> |
54 | 54 | |
55 | 55 | <template> |
56 | - <BasicTable class="event-manage-table" @register="register"> | |
56 | + <BasicTable class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700" @register="register"> | |
57 | 57 | <template #outputParams="{ record }"> |
58 | 58 | <span class="cursor-pointer text-blue-500" @click="handleViewDetail(record)"> |
59 | 59 | <EyeOutlined class="svg:text-blue-500" /> |
... | ... | @@ -65,9 +65,3 @@ |
65 | 65 | <Input.TextArea v-model:value="outputData" :autosize="true" /> |
66 | 66 | </BasicModal> |
67 | 67 | </template> |
68 | - | |
69 | -<style lang="less" scoped> | |
70 | - .event-manage-table { | |
71 | - background-color: #f0f2f5; | |
72 | - } | |
73 | -</style> | ... | ... |
... | ... | @@ -230,15 +230,16 @@ |
230 | 230 | <template> |
231 | 231 | <PageWrapper |
232 | 232 | dense |
233 | - content-class="flex flex-col bg-transparent p-4" | |
234 | - :content-style="{ backgroundColor: '#F0F2F5' }" | |
233 | + content-class="flex flex-col bg-transparent p-4 bg-neutral-100 dark:text-gray-300 dark:bg-dark-700" | |
235 | 234 | > |
236 | - <section class="flex flex-col justify-between w-full bg-light-50 pt-3 mb-4"> | |
235 | + <section | |
236 | + class="flex flex-col justify-between w-full bg-light-50 pt-3 mb-4 dark:text-gray-300 dark:bg-dark-900" | |
237 | + > | |
237 | 238 | <div class="flex-auto"> |
238 | 239 | <BasicForm @register="registerForm" /> |
239 | 240 | </div> |
240 | 241 | </section> |
241 | - <section class="bg-light-50"> | |
242 | + <section class="bg-light-50 !dark:text-gray-300 !dark:bg-dark-900"> | |
242 | 243 | <div |
243 | 244 | v-show="mode === EnumTableCardMode.CARD" |
244 | 245 | class="flex h-70px items-center justify-end p-2" | ... | ... |
... | ... | @@ -102,7 +102,9 @@ |
102 | 102 | </script> |
103 | 103 | |
104 | 104 | <template> |
105 | - <PageWrapper class="bg-gray-100 device-task-list-container"> | |
105 | + <PageWrapper | |
106 | + class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700 device-task-list-container" | |
107 | + > | |
106 | 108 | <section |
107 | 109 | class="form-container bg-light-50 px-4 pt-4 mt-4 x dark:text-gray-300 dark:bg-dark-900" |
108 | 110 | > | ... | ... |
1 | 1 | <template> |
2 | - <BasicTable class="command-record-table" @register="registerTable"> | |
2 | + <BasicTable | |
3 | + class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700 p-4" | |
4 | + @register="registerTable" | |
5 | + > | |
3 | 6 | <template #toolbar> |
4 | 7 | <Space> |
5 | 8 | <Button type="primary" @click="openModal(true)">命令下发</Button> |
... | ... | @@ -21,11 +24,11 @@ |
21 | 24 | |
22 | 25 | <BasicModal |
23 | 26 | @register="registerCommandIssuanceModal" |
24 | - width="600px" | |
27 | + width="700px" | |
25 | 28 | title="命令下发" |
26 | 29 | :showOkBtn="false" |
27 | 30 | cancelText="关闭" |
28 | - :footer="h('div')" | |
31 | + :footer="null" | |
29 | 32 | > |
30 | 33 | <CommandIssuance :deviceDetail="deviceDetail" /> |
31 | 34 | </BasicModal> |
... | ... | @@ -91,10 +94,3 @@ |
91 | 94 | commonModalInfo('响应内容', jsonParams); |
92 | 95 | }; |
93 | 96 | </script> |
94 | - | |
95 | -<style lang="less" scoped> | |
96 | - .command-record-table { | |
97 | - background-color: #f0f2f5; | |
98 | - padding: 16px; | |
99 | - } | |
100 | -</style> | ... | ... |
... | ... | @@ -151,7 +151,7 @@ |
151 | 151 | </Tabs> |
152 | 152 | <template #footer> |
153 | 153 | <div |
154 | - class="absolute right-0 bottom-0 w-full border-t bg-light-50 border-t-gray-100 py-2 px-4 text-right" | |
154 | + class="absolute right-0 bottom-0 w-full border-t bg-light-50 dark:text-gray-300 dark:bg-dark-700 dark:border-t-gray-700 border-t-gray-100 py-2 px-4 text-right" | |
155 | 155 | > |
156 | 156 | <Button class="mr-2" @click="closeDrawer">取消</Button> |
157 | 157 | <Authority :value="OtaPermissionKey.UPDATE"> | ... | ... |
... | ... | @@ -193,7 +193,11 @@ |
193 | 193 | const userStore = useUserStore(); |
194 | 194 | |
195 | 195 | const permissionStore = usePermissionStore(); |
196 | - async function handleLoginCustomAdmin(record: { tbUser: string; id: string }) { | |
196 | + async function handleLoginCustomAdmin(record: { | |
197 | + tbUser: string; | |
198 | + id: string; | |
199 | + hasPassword: boolean; | |
200 | + }) { | |
197 | 201 | try { |
198 | 202 | const { token, refreshToken } = await getUserToken(record.id); |
199 | 203 | userStore.storeToken(token, refreshToken); |
... | ... | @@ -208,7 +212,7 @@ |
208 | 212 | }); |
209 | 213 | router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw); |
210 | 214 | permissionStore.setDynamicAddedRoute(true); |
211 | - go(PageEnum.BASE_HOME); | |
215 | + record.hasPassword ? go(PageEnum.BASE_HOME) : go(PageEnum.SYSTEM_PASSWORD); | |
212 | 216 | } catch (error) { |
213 | 217 | } finally { |
214 | 218 | } | ... | ... |
... | ... | @@ -161,18 +161,21 @@ |
161 | 161 | api: async () => { |
162 | 162 | try { |
163 | 163 | if (!organizationId) return []; |
164 | - return await getMeetTheConditionsDevice({ | |
164 | + const result = await getMeetTheConditionsDevice({ | |
165 | 165 | deviceProfileId, |
166 | 166 | deviceType, |
167 | 167 | organizationId, |
168 | 168 | }); |
169 | + return result.map((item) => ({ | |
170 | + ...item, | |
171 | + value: item.tbDeviceId, | |
172 | + label: item.alias || item.name, | |
173 | + })); | |
169 | 174 | } catch (error) { |
170 | 175 | return []; |
171 | 176 | } |
172 | 177 | }, |
173 | 178 | mode: props.multiple ? 'multiple' : 'combobox', |
174 | - labelField: 'name', | |
175 | - valueField: 'tbDeviceId', | |
176 | 179 | placeholder: '请选择设备', |
177 | 180 | maxTagCount: 3, |
178 | 181 | maxTagTextLength: 4, | ... | ... |
... | ... | @@ -118,7 +118,7 @@ |
118 | 118 | <template> |
119 | 119 | <PageWrapper class="task-center-container"> |
120 | 120 | <section |
121 | - class="bg-light-50 flex p-4 justify-between items-center x dark:text-gray-300 dark:bg-dark-900" | |
121 | + class="bg-light-50 flex p-4 justify-between items-center dark:text-gray-300 dark:bg-dark-900" | |
122 | 122 | > |
123 | 123 | <div class="text-2xl">任务中心</div> |
124 | 124 | <Authority :value="PermissionEnum.CREATE"> | ... | ... |
... | ... | @@ -333,7 +333,12 @@ |
333 | 333 | <h3 class="w-24 flex-shrink-0 text-right pr-2 my-4">选择数据源</h3> |
334 | 334 | |
335 | 335 | <section ref="formListEl"> |
336 | - <div v-for="item in dataSource" :data-id="item.id" :key="item.id" class="flex bg-light-50"> | |
336 | + <div | |
337 | + v-for="item in dataSource" | |
338 | + :data-id="item.id" | |
339 | + :key="item.id" | |
340 | + class="flex bg-neutral-100 dark:text-gray-300 dark:bg-dark-700" | |
341 | + > | |
337 | 342 | <div class="w-24 text-right flex justify-end" style="flex: 0 0 96px"> 选择设备 </div> |
338 | 343 | <div class="pl-2 flex-auto"> |
339 | 344 | <component | ... | ... |