|
@@ -1,93 +1,87 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="setting-container">
|
|
|
|
|
- <div class="setting-card">
|
|
|
|
|
- <div class="card-header">
|
|
|
|
|
- <h2 class="title">Network Settings</h2>
|
|
|
|
|
- <p class="subtitle">Configure device network connection parameters</p>
|
|
|
|
|
|
|
+ <div class="ip-settings">
|
|
|
|
|
+ <div class="section">
|
|
|
|
|
+ <div class="section-title">DHCP Settings</div>
|
|
|
|
|
+ <div class="dhcp-row">
|
|
|
|
|
+ <span class="label">Automatic (DHCP):</span>
|
|
|
|
|
+ <el-switch
|
|
|
|
|
+ v-model="settingFormData.enableDHCP"
|
|
|
|
|
+ :active-value="1"
|
|
|
|
|
+ :inactive-value="0"
|
|
|
|
|
+ active-color="#409eff"
|
|
|
|
|
+ inactive-color="#dcdfe4"
|
|
|
|
|
+ @change="switchChange($event)"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="content">
|
|
|
|
|
- <el-form
|
|
|
|
|
- ref="settingFormRef"
|
|
|
|
|
- :hide-required-asterisk="true"
|
|
|
|
|
- label-position="left"
|
|
|
|
|
- label-width="125px"
|
|
|
|
|
- :model="settingFormData"
|
|
|
|
|
- :rules="settingFormRules"
|
|
|
|
|
- @keyup.enter="handleSave"
|
|
|
|
|
- >
|
|
|
|
|
- <!-- 自动获取DHCP -->
|
|
|
|
|
- <div class="dhcp-section">
|
|
|
|
|
- <div class="dhcp-header">
|
|
|
|
|
- <span class="dhcp-label">Automatic (DHCP)</span>
|
|
|
|
|
- <el-switch
|
|
|
|
|
- v-model="settingFormData.enableDHCP"
|
|
|
|
|
- :active-value="1"
|
|
|
|
|
- :inactive-value="0"
|
|
|
|
|
- active-color="#409eff"
|
|
|
|
|
- inactive-color="#dcdfe4"
|
|
|
|
|
- @change="switchChange($event)"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- <p class="dhcp-tip">The following fields will be disabled when automatic configuration is enabled.</p>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- IP版本 -->
|
|
|
|
|
- <el-form-item label="IP Version" prop="IP_version" class="form-item-custom">
|
|
|
|
|
- <el-input v-model="IP_version" disabled></el-input>
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <!-- IP地址 -->
|
|
|
|
|
- <el-form-item label="IP Address" prop="IP" class="form-item-custom">
|
|
|
|
|
- <IPInputBox
|
|
|
|
|
- :disabled="settingFormData.enableDHCP"
|
|
|
|
|
- :ip-val="settingFormData.ipAddress"
|
|
|
|
|
- @update:ip-val="(updateVal) => (settingFormData.ipAddress = updateVal)"
|
|
|
|
|
- />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 子网掩码 -->
|
|
|
|
|
- <el-form-item label="Subnet Mask" prop="mask" class="form-item-custom">
|
|
|
|
|
- <IPInputBox
|
|
|
|
|
- :disabled="settingFormData.enableDHCP"
|
|
|
|
|
- :ip-val="settingFormData.subNetAddress"
|
|
|
|
|
- @update:ip-val="(updateVal) => (settingFormData.subNetAddress = updateVal)"
|
|
|
|
|
- />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 默认网关 -->
|
|
|
|
|
- <el-form-item label="Default Gateway" prop="gateway" class="form-item-custom">
|
|
|
|
|
- <IPInputBox
|
|
|
|
|
- :disabled="settingFormData.enableDHCP"
|
|
|
|
|
- :ip-val="settingFormData.gateWayAddress"
|
|
|
|
|
- @update:ip-val="(updateVal) => (settingFormData.gateWayAddress = updateVal)"
|
|
|
|
|
- />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
- <!-- 物理地址 -->
|
|
|
|
|
- <el-form-item label="Physical Address" class="form-item-custom">
|
|
|
|
|
- <el-input
|
|
|
|
|
- v-model="settingFormData.deviceMac"
|
|
|
|
|
- disabled
|
|
|
|
|
- placeholder="MAC地址"
|
|
|
|
|
- class="mac-input"
|
|
|
|
|
- />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 操作按钮 -->
|
|
|
|
|
- <div class="button-group">
|
|
|
|
|
- <el-button
|
|
|
|
|
- :loading="loading"
|
|
|
|
|
- size="large"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click="handleSave()"
|
|
|
|
|
- class="save-button"
|
|
|
|
|
- >
|
|
|
|
|
- <span v-if="!loading">Save</span>
|
|
|
|
|
- <span v-else>Saving...</span>
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-form>
|
|
|
|
|
|
|
+ <div class="dhcp-tip">
|
|
|
|
|
+ <el-icon class="tip-icon"><InfoFilled /></el-icon>
|
|
|
|
|
+ <span>The following fields will be disabled when automatic configuration is enabled.</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <el-divider class="short-divider" />
|
|
|
|
|
+
|
|
|
|
|
+ <div class="section">
|
|
|
|
|
+ <div class="section-title">Network Parameters</div>
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ ref="settingFormRef"
|
|
|
|
|
+ :hide-required-asterisk="true"
|
|
|
|
|
+ label-position="left"
|
|
|
|
|
+ label-width="140px"
|
|
|
|
|
+ :model="settingFormData"
|
|
|
|
|
+ :rules="settingFormRules"
|
|
|
|
|
+ @keyup.enter="handleSave"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form-item label="IP Version" class="form-item-custom">
|
|
|
|
|
+ <el-input v-model="IP_version" disabled style="width: 240px;" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="IP Address" prop="IP" class="form-item-custom">
|
|
|
|
|
+ <IPInputBox
|
|
|
|
|
+ :disabled="settingFormData.enableDHCP"
|
|
|
|
|
+ :ip-val="settingFormData.ipAddress"
|
|
|
|
|
+ @update:ip-val="(updateVal) => (settingFormData.ipAddress = updateVal)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="Subnet Mask" prop="mask" class="form-item-custom">
|
|
|
|
|
+ <IPInputBox
|
|
|
|
|
+ :disabled="settingFormData.enableDHCP"
|
|
|
|
|
+ :ip-val="settingFormData.subNetAddress"
|
|
|
|
|
+ @update:ip-val="(updateVal) => (settingFormData.subNetAddress = updateVal)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="Default Gateway" prop="gateway" class="form-item-custom">
|
|
|
|
|
+ <IPInputBox
|
|
|
|
|
+ :disabled="settingFormData.enableDHCP"
|
|
|
|
|
+ :ip-val="settingFormData.gateWayAddress"
|
|
|
|
|
+ @update:ip-val="(updateVal) => (settingFormData.gateWayAddress = updateVal)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="IPv4 DNS" prop="firstDNSAddress" class="form-item-custom">
|
|
|
|
|
+ <IPInputBox
|
|
|
|
|
+ :disabled="settingFormData.enableDHCP"
|
|
|
|
|
+ :ip-val="settingFormData.firstDNSAddress"
|
|
|
|
|
+ @update:ip-val="(updateVal) => (settingFormData.firstDNSAddress = updateVal)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="Physical Address" class="form-item-custom">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="settingFormData.deviceMac"
|
|
|
|
|
+ disabled
|
|
|
|
|
+ placeholder="MAC address"
|
|
|
|
|
+ style="width: 240px;"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-button type="primary" round :loading="loading" @click="handleSave">
|
|
|
|
|
+ <span v-if="!loading">Save</span>
|
|
|
|
|
+ <span v-else>Saving...</span>
|
|
|
|
|
+ </el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -98,20 +92,17 @@ import {
|
|
|
ElMessage,
|
|
ElMessage,
|
|
|
ElMessageBox
|
|
ElMessageBox
|
|
|
} from 'element-plus'
|
|
} from 'element-plus'
|
|
|
|
|
+import { InfoFilled } from '@element-plus/icons-vue'
|
|
|
import { getUserSettingApi, putUserSettingApi } from '@/api/setting'
|
|
import { getUserSettingApi, putUserSettingApi } from '@/api/setting'
|
|
|
import { type UpdateSettingRequestData } from '@/api/types/setting'
|
|
import { type UpdateSettingRequestData } from '@/api/types/setting'
|
|
|
-import IPInputBox from './components/IPInputBox.vue'
|
|
|
|
|
-import {useUserStore} from "@/stores/modules/user";
|
|
|
|
|
-import {useRouter} from "vue-router";
|
|
|
|
|
|
|
+import IPInputBox from '../IPInputBox.vue'
|
|
|
|
|
+import { useUserStore } from "@/stores/modules/user"
|
|
|
|
|
+import { useRouter } from "vue-router"
|
|
|
|
|
+
|
|
|
const router = useRouter()
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
const IP_version = ref('IPV4')
|
|
const IP_version = ref('IPV4')
|
|
|
-const options = [
|
|
|
|
|
- {
|
|
|
|
|
- value: 'IPV4',
|
|
|
|
|
- label: 'IPV4'
|
|
|
|
|
- }
|
|
|
|
|
-]
|
|
|
|
|
|
|
+
|
|
|
/** 按钮 Loading */
|
|
/** 按钮 Loading */
|
|
|
const loading = ref(false)
|
|
const loading = ref(false)
|
|
|
/** 表单数据 */
|
|
/** 表单数据 */
|
|
@@ -121,6 +112,8 @@ const settingFormData: UpdateSettingRequestData = reactive({
|
|
|
ipAddress: '',
|
|
ipAddress: '',
|
|
|
subNetAddress: '',
|
|
subNetAddress: '',
|
|
|
gateWayAddress: '',
|
|
gateWayAddress: '',
|
|
|
|
|
+ firstDNSAddress: '',
|
|
|
|
|
+ secondDNSAddress: '',
|
|
|
deviceMac: ''
|
|
deviceMac: ''
|
|
|
})
|
|
})
|
|
|
|
|
|
|
@@ -133,7 +126,6 @@ const settingFormRules: FormRules = {
|
|
|
{
|
|
{
|
|
|
validator: (rule, value, callback) => {
|
|
validator: (rule, value, callback) => {
|
|
|
if (settingFormData.ipAddress) {
|
|
if (settingFormData.ipAddress) {
|
|
|
- // 添加网段验证
|
|
|
|
|
if (settingFormData.gateWayAddress && settingFormData.subNetAddress) {
|
|
if (settingFormData.gateWayAddress && settingFormData.subNetAddress) {
|
|
|
if (!isSameSubnet(settingFormData.ipAddress, settingFormData.gateWayAddress, settingFormData.subNetAddress)) {
|
|
if (!isSameSubnet(settingFormData.ipAddress, settingFormData.gateWayAddress, settingFormData.subNetAddress)) {
|
|
|
callback(new Error('IP address and gateway address are not in the same subnet'))
|
|
callback(new Error('IP address and gateway address are not in the same subnet'))
|
|
@@ -164,7 +156,6 @@ const settingFormRules: FormRules = {
|
|
|
{
|
|
{
|
|
|
validator: (rule, value, callback) => {
|
|
validator: (rule, value, callback) => {
|
|
|
if (settingFormData.gateWayAddress) {
|
|
if (settingFormData.gateWayAddress) {
|
|
|
- // 添加网段验证
|
|
|
|
|
if (settingFormData.ipAddress && settingFormData.subNetAddress) {
|
|
if (settingFormData.ipAddress && settingFormData.subNetAddress) {
|
|
|
if (!isSameSubnet(settingFormData.ipAddress, settingFormData.gateWayAddress, settingFormData.subNetAddress)) {
|
|
if (!isSameSubnet(settingFormData.ipAddress, settingFormData.gateWayAddress, settingFormData.subNetAddress)) {
|
|
|
callback(new Error('IP address and gateway address are not in the same subnet'))
|
|
callback(new Error('IP address and gateway address are not in the same subnet'))
|
|
@@ -178,36 +169,34 @@ const settingFormRules: FormRules = {
|
|
|
},
|
|
},
|
|
|
trigger: 'blur'
|
|
trigger: 'blur'
|
|
|
}
|
|
}
|
|
|
- ]
|
|
|
|
|
|
|
+ ],
|
|
|
|
|
+ firstDNSAddress: [
|
|
|
|
|
+ {
|
|
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
|
|
+ if (settingFormData.firstDNSAddress) {
|
|
|
|
|
+ callback()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback(new Error('Please enter the IPv4 DNS'))
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ trigger: 'blur'
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 检查IP地址和网关地址是否在同一个网段
|
|
// 检查IP地址和网关地址是否在同一个网段
|
|
|
const isSameSubnet = (ip: string, gateway: string, subnetMask: string): boolean => {
|
|
const isSameSubnet = (ip: string, gateway: string, subnetMask: string): boolean => {
|
|
|
- if (!ip || !gateway || !subnetMask) {
|
|
|
|
|
- return true // 如果任一字段为空,不进行验证
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (!ip || !gateway || !subnetMask) return true
|
|
|
try {
|
|
try {
|
|
|
const ipParts = ip.split('.').map(Number)
|
|
const ipParts = ip.split('.').map(Number)
|
|
|
const gatewayParts = gateway.split('.').map(Number)
|
|
const gatewayParts = gateway.split('.').map(Number)
|
|
|
const maskParts = subnetMask.split('.').map(Number)
|
|
const maskParts = subnetMask.split('.').map(Number)
|
|
|
-
|
|
|
|
|
- // 验证IP地址格式
|
|
|
|
|
- if (ipParts.length !== 4 || gatewayParts.length !== 4 || maskParts.length !== 4) {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 计算网络地址
|
|
|
|
|
|
|
+ if (ipParts.length !== 4 || gatewayParts.length !== 4 || maskParts.length !== 4) return false
|
|
|
const ipNetwork = ipParts.map((part, index) => part & maskParts[index])
|
|
const ipNetwork = ipParts.map((part, index) => part & maskParts[index])
|
|
|
const gatewayNetwork = gatewayParts.map((part, index) => part & maskParts[index])
|
|
const gatewayNetwork = gatewayParts.map((part, index) => part & maskParts[index])
|
|
|
-
|
|
|
|
|
- // 比较网络地址是否相同
|
|
|
|
|
for (let i = 0; i < 4; i++) {
|
|
for (let i = 0; i < 4; i++) {
|
|
|
- if (ipNetwork[i] !== gatewayNetwork[i]) {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (ipNetwork[i] !== gatewayNetwork[i]) return false
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
return true
|
|
return true
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('网段验证错误:', error)
|
|
console.error('网段验证错误:', error)
|
|
@@ -215,15 +204,14 @@ const isSameSubnet = (ip: string, gateway: string, subnetMask: string): boolean
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
const switchChange = ($event: number) => {
|
|
const switchChange = ($event: number) => {
|
|
|
if ($event === 1) {
|
|
if ($event === 1) {
|
|
|
settingFormRef.value?.clearValidate()
|
|
settingFormRef.value?.clearValidate()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-const param = {
|
|
|
|
|
- NIC: 1
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
+const param = { NIC: 1 }
|
|
|
|
|
+
|
|
|
/** 获取表单数据 */
|
|
/** 获取表单数据 */
|
|
|
const fetchData = () => {
|
|
const fetchData = () => {
|
|
|
getUserSettingApi(param.NIC).then((res) => {
|
|
getUserSettingApi(param.NIC).then((res) => {
|
|
@@ -240,193 +228,88 @@ fetchData()
|
|
|
|
|
|
|
|
/** 保存逻辑 */
|
|
/** 保存逻辑 */
|
|
|
const handleSave = () => {
|
|
const handleSave = () => {
|
|
|
- settingFormRef.value?.validate((valid: boolean, fields) => {
|
|
|
|
|
- if (valid) {
|
|
|
|
|
- ElMessageBox.confirm('Changing the network configuration will restart the device', 'Note', {
|
|
|
|
|
- confirmButtonText: 'OK',
|
|
|
|
|
- cancelButtonText: 'Cancel',
|
|
|
|
|
- type: 'warning',
|
|
|
|
|
- confirmButtonClass: 'el-button--danger'
|
|
|
|
|
- }).then(() => {
|
|
|
|
|
- loading.value = true
|
|
|
|
|
- putUserSettingApi(param.NIC, settingFormData)
|
|
|
|
|
- .then(() => {
|
|
|
|
|
- ElMessage.success('Operation successful. Please wait a moment...')
|
|
|
|
|
- useUserStore().logout()
|
|
|
|
|
- router.push('/login')
|
|
|
|
|
- })
|
|
|
|
|
- .finally(() => {
|
|
|
|
|
- loading.value = false
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ settingFormRef.value?.validate((valid: boolean, fields) => {
|
|
|
|
|
+ if (valid) {
|
|
|
|
|
+ ElMessageBox.confirm('Changing the network configuration will restart the device', 'Note', {
|
|
|
|
|
+ confirmButtonText: 'OK',
|
|
|
|
|
+ cancelButtonText: 'Cancel',
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ confirmButtonClass: 'el-button--danger'
|
|
|
|
|
+ }).then(() => {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ putUserSettingApi(param.NIC, settingFormData)
|
|
|
|
|
+ .then(() => {
|
|
|
|
|
+ ElMessage.success('Operation successful. Please wait a moment...')
|
|
|
|
|
+ useUserStore().logout()
|
|
|
|
|
+ router.push('/login')
|
|
|
|
|
+ })
|
|
|
|
|
+ .finally(() => {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
|
|
-.setting-container {
|
|
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.ip-settings {
|
|
|
padding: 20px;
|
|
padding: 20px;
|
|
|
- //background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
|
|
|
- min-height: 85vh;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- //align-items: flex-start;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.setting-card {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- max-width: 510px;
|
|
|
|
|
- background: white;
|
|
|
|
|
- border-radius: 12px;
|
|
|
|
|
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- transition: all 0.3s ease;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-.card-header {
|
|
|
|
|
- color: #000104;
|
|
|
|
|
- padding: 20px 20px 0 20px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
-
|
|
|
|
|
- .title {
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- font-size: 24px;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
- margin-bottom: 8px;
|
|
|
|
|
|
|
+ .el-button{
|
|
|
|
|
+ margin-top: 30px;
|
|
|
|
|
+ width: 80px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- .subtitle {
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- opacity: 0.9;
|
|
|
|
|
|
|
+ .short-divider {
|
|
|
|
|
+ max-width: 700px;
|
|
|
|
|
+ margin: 16px 0;
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-.content {
|
|
|
|
|
- padding: 30px;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ .section {
|
|
|
|
|
+ margin: 16px 0;
|
|
|
|
|
|
|
|
-.dhcp-section {
|
|
|
|
|
- background: #f0f9ff;
|
|
|
|
|
- border-left: 4px solid #409eff;
|
|
|
|
|
- padding: 16px;
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
- margin-bottom: 24px;
|
|
|
|
|
|
|
+ .section-title {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- .dhcp-header {
|
|
|
|
|
|
|
+ .dhcp-row {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
margin-bottom: 8px;
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
- .dhcp-label {
|
|
|
|
|
|
|
+ .label {
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
- font-weight: 500;
|
|
|
|
|
color: #333;
|
|
color: #333;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.dhcp-tip {
|
|
.dhcp-tip {
|
|
|
- margin: 0;
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+ font-size: 13px;
|
|
|
color: #909399;
|
|
color: #909399;
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.form-item-custom {
|
|
|
|
|
- margin-bottom: 20px;
|
|
|
|
|
-
|
|
|
|
|
- :deep(.el-form-item__label) {
|
|
|
|
|
- color: #606266;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- padding-right: 12px;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.mac-input {
|
|
|
|
|
- :deep(.el-input__wrapper) {
|
|
|
|
|
- background-color: #f5f7fa !important;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-.button-group {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 12px;
|
|
|
|
|
- margin-top: 32px;
|
|
|
|
|
- padding-top: 20px;
|
|
|
|
|
- border-top: 1px solid #ebeef5;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.save-button {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- height: 40px;
|
|
|
|
|
- font-size: 16px;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- border-radius: 6px;
|
|
|
|
|
- transition: all 0.3s ease;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- transform: translateY(-2px);
|
|
|
|
|
- box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- &:active {
|
|
|
|
|
- transform: translateY(0);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 响应式设计
|
|
|
|
|
-@media (max-width: 600px) {
|
|
|
|
|
- .setting-container {
|
|
|
|
|
- padding: 12px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .setting-card {
|
|
|
|
|
- max-width: 100%;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .content {
|
|
|
|
|
- padding: 20px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .card-header {
|
|
|
|
|
- padding: 20px 16px;
|
|
|
|
|
-
|
|
|
|
|
- .title {
|
|
|
|
|
- font-size: 20px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .subtitle {
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
|
|
+ .tip-icon {
|
|
|
|
|
+ font-size: 15px;
|
|
|
|
|
+ color: #909399;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 深色主题支持(可选)
|
|
|
|
|
-@media (prefers-color-scheme: dark) {
|
|
|
|
|
- .setting-card {
|
|
|
|
|
- background: #1e1e1e;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .content {
|
|
|
|
|
- color: #e0e0e0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
.form-item-custom {
|
|
.form-item-custom {
|
|
|
- :deep(.el-form-item__label) {
|
|
|
|
|
- color: #b0b0b0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ margin-bottom: 18px;
|
|
|
|
|
|
|
|
- :deep(.el-input__wrapper) {
|
|
|
|
|
- background-color: #2a2a2a;
|
|
|
|
|
- border-color: #404040;
|
|
|
|
|
|
|
+ :deep(.el-form-item__label) {
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ font-weight: 500;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+
|
|
|
|
|
+</style>
|