Commit 1b367d0d by DaiJiezhang

Refine phone list workspace

parent 00d54727
...@@ -539,6 +539,7 @@ function renderExternalRuntime(moduleKey) { ...@@ -539,6 +539,7 @@ function renderExternalRuntime(moduleKey) {
globalState: state, globalState: state,
loadPhoneRows, loadPhoneRows,
deletePhoneRecord, deletePhoneRecord,
savePhoneRecord,
openAddDialog: (mode, record) => { openAddDialog: (mode, record) => {
window.PhoneAddDialogAPI?.open?.(mode, record); window.PhoneAddDialogAPI?.open?.(mode, record);
}, },
......
...@@ -72,4 +72,17 @@ public class PhoneMybatisConfig { ...@@ -72,4 +72,17 @@ public class PhoneMybatisConfig {
public SqlSessionTemplate phoneSqlSessionTemplate(@Qualifier("phoneSqlSessionFactory") SqlSessionFactory phoneSqlSessionFactory) { public SqlSessionTemplate phoneSqlSessionTemplate(@Qualifier("phoneSqlSessionFactory") SqlSessionFactory phoneSqlSessionFactory) {
return new SqlSessionTemplate(phoneSqlSessionFactory); return new SqlSessionTemplate(phoneSqlSessionFactory);
} }
@Bean
public org.springframework.boot.ApplicationRunner phoneDatabaseInitializer(@Qualifier("phoneDataSource") DataSource phoneDataSource) {
return args -> {
try (java.sql.Connection conn = phoneDataSource.getConnection();
java.sql.Statement stmt = conn.createStatement()) {
stmt.execute("ALTER TABLE wx_phone MODIFY COLUMN image_attachment_1 LONGTEXT");
stmt.execute("ALTER TABLE wx_phone MODIFY COLUMN image_attachment_2 LONGTEXT");
} catch (Exception e) {
e.printStackTrace();
}
};
}
} }
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
<script src="src/modules/wechat/wechat-list-runtime.js"></script> <script src="src/modules/wechat/wechat-list-runtime.js"></script>
<script src="src/modules/phone/phone-add-dialog.js"></script> <script src="src/modules/phone/phone-add-dialog.js"></script>
<script src="src/modules/phone/phone-detail-drawer.js"></script> <script src="src/modules/phone/phone-detail-drawer.js"></script>
<script src="src/modules/phone/phone-image-cell.js"></script>
<script src="src/modules/phone/phone-list-runtime.js"></script> <script src="src/modules/phone/phone-list-runtime.js"></script>
<script src="src/modules/shared/record-adapters.js"></script> <script src="src/modules/shared/record-adapters.js"></script>
<script src="src/modules/shared/wechat-api-client.js"></script> <script src="src/modules/shared/wechat-api-client.js"></script>
......
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
<el-option label="中国联通" value="中国联通"></el-option> <el-option label="中国联通" value="中国联通"></el-option>
<el-option label="中国电信" value="中国电信"></el-option> <el-option label="中国电信" value="中国电信"></el-option>
<el-option label="中国广电" value="中国广电"></el-option> <el-option label="中国广电" value="中国广电"></el-option>
<el-option label="虚商" value="虚商"></el-option> <el-option label="亮哥渠道(虚拟)" value="亮哥渠道(虚拟)"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
......
(function attachPhoneImageCell() {
const { ref } = window.Vue;
/**
* 代码作用(白话):手机号卡列表图片列的图片单元组件,负责缩略图展示、占位图回退、预览与删除悬浮操作;关联文件:F:/Project/xyw_console/src/modules/phone/phone-list-runtime.js;关联逻辑(调用链/消息链/数据流):PhoneListTable 图片列 -> <phone-card-image-cell> -> 预览/删除回调 -> 列表刷新。
*/
function handleImageError(event) {
const image = event?.target;
if (!image) {
return;
}
image.style.display = 'none';
const placeholder = image.nextElementSibling;
if (placeholder) {
placeholder.style.display = 'flex';
}
}
const PhoneCardImageCell = {
name: 'PhoneCardImageCell',
props: {
images: { type: Array, default: () => [] },
recordId: { type: [String, Number], default: null },
clearImage: { type: Function, default: null }
},
setup(props) {
const previewVisible = ref(false);
const previewIndex = ref(0);
function openPreview(index) {
previewIndex.value = index;
previewVisible.value = true;
}
function closePreview() {
previewVisible.value = false;
}
function handleDelete(index) {
if (typeof props.clearImage === 'function') {
props.clearImage(index);
}
}
return {
previewVisible,
previewIndex,
openPreview,
closePreview,
handleDelete,
handleImageError
};
},
template: `
<div class="phone-image-cell">
<template v-if="images && images.length">
<div
v-for="(image, index) in images"
:key="(recordId ?? 'row') + '-img-' + index"
class="phone-image-thumb"
>
<img :src="image" alt="号卡图片缩略图" class="phone-image-img" @error="handleImageError" />
<div class="phone-image-fallback">占位图</div>
<div class="phone-image-actions" @click.stop @mousedown.stop @dblclick.stop>
<button
type="button"
class="phone-image-action phone-image-action--preview"
title="预览图片"
@click.stop="openPreview(index)"
@mousedown.stop
><svg viewBox="0 0 1024 1024" width="16" height="16"><path fill="currentColor" d="M515.2 224c-307.2 0-492.8 313.6-492.8 313.6s214.4 304 492.8 304 492.8-304 492.8-304S822.4 224 515.2 224zM832 652.8c-102.4 86.4-211.2 140.8-320 140.8s-217.6-51.2-320-140.8c-35.2-32-70.4-64-99.2-99.2-6.4-6.4-9.6-12.8-16-19.2 3.2-6.4 9.6-12.8 12.8-19.2 25.6-35.2 57.6-70.4 92.8-102.4 99.2-89.6 208-144 329.6-144s230.4 54.4 329.6 144c35.2 32 64 67.2 92.8 102.4 3.2 6.4 9.6 12.8 12.8 19.2-3.2 6.4-9.6 12.8-16 19.2C902.4 585.6 870.4 620.8 832 652.8z"/><path fill="currentColor" d="M512 345.6c-96 0-169.6 76.8-169.6 169.6 0 96 76.8 169.6 169.6 169.6 96 0 169.6-76.8 169.6-169.6C681.6 422.4 604.8 345.6 512 345.6zM512 640c-67.2 0-121.6-54.4-121.6-121.6 0-67.2 54.4-121.6 121.6-121.6 67.2 0 121.6 54.4 121.6 121.6C633.6 582.4 579.2 640 512 640z"/></svg></button>
<button
type="button"
class="phone-image-action phone-image-action--delete"
title="删除图片"
@click.stop="handleDelete(index)"
@mousedown.stop
><svg viewBox="0 0 1024 1024" width="16" height="16"><path fill="currentColor" d="M709.469091 209.454545H930.909091a34.909091 34.909091 0 0 1 0 69.818182h-81.454546v607.185455c0 56.366545-44.311273 102.632727-99.746909 102.632727H274.292364c-55.435636 0-99.746909-46.266182-99.746909-102.632727V279.272727H93.090909a34.909091 34.909091 0 0 1 0-69.818182h244.712727a186.181818 186.181818 0 0 1 371.665455 0z m-70.050909 0a116.363636 116.363636 0 0 0-231.563637 0h231.563637z m140.218182 69.818182h-535.272728v607.185455c0 18.455273 13.730909 32.814545 29.928728 32.814545h475.415272c16.174545 0 29.928727-14.359273 29.928728-32.814545V279.272727z m-418.909091 147.2a34.909091 34.909091 0 0 1 69.818182 0v338.897455a34.909091 34.909091 0 0 1-69.818182 0V426.472727z m232.727272 0a34.909091 34.909091 0 0 1 69.818182 0v338.897455a34.909091 34.909091 0 0 1-69.818182 0V426.472727z"/></svg></button>
</div>
</div>
</template>
<div v-else class="phone-image-thumb phone-image-thumb--empty">
<span class="phone-image-fallback">占位图</span>
</div>
<el-image-viewer
v-if="previewVisible"
:url-list="images"
:initial-index="previewIndex"
:z-index="3000"
:hide-on-click-modal="true"
teleported
@close="closePreview"
/>
</div>
`
};
window.PhoneCardImageCell = PhoneCardImageCell;
})();
/* Import original styles first */ /* Import original styles first */
@import url('styles.css'); @import url('styles.css');
/* Overrides for right side replication */ /* Overrides for right side replication */
...@@ -1229,3 +1229,103 @@ ...@@ -1229,3 +1229,103 @@
.phone-date-range .el-range-separator { .phone-date-range .el-range-separator {
padding: 0 2px !important; padding: 0 2px !important;
} }
.phone-table-header-nowrap .cell {
white-space: nowrap !important;
text-overflow: clip !important;
padding: 0 8px !important;
}
/* Phone card image column cell: thumbnail + hover preview/delete actions */
.phone-image-cell {
display: flex;
gap: 8px;
align-items: center;
min-height: 52px;
}
.phone-image-thumb {
position: relative;
width: 52px;
height: 52px;
border-radius: 10px;
overflow: hidden;
border: 1px solid #e5e7eb;
background: #f8fafc;
flex: 0 0 auto;
}
.phone-image-thumb--empty {
border: 1px dashed #cbd5e1;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
}
.phone-image-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.phone-image-fallback {
display: none;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 11px;
color: #94a3b8;
background: #f8fafc;
}
.phone-image-thumb--empty .phone-image-fallback {
display: flex;
}
.phone-image-actions {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
background: rgba(17, 24, 39, 0.5);
opacity: 0;
transition: opacity 0.18s ease;
}
.phone-image-thumb:hover .phone-image-actions {
opacity: 1;
}
.phone-image-action {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
padding: 0;
border: none;
border-radius: 6px;
background: transparent;
color: #bfbfbf;
cursor: pointer;
line-height: 1;
transition: color 0.15s ease, background 0.15s ease;
}
.phone-image-action svg {
width: 16px;
height: 16px;
display: block;
}
.phone-image-action--preview:hover {
color: #2563eb;
background: rgba(255, 255, 255, 0.18);
}
.phone-image-action--delete:hover {
color: #ef4444;
background: rgba(255, 255, 255, 0.18);
}
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