Commit 80886283 by DaiJiezhang

Refine phone dialog and styles

parent 4fa4ae75
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<title>学有为资产管理台</title> <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="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="node_modules/element-plus/dist/index.css" />
<link rel="stylesheet" href="styles-v2.css?v=20260707" /> <link rel="stylesheet" href="styles-v2.css?v=20260708b" />
</head> </head>
<body> <body>
......
(function initPhoneAddDialog() { (function initPhoneAddDialog() {
const { createApp, ref, reactive } = window.Vue; const { createApp, ref, reactive } = window.Vue;
const ElementPlus = window.ElementPlus; const ElementPlus = window.ElementPlus;
...@@ -256,14 +256,15 @@ ...@@ -256,14 +256,15 @@
}; };
}, },
template: ` template: `
<el-dialog v-model="visible" width="760px" top="8vh"> <el-dialog v-model="visible" width="640px" top="6vh" custom-class="phone-form-dialog">
<template #header> <template #header>
<div style="font-size: 18px; font-weight: bold; color: #303133;"> <div class="phone-form-dialog__title">
{{ isEdit ? '编辑手机号卡' : '新增手机号卡' }} {{ isEdit ? '编辑手机号卡' : '新增手机号卡' }}
</div> </div>
</template> </template>
<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px" label-position="right"> <el-form :model="formData" :rules="rules" ref="formRef" label-width="120px" label-position="right" class="phone-form-dialog__form">
<div style="font-size: 15px; font-weight: 600; color: #303133; margin: 0 0 16px 0; line-height: 1;">基础信息</div> <div class="phone-form-dialog__section">
<div class="phone-form-dialog__section-title">基础信息</div>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="手机号" prop="phoneNumber"> <el-form-item label="手机号" prop="phoneNumber">
...@@ -306,30 +307,30 @@ ...@@ -306,30 +307,30 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="图片字段"> <el-form-item label="图片字段">
<div style="width: 100%; display: flex; flex-direction: column; gap: 12px;"> <div class="phone-form-dialog__image-block">
<input ref="imageInputRef" type="file" accept="image/*" multiple style="display: none;" @change="handleImageFileChange" /> <input ref="imageInputRef" type="file" accept="image/*" multiple style="display: none;" @change="handleImageFileChange" />
<div style="display: flex; align-items: center; gap: 12px; flex-wrap: wrap;"> <div class="phone-form-dialog__image-toolbar">
<el-button type="primary" plain @click="triggerImageSelect">选择图片</el-button> <el-button type="primary" plain @click="triggerImageSelect">选择图片</el-button>
<span style="font-size: 12px; color: #6b7280;">一个图片字段区域内最多展示 2 张图,保存时会拆回两个 SQL 字段。</span> <span class="phone-form-dialog__image-hint">最多上传 2 张图片,保存时拆分写入两个图片字段。</span>
</div> </div>
<div style="display: flex; gap: 12px; flex-wrap: wrap; min-height: 104px;"> <div class="phone-form-dialog__image-list">
<div v-for="(image, index) in imageItems" :key="image.id" style="position: relative; width: 104px; height: 104px; border-radius: 12px; overflow: hidden; border: 1px solid #e5e7eb; background: #f8fafc;"> <div v-for="(image, index) in imageItems" :key="image.id" class="phone-form-dialog__image-item">
<img :src="image.url" :alt="image.name" style="width: 100%; height: 100%; object-fit: cover; display: block;" /> <img :src="image.url" :alt="image.name" class="phone-form-dialog__image-img" />
<button type="button" @click="removeImage(index)" style="position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border: none; border-radius: 999px; background: rgba(17, 24, 39, 0.72); color: #ffffff; cursor: pointer; line-height: 1;">x</button> <button type="button" class="phone-form-dialog__image-remove" @click="removeImage(index)">×</button>
</div> </div>
<div v-if="!imageItems.length" style="width: 104px; height: 104px; border-radius: 12px; border: 1px dashed #cbd5e1; background: #f8fafc; display: flex; align-items: center; justify-content: center; color: #94a3b8; font-size: 12px; text-align: center; padding: 8px;">暂无图片<br/>占位图</div> <div v-if="!imageItems.length" class="phone-form-dialog__image-empty" @click="triggerImageSelect">双击上传</div>
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</div>
<el-divider border-style="dashed" style="margin: 16px 0;"></el-divider> <div class="phone-form-dialog__section">
<div style="font-size: 15px; font-weight: 600; color: #303133; margin: 0 0 16px 0; line-height: 1;">状态与保留</div> <div class="phone-form-dialog__section-title">状态与保留</div>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="号卡状态" prop="cardStatus"> <el-form-item label="号卡状态" prop="cardStatus">
...@@ -342,34 +343,60 @@ ...@@ -342,34 +343,60 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="号码状态" prop="numberStatus"> <el-form-item label="号码状态" prop="numberStatus">
<el-switch v-model="formData.numberStatus" active-text="正常" inactive-text="异常"></el-switch> <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-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="12">
<el-form-item label="可变更 5 元套餐" prop="packageChange5yuan"> <el-form-item label="可变更 5 元套餐" prop="packageChange5yuan">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.packageChange5yuan"></el-switch> <el-switch v-model="formData.packageChange5yuan"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.packageChange5yuan }">当前:{{ formData.packageChange5yuan ? '可变更' : '不可变更' }}</span>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</div>
<el-divider border-style="dashed" style="margin: 16px 0;"></el-divider> <div class="phone-form-dialog__section">
<div style="font-size: 15px; font-weight: 600; color: #303133; margin: 0 0 16px 0; line-height: 1;">生态账号绑定</div> <div class="phone-form-dialog__section-title">生态账号绑定</div>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="8"> <el-col :span="12">
<el-form-item label="开通微信" prop="wechat" label-width="90px"> <el-form-item label="开通微信" prop="wechat">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.wechat"></el-switch> <el-switch v-model="formData.wechat"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wechat }">当前:{{ formData.wechat ? '已开通' : '未开通' }}</span>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="12">
<el-form-item label="开通企业微信" prop="wecom" label-width="110px"> <el-form-item label="开通企业微信" prop="wecom">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.wecom"></el-switch> <el-switch v-model="formData.wecom"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.wecom }">当前:{{ formData.wecom ? '已开通' : '未开通' }}</span>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> </el-row>
<el-form-item label="可外呼" prop="outboundCall" label-width="80px"> <el-row :gutter="24">
<el-col :span="12">
<el-form-item label="可外呼" prop="outboundCall">
<div class="phone-form-dialog__switch">
<el-switch v-model="formData.outboundCall"></el-switch> <el-switch v-model="formData.outboundCall"></el-switch>
<span class="phone-form-dialog__switch-status" :class="{ 'is-on': formData.outboundCall }">当前:{{ formData.outboundCall ? '支持' : '不支持' }}</span>
</div>
</el-form-item>
</el-col>
<el-col :span="12">
<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>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
...@@ -385,19 +412,13 @@ ...@@ -385,19 +412,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24"> </div>
<el-col :span="12">
<el-form-item label="小程序备案" prop="miniProgramFiling">
<el-switch v-model="formData.miniProgramFiling" active-text="已备案" inactive-text="未备案"></el-switch>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <div class="phone-form-dialog__footer">
<el-button @click="close">取消</el-button> <el-button @click="close">取消</el-button>
<el-button type="primary" @click="handleSubmit">提交保存</el-button> <el-button type="primary" @click="handleSubmit">提交保存</el-button>
</span> </div>
</template> </template>
</el-dialog> </el-dialog>
` `
......
...@@ -1372,3 +1372,207 @@ ...@@ -1372,3 +1372,207 @@
font-size: 13px; font-size: 13px;
color: #111827; color: #111827;
} }
/* =========================================================
Phone Card Add/Edit Dialog
Fixed header / footer, scrollable body, compact layout.
Uses Element Plus components and project color tokens only.
========================================================= */
/* Dialog shell: flex column, max 80vh */
.phone-form-dialog {
max-height: 80vh;
display: flex;
flex-direction: column;
margin: var(--el-dialog-margin-top, 15vh) auto 50px;
overflow: hidden;
border-radius: 12px;
}
/* Header: fixed, compact */
.phone-form-dialog .el-dialog__header {
padding: 14px 20px 12px;
margin-right: 0;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
/* Body: scrollable middle area */
.phone-form-dialog .el-dialog__body {
padding: 16px 20px 8px;
flex: 1;
min-height: 0;
overflow-y: auto;
}
/* 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;
flex-shrink: 0;
}
.phone-form-dialog__title {
font-size: 16px;
font-weight: 600;
color: #1f2937;
line-height: 1.4;
}
/* Compact form-item vertical rhythm */
.phone-form-dialog__form .el-form-item {
margin-bottom: 14px;
}
.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__section {
margin-bottom: 18px;
}
.phone-form-dialog__section:last-child {
margin-bottom: 12px;
}
.phone-form-dialog__section-title {
position: relative;
padding-left: 10px;
margin-bottom: 14px;
font-size: 13px;
font-weight: 600;
color: #1f2937;
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;
background: #2563eb;
border-radius: 2px;
}
/* Switch field: toggle + trailing status text */
.phone-form-dialog__switch {
display: flex;
align-items: center;
gap: 8px;
height: 32px;
}
.phone-form-dialog__switch-status {
font-size: 12px;
color: #9ca3af;
line-height: 1.5;
white-space: nowrap;
transition: color 0.2s ease;
}
.phone-form-dialog__switch-status.is-on {
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 {
display: flex;
align-items: center;
gap: 10px;
}
.phone-form-dialog__image-hint {
font-size: 12px;
color: #9ca3af;
line-height: 1;
}
.phone-form-dialog__image-list {
display: flex;
gap: 8px;
flex-wrap: wrap;
min-height: 64px;
}
.phone-form-dialog__image-item {
position: relative;
width: 64px;
height: 64px;
border-radius: 6px;
overflow: hidden;
border: 1px solid #e5e7eb;
background: #fff;
flex: 0 0 auto;
}
.phone-form-dialog__image-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.phone-form-dialog__image-remove {
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;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s ease;
}
.phone-form-dialog__image-remove:hover {
background: rgba(17, 24, 39, 0.92);
}
.phone-form-dialog__image-empty {
width: 64px;
height: 64px;
border-radius: 6px;
border: 1px dashed #d1d5db;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
color: #c0c4cc;
font-size: 12px;
cursor: default;
user-select: none;
}
/* Footer: right-aligned action buttons */
.phone-form-dialog__footer {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 12px;
}
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