Commit 676a6a17 by DaiJiezhang

Refine phone dialog and styles

parent 80886283
......@@ -7,7 +7,7 @@
<title>学有为资产管理台</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%230f766e'/%3E%3Ctext x='50%25' y='55%25' text-anchor='middle' font-size='26' font-family='Arial' fill='white'%3EXY%3C/text%3E%3C/svg%3E" />
<link rel="stylesheet" href="node_modules/element-plus/dist/index.css" />
<link rel="stylesheet" href="styles-v2.css?v=20260708b" />
<link rel="stylesheet" href="styles-v2.css?v=20260708c" />
</head>
<body>
......
......@@ -196,12 +196,89 @@
/**
* 代码作用(白话):删除当前图片区域中的单张图片,并把剩余图片重新同步回两个 SQL 字段;关联文件:F:/Project/xyw_console/src/modules/shared/phone-api-client.js、F:/Project/xyw_console/backend/src/main/java/com/xyw/console/phone/dto/WxPhoneSaveRequest.java;关联逻辑(调用链/消息链/数据流):点击删除图片 -> removeImage() -> imageItems -> syncImagesToFormData() -> 保存请求。
*/
function removeImage(index) {
function removeImage(index, event) {
event?.stopPropagation();
event?.preventDefault();
imageItems.value = imageItems.value.filter((_, itemIndex) => itemIndex !== index);
syncImagesToFormData();
}
/**
* 代码作用(白话):双击空图片槽位时触发文件选择,让用户通过双击占位框上传;关联文件:F:/Project/xyw_console/src/modules/phone/phone-add-dialog.js;关联逻辑(调用链/消息链/数据流):双击占位框 -> handleImageDblClick() -> triggerImageSelect() -> file input -> handleImageFileChange()。
*/
function handleImageDblClick(event) {
event?.stopPropagation();
event?.preventDefault();
triggerImageSelect();
}
/**
* 代码作用(白话):处理图片拖拽上传,支持拖拽图片文件到上传区域;关联文件:F:/Project/xyw_console/src/modules/phone/phone-add-dialog.js;关联逻辑(调用链/消息链/数据流):拖拽图片 -> handleImageDrop() -> readFileAsDataUrl() -> imageItems/syncImagesToFormData()。
*/
async function handleImageDrop(event, slotIndex) {
event?.preventDefault();
event?.stopPropagation();
const files = Array.from(event?.dataTransfer?.files || []);
if (!files.length) {
return;
}
// 只处理图片文件
const imageFiles = files.filter(file => file.type.startsWith('image/'));
if (!imageFiles.length) {
ElementPlus.ElMessage.warning('请上传图片文件');
return;
}
if (imageItems.value.length + imageFiles.length > 2) {
ElementPlus.ElMessage.warning('最多上传 2 张图片');
return;
}
try {
const nextItems = [];
for (let index = 0; index < imageFiles.length; index += 1) {
const file = imageFiles[index];
const url = await readFileAsDataUrl(file);
nextItems.push({
id: `${Date.now()}-${index}`,
url,
name: file.name || `图片${imageItems.value.length + index + 1}`
});
}
imageItems.value = imageItems.value.concat(nextItems).slice(0, 2);
syncImagesToFormData();
} catch (error) {
ElementPlus.ElMessage.error(error.message || '读取图片失败,请稍后重试');
}
}
/**
* 代码作用(白话):预览已有图片,使用 Element Plus 的 ElImageViewer 全屏查看;关联文件:F:/Project/xyw_console/src/modules/phone/phone-add-dialog.js;关联逻辑(调用链/消息链/数据流):点击预览按钮 -> previewImage() -> ElImageViewer 临时组件。
*/
function previewImage(url, event) {
event?.stopPropagation();
event?.preventDefault();
const tempDiv = document.createElement('div');
document.body.appendChild(tempDiv);
const viewerApp = createApp({
components: { 'el-image-viewer': ElementPlus.ElImageViewer },
template: '<el-image-viewer :url-list="urls" :initial-index="0" @close="close" teleported />',
setup() {
const urls = ref([url]);
function close() {
viewerApp.unmount();
tempDiv.remove();
}
return { urls, close };
}
});
viewerApp.use(ElementPlus);
viewerApp.mount(tempDiv);
}
/**
* 代码作用(白话):在表单校验通过后调用外层统一保存动作,并在成功后刷新列表;关联文件:F:/Project/xyw_console/app-v2.js、F:/Project/xyw_console/src/modules/shared/phone-api-client.js;关联逻辑(调用链/消息链/数据流):保存按钮 -> handleSubmit() -> submitAfterValidate() -> PhoneAddDialogActions.save() -> afterSave() -> phone 列表刷新。
*/
async function submitAfterValidate(valid) {
......@@ -252,22 +329,67 @@
triggerImageSelect,
handleImageFileChange,
removeImage,
handleImageDblClick,
handleImageDrop,
previewImage,
handleSubmit
};
},
template: `
<el-dialog v-model="visible" width="640px" top="6vh" custom-class="phone-form-dialog">
<el-dialog v-model="visible" width="860px" top="6vh" custom-class="phone-form-dialog">
<template #header>
<div class="phone-form-dialog__title">
{{ isEdit ? '编辑手机号卡' : '新增手机号卡' }}
<span class="phone-form-dialog__title-text">{{ isEdit ? '编辑手机号卡' : '新增手机号卡' }}</span>
<span class="phone-form-dialog__title-hint">基础信息为必填,其余可按需补充</span>
</div>
</template>
<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px" label-position="right" class="phone-form-dialog__form">
<div class="phone-form-dialog__section">
<div class="phone-form-dialog__section-title">基础信息</div>
<el-row :gutter="24">
<!-- 01 图片附件区域 -->
<div class="phone-form-dialog__section phone-form-dialog__section--image">
<div class="phone-form-dialog__section-title">
<span class="phone-form-dialog__section-no">01</span>
<span class="phone-form-dialog__section-name">图片附件</span>
<span class="phone-form-dialog__section-sub">最多 2 张</span>
</div>
<input ref="imageInputRef" type="file" accept="image/*" multiple style="display: none;" @change="handleImageFileChange" />
<div class="phone-form-dialog__image-slots">
<div
v-for="slotIndex in 2"
:key="slotIndex"
class="phone-form-dialog__image-slot"
@click="triggerImageSelect"
@dragover.prevent
@drop="handleImageDrop($event, slotIndex - 1)">
<div v-if="imageItems[slotIndex - 1]" class="phone-form-dialog__image-item">
<img :src="imageItems[slotIndex - 1].url" :alt="imageItems[slotIndex - 1].name" class="phone-form-dialog__image-img" />
<div class="phone-form-dialog__image-overlay">
<button type="button" class="phone-form-dialog__image-preview-btn" @click.stop="previewImage(imageItems[slotIndex - 1].url, $event)">预览</button>
<button type="button" class="phone-form-dialog__image-remove" @click.stop="removeImage(slotIndex - 1, $event)">×</button>
</div>
</div>
<div v-else class="phone-form-dialog__image-empty">
<div class="phone-form-dialog__image-empty-text">拖拽上传</div>
<div class="phone-form-dialog__image-empty-divider">/</div>
<div class="phone-form-dialog__image-empty-text">点击选择</div>
</div>
</div>
</div>
<div class="phone-form-dialog__image-hint">支持 JPG / PNG,最多上传 2 张</div>
</div>
<!-- 分隔线 -->
<div class="phone-form-dialog__divider"></div>
<!-- 02 基础信息区域 -->
<div class="phone-form-dialog__section phone-form-dialog__section--primary">
<div class="phone-form-dialog__section-title">
<span class="phone-form-dialog__section-no">02</span>
<span class="phone-form-dialog__section-name">基础信息</span>
<span class="phone-form-dialog__section-tag">必填</span>
</div>
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="手机号" prop="phoneNumber">
<el-form-item label="手机号" prop="phoneNumber" required>
<el-input v-model="formData.phoneNumber" placeholder="请输入手机号"></el-input>
</el-form-item>
</el-col>
......@@ -277,14 +399,14 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="ICCID 卡号" prop="iccid">
<el-input v-model="formData.iccid" placeholder="请输入 ICCID"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="渠道运营商" prop="channelOperator">
<el-form-item label="渠道运营商" prop="channelOperator" required>
<el-select v-model="formData.channelOperator" placeholder="请选择运营商" style="width: 100%;">
<el-option label="中国移动" value="中国移动"></el-option>
<el-option label="中国联通" value="中国联通"></el-option>
......@@ -295,7 +417,7 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="所在城市" prop="city">
<el-input v-model="formData.city" placeholder="请输入号码归属地"></el-input>
......@@ -307,31 +429,18 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="图片字段">
<div class="phone-form-dialog__image-block">
<input ref="imageInputRef" type="file" accept="image/*" multiple style="display: none;" @change="handleImageFileChange" />
<div class="phone-form-dialog__image-toolbar">
<el-button type="primary" plain @click="triggerImageSelect">选择图片</el-button>
<span class="phone-form-dialog__image-hint">最多上传 2 张图片,保存时拆分写入两个图片字段。</span>
</div>
<div class="phone-form-dialog__image-list">
<div v-for="(image, index) in imageItems" :key="image.id" class="phone-form-dialog__image-item">
<img :src="image.url" :alt="image.name" class="phone-form-dialog__image-img" />
<button type="button" class="phone-form-dialog__image-remove" @click="removeImage(index)">×</button>
</div>
<div v-if="!imageItems.length" class="phone-form-dialog__image-empty" @click="triggerImageSelect">双击上传</div>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="phone-form-dialog__section">
<div class="phone-form-dialog__section-title">状态与保留</div>
<el-row :gutter="24">
<!-- 分隔线 -->
<div class="phone-form-dialog__divider"></div>
<!-- 03 辅助配置区域 -->
<div class="phone-form-dialog__section phone-form-dialog__section--auxiliary">
<div class="phone-form-dialog__section-title">
<span class="phone-form-dialog__section-no">03</span>
<span class="phone-form-dialog__section-name">辅助配置</span>
</div>
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="号卡状态" prop="cardStatus">
<el-select v-model="formData.cardStatus" style="width: 100%;">
......@@ -342,34 +451,20 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="号码状态" prop="numberStatus">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.numberStatus"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.numberStatus }">当前:{{ formData.numberStatus ? '正常' : '异常' }}</span>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="可变更 5 元套餐" prop="packageChange5yuan">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.packageChange5yuan"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.packageChange5yuan }">当前:{{ formData.packageChange5yuan ? '可变更' : '不可变更' }}</span>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.packageChange5yuan }">{{ formData.packageChange5yuan ? '可变更' : '不可变更' }}</span>
</div>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="phone-form-dialog__section">
<div class="phone-form-dialog__section-title">生态账号绑定</div>
<el-row :gutter="24">
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="开通微信" prop="wechat">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.wechat"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wechat }">当前:{{ formData.wechat ? '已开通' : '未开通' }}</span>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wechat }">{{ formData.wechat ? '已开通' : '未开通' }}</span>
</div>
</el-form-item>
</el-col>
......@@ -377,17 +472,17 @@
<el-form-item label="开通企业微信" prop="wecom">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.wecom"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wecom }">当前:{{ formData.wecom ? '已开通' : '未开通' }}</span>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wecom }">{{ formData.wecom ? '已开通' : '未开通' }}</span>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="32">
<el-col :span="12">
<el-form-item label="可外呼" prop="outboundCall">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.outboundCall"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.outboundCall }">当前:{{ formData.outboundCall ? '支持' : '不支持' }}</span>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.outboundCall }">{{ formData.outboundCall ? '支持' : '不支持' }}</span>
</div>
</el-form-item>
</el-col>
......@@ -395,18 +490,13 @@
<el-form-item label="小程序备案" prop="miniProgramFiling">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.miniProgramFiling"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.miniProgramFiling }">当前:{{ formData.miniProgramFiling ? '已备案' : '未备案' }}</span>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.miniProgramFiling }">{{ formData.miniProgramFiling ? '已备案' : '未备案' }}</span>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="绑定企业微信" prop="linkedWecom">
<el-input v-model="formData.linkedWecom" placeholder="关联的企业微信账号"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-row :gutter="32">
<el-col :span="24">
<el-form-item label="抖音账号" prop="douyinAccount">
<el-input v-model="formData.douyinAccount" placeholder="关联的抖音号"></el-input>
</el-form-item>
......@@ -417,7 +507,7 @@
<template #footer>
<div class="phone-form-dialog__footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="handleSubmit">提交保存</el-button>
<el-button type="primary" class="phone-form-dialog__submit-btn" @click="handleSubmit">提交保存</el-button>
</div>
</template>
</el-dialog>
......
......@@ -1380,93 +1380,281 @@
========================================================= */
/* Dialog shell: flex column, max 80vh */
/* ===== Phone Form Dialog: layered hierarchy + unified controls ===== */
.phone-form-dialog {
max-height: 80vh;
width: 860px !important;
max-width: calc(100vw - 48px) !important;
height: 620px !important;
max-height: 78vh !important;
display: flex;
flex-direction: column;
margin: var(--el-dialog-margin-top, 15vh) auto 50px;
overflow: hidden;
border-radius: 12px;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
}
/* Header: fixed, compact */
.phone-form-dialog .el-dialog__header {
padding: 14px 20px 12px;
padding: 16px 24px 14px;
margin-right: 0;
border-bottom: 1px solid #f0f0f0;
border-bottom: 1px solid #e5e7eb;
flex-shrink: 0;
background: #fff;
}
/* Body: scrollable middle area */
.phone-form-dialog .el-dialog__body {
padding: 16px 20px 8px;
padding: 16px 24px;
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
background: #fff;
}
/* Footer: fixed, light background to separate from content */
.phone-form-dialog .el-dialog__footer {
padding: 10px 20px 14px;
border-top: 1px solid #f0f0f0;
background: #fafbfc;
padding: 12px 24px 16px;
border-top: 1px solid #e5e7eb;
background: #fff;
flex-shrink: 0;
}
/* Dialog title with hint */
.phone-form-dialog__title {
font-size: 16px;
font-weight: 600;
color: #1f2937;
display: flex;
align-items: baseline;
gap: 10px;
line-height: 1.4;
}
/* Compact form-item vertical rhythm */
.phone-form-dialog__title-text {
font-size: 17px;
font-weight: 700;
color: #111827;
}
.phone-form-dialog__title-hint {
font-size: 12px;
color: #9ca3af;
font-weight: 400;
}
/* ===== Unified form controls ===== */
.phone-form-dialog__form .el-input__inner,
.phone-form-dialog__form .el-select .el-input__inner {
height: 34px !important;
line-height: 34px !important;
border-radius: 6px !important;
border-color: #d1d5db !important;
transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
}
.phone-form-dialog__form .el-input__inner:focus,
.phone-form-dialog__form .el-select .el-input__inner:focus {
border-color: #d1d5db !important;
box-shadow: none !important;
}
.phone-form-dialog__form .el-input__inner::placeholder {
color: #c0c4cc;
font-size: 13px;
}
/* Unified form-item */
.phone-form-dialog__form .el-form-item {
margin-bottom: 14px;
margin-bottom: 15px;
}
.phone-form-dialog__form .el-row:last-child .el-form-item {
margin-bottom: 0;
}
/* Section: grouped blocks with left accent bar header */
.phone-form-dialog__form .el-form-item__label {
color: #4b5563;
font-size: 13px;
font-weight: 500;
line-height: 34px;
padding-right: 12px;
}
/* Required asterisk: bolder red */
.phone-form-dialog__form .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label::before {
color: #ef4444;
font-weight: 700;
margin-right: 4px;
}
/* ===== Section base ===== */
.phone-form-dialog__section {
margin-bottom: 18px;
margin-bottom: 20px;
}
.phone-form-dialog__section:last-child {
margin-bottom: 12px;
margin-bottom: 0;
}
/* Section title: number + name + tag/sub */
.phone-form-dialog__section-title {
position: relative;
padding-left: 10px;
margin-bottom: 14px;
font-size: 13px;
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
user-select: none;
}
.phone-form-dialog__section-no {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 6px;
font-size: 11px;
font-weight: 700;
line-height: 1;
flex-shrink: 0;
}
.phone-form-dialog__section-name {
font-size: 14px;
font-weight: 600;
color: #1f2937;
color: #111827;
line-height: 1;
user-select: none;
}
.phone-form-dialog__section-title::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 12px;
.phone-form-dialog__section-tag {
display: inline-flex;
align-items: center;
height: 18px;
padding: 0 6px;
border-radius: 3px;
font-size: 11px;
font-weight: 600;
line-height: 1;
}
.phone-form-dialog__section-sub {
font-size: 12px;
color: #9ca3af;
font-weight: 400;
line-height: 1;
}
/* ===== Image section: first priority ===== */
.phone-form-dialog__section--image {
background: transparent;
padding: 0;
border-radius: 0;
border: none;
box-shadow: none;
}
.phone-form-dialog__section--image .phone-form-dialog__section-no {
background: #e5e7eb;
color: #4b5563;
}
.phone-form-dialog__section--image .phone-form-dialog__section-name {
font-size: 13px;
color: #374151;
}
/* ===== Primary section: strongest emphasis ===== */
.phone-form-dialog__section--primary {
background: transparent;
padding: 0;
border-radius: 0;
border: none;
box-shadow: none;
}
.phone-form-dialog__section--primary .phone-form-dialog__section-no {
background: #2563eb;
border-radius: 2px;
color: #fff;
}
.phone-form-dialog__section--primary .phone-form-dialog__section-tag {
background: #fee2e2;
color: #dc2626;
}
/* ===== Divider ===== */
.phone-form-dialog__divider {
height: 1px;
background: #e5e7eb;
margin: 20px 0;
}
/* ===== Auxiliary section: muted, de-emphasized ===== */
.phone-form-dialog__section--auxiliary {
background: transparent;
padding: 0;
border-radius: 0;
border: none;
box-shadow: none;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__section-no {
background: #d1d5db;
color: #6b7280;
width: 20px;
height: 20px;
font-size: 10px;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__section-name {
font-size: 12px;
color: #6b7280;
font-weight: 600;
letter-spacing: 0.3px;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__section-sub {
font-size: 11px;
color: #9ca3af;
}
/* Auxiliary controls: smaller, muted */
.phone-form-dialog__section--auxiliary .el-form-item {
margin-bottom: 15px;
}
/* Switch field: toggle + trailing status text */
.phone-form-dialog__section--auxiliary .el-form-item__label {
color: #9ca3af;
font-size: 12px;
font-weight: 400;
}
.phone-form-dialog__section--auxiliary .el-input__inner,
.phone-form-dialog__section--auxiliary .el-select .el-input__inner {
height: 30px !important;
line-height: 30px !important;
font-size: 12px !important;
background: #fff !important;
border-color: #e5e7eb !important;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__switch {
height: 30px;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__switch-status {
color: #b0b4bb;
font-size: 11px;
}
.phone-form-dialog__section--auxiliary .phone-form-dialog__switch-status.is-on {
color: #6b7280;
}
/* ===== Switch field ===== */
.phone-form-dialog__switch {
display: flex;
align-items: center;
gap: 8px;
height: 32px;
height: 34px;
}
.phone-form-dialog__switch-status {
......@@ -1481,46 +1669,27 @@
color: #2563eb;
}
/* Image field: compact block, ~100px total height */
.phone-form-dialog__image-block {
width: 100%;
display: flex;
flex-direction: column;
gap: 6px;
padding: 10px 12px;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 6px;
}
.phone-form-dialog__image-toolbar {
/* ===== Image slots ===== */
.phone-form-dialog__image-slots {
display: flex;
align-items: center;
gap: 10px;
}
.phone-form-dialog__image-hint {
font-size: 12px;
color: #9ca3af;
line-height: 1;
gap: 16px;
margin-top: 16px;
}
.phone-form-dialog__image-list {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-height: 64px;
.phone-form-dialog__image-slot {
flex: 0 0 auto;
cursor: pointer;
}
.phone-form-dialog__image-item {
position: relative;
width: 64px;
height: 64px;
border-radius: 6px;
width: 150px;
height: 84px;
border-radius: 8px;
overflow: hidden;
border: 1px solid #e5e7eb;
background: #fff;
flex: 0 0 auto;
cursor: pointer;
}
.phone-form-dialog__image-img {
......@@ -1530,49 +1699,124 @@
display: block;
}
.phone-form-dialog__image-remove {
.phone-form-dialog__image-overlay {
position: absolute;
top: 2px;
right: 2px;
width: 18px;
height: 18px;
padding: 0;
border: none;
border-radius: 50%;
background: rgba(17, 24, 39, 0.72);
color: #fff;
font-size: 12px;
line-height: 1;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.55);
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
opacity: 0;
transition: opacity 0.2s ease;
}
.phone-form-dialog__image-item:hover .phone-form-dialog__image-overlay {
opacity: 1;
}
.phone-form-dialog__image-preview-btn,
.phone-form-dialog__image-remove {
padding: 3px 8px;
border: none;
border-radius: 4px;
background: rgba(255, 255, 255, 0.92);
color: #1f2937;
font-size: 11px;
cursor: pointer;
transition: background 0.15s ease;
}
.phone-form-dialog__image-preview-btn:hover,
.phone-form-dialog__image-remove:hover {
background: rgba(17, 24, 39, 0.92);
background: #fff;
}
.phone-form-dialog__image-empty {
width: 64px;
height: 64px;
border-radius: 6px;
width: 150px;
height: 84px;
border-radius: 8px;
border: 1px dashed #d1d5db;
background: #fff;
background: #fafafa;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #c0c4cc;
font-size: 12px;
cursor: default;
gap: 4px;
cursor: pointer;
user-select: none;
transition: border-color 0.2s ease, background 0.2s ease;
}
/* Footer: right-aligned action buttons */
.phone-form-dialog__image-empty:hover {
border-color: #2563eb;
background: #eff6ff;
}
.phone-form-dialog__image-empty-text {
font-size: 12px;
color: #9ca3af;
font-weight: 500;
}
.phone-form-dialog__image-empty-divider {
font-size: 12px;
color: #d1d5db;
}
.phone-form-dialog__image-hint {
margin-top: 8px;
font-size: 12px;
color: #9ca3af;
}
/* ===== Footer ===== */
.phone-form-dialog__footer {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 12px;
}
/* Cancel button: subtle */
.phone-form-dialog__footer .el-button:not(.phone-form-dialog__submit-btn) {
height: 36px;
padding: 0 18px;
border-radius: 6px;
border-color: #e5e7eb;
color: #6b7280;
font-weight: 500;
}
.phone-form-dialog__footer .el-button:not(.phone-form-dialog__submit-btn):hover {
border-color: #d1d5db;
color: #374151;
background: #f9fafb;
}
/* Submit button: enhanced prominence */
.phone-form-dialog__submit-btn {
height: 36px !important;
padding: 0 28px !important;
font-size: 14px !important;
font-weight: 600 !important;
border-radius: 6px !important;
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%) !important;
border: none !important;
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3) !important;
transition: all 0.2s ease !important;
}
.phone-form-dialog__submit-btn:hover {
background: linear-gradient(135deg, #1d4ed8 0%, #1e40af 100%) !important;
box-shadow: 0 4px 14px rgba(37, 99, 235, 0.4) !important;
transform: translateY(-1px) !important;
}
.phone-form-dialog__submit-btn:active {
transform: translateY(0) !important;
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.3) !important;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment