Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xyw_asset_console
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DaiJiezhang
xyw_asset_console
Commits
755bba6d
Commit
755bba6d
authored
Jul 07, 2026
by
DaiJiezhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refine phone image handling flow
parent
1b367d0d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
137 additions
and
72 deletions
+137
-72
WxPhoneEntity.java
...main/java/com/xyw/console/phone/entity/WxPhoneEntity.java
+3
-2
WxPhoneMapper.java
...main/java/com/xyw/console/phone/mapper/WxPhoneMapper.java
+12
-0
WxPhoneService.java
...in/java/com/xyw/console/phone/service/WxPhoneService.java
+35
-2
index.html
index.html
+4
-4
phone-image-cell.js
src/modules/phone/phone-image-cell.js
+30
-61
phone-list-runtime.js
src/modules/phone/phone-list-runtime.js
+0
-0
phone-api-client.js
src/modules/shared/phone-api-client.js
+9
-2
styles-v2.css
styles-v2.css
+44
-1
No files found.
backend/src/main/java/com/xyw/console/phone/entity/WxPhoneEntity.java
View file @
755bba6d
package
com
.
xyw
.
console
.
phone
.
entity
;
import
com.baomidou.mybatisplus.annotation.FieldStrategy
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
...
...
@@ -25,10 +26,10 @@ public class WxPhoneEntity {
@TableField
(
"city"
)
private
String
city
;
@TableField
(
"image_attachment_1"
)
@TableField
(
value
=
"image_attachment_1"
,
updateStrategy
=
FieldStrategy
.
ALWAYS
)
private
String
imageAttachment1
;
@TableField
(
"image_attachment_2"
)
@TableField
(
value
=
"image_attachment_2"
,
updateStrategy
=
FieldStrategy
.
ALWAYS
)
private
String
imageAttachment2
;
@TableField
(
"card_status"
)
...
...
backend/src/main/java/com/xyw/console/phone/mapper/WxPhoneMapper.java
View file @
755bba6d
...
...
@@ -2,6 +2,18 @@ package com.xyw.console.phone.mapper;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.xyw.console.phone.entity.WxPhoneEntity
;
import
org.apache.ibatis.annotations.Param
;
import
org.apache.ibatis.annotations.Update
;
public
interface
WxPhoneMapper
extends
BaseMapper
<
WxPhoneEntity
>
{
/**
* 显式更新图片字段,确保 null 值能写入 DB。
* FieldStrategy.ALWAYS 在自定义 SqlSessionFactory 下可能不生效,
* 这里用原生 SQL 绕过,保证删除图片时字段被置为 NULL。
*/
@Update
(
"UPDATE wx_phone SET image_attachment_1 = #{imageAttachment1}, image_attachment_2 = #{imageAttachment2} WHERE id = #{id}"
)
int
updateImages
(
@Param
(
"id"
)
Long
id
,
@Param
(
"imageAttachment1"
)
String
imageAttachment1
,
@Param
(
"imageAttachment2"
)
String
imageAttachment2
);
}
backend/src/main/java/com/xyw/console/phone/service/WxPhoneService.java
View file @
755bba6d
...
...
@@ -6,8 +6,10 @@ import com.xyw.console.phone.entity.WxPhoneEntity;
import
com.xyw.console.phone.mapper.WxPhoneMapper
;
import
java.util.List
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
@Slf4j
@Service
@RequiredArgsConstructor
public
class
WxPhoneService
{
...
...
@@ -41,13 +43,44 @@ public class WxPhoneService {
/**
* 浠g爜浣滅敤锛堢櫧璇濓級锛氭洿鏂版寚瀹氭墜鏈哄彿鍗★紝骞舵妸鏁版嵁搴撻噷鐨勬渶鏂拌褰曡繑鍥炵粰鍓嶇銆? * 鍏宠仈鏂囦欢锛欶:/Project/xyw_console/backend/src/main/java/com/xyw/console/phone/controller/WxPhoneController.java銆丗:/Project/xyw_console/src/modules/phone/phone-add-dialog.js銆? * 鍏宠仈閫昏緫锛堣皟鐢ㄩ摼/娑堟伅閾?鏁版嵁娴侊級锛歅UT /api/wx-phones/{id} -> updateRecord() -> Mapper.updateById() -> 鍓嶇鍒锋柊鍒楄〃銆? */
public
WxPhoneEntity
updateRecord
(
Long
id
,
WxPhoneSaveRequest
request
)
{
log
.
info
(
"更新请求:id={}, request.imageAttachment1={}, request.imageAttachment2={}"
,
id
,
request
.
getImageAttachment1
()
==
null
?
"null"
:
"长度="
+
request
.
getImageAttachment1
().
length
(),
request
.
getImageAttachment2
()
==
null
?
"null"
:
"长度="
+
request
.
getImageAttachment2
().
length
());
WxPhoneEntity
entity
=
wxPhoneMapper
.
selectById
(
id
);
if
(
entity
==
null
)
{
log
.
warn
(
"更新手机号卡失败:未找到 id={}"
,
id
);
return
null
;
}
String
oldImage1
=
entity
.
getImageAttachment1
();
String
oldImage2
=
entity
.
getImageAttachment2
();
copyRequestToEntity
(
request
,
entity
);
wxPhoneMapper
.
updateById
(
entity
);
return
normalizeEntity
(
wxPhoneMapper
.
selectById
(
id
));
String
newImage1
=
entity
.
getImageAttachment1
();
String
newImage2
=
entity
.
getImageAttachment2
();
log
.
info
(
"复制后:id={}, entity.imageAttachment1={}, entity.imageAttachment2={}"
,
id
,
newImage1
==
null
?
"null"
:
"长度="
+
newImage1
.
length
(),
newImage2
==
null
?
"null"
:
"长度="
+
newImage2
.
length
());
if
(
oldImage1
!=
null
&&
newImage1
==
null
)
{
log
.
info
(
"删除图片:id={}, 字段=image_attachment_1, 旧值长度={}"
,
id
,
oldImage1
.
length
());
}
if
(
oldImage2
!=
null
&&
newImage2
==
null
)
{
log
.
info
(
"删除图片:id={}, 字段=image_attachment_2, 旧值长度={}"
,
id
,
oldImage2
.
length
());
}
int
updatedRows
=
wxPhoneMapper
.
updateById
(
entity
);
log
.
info
(
"updateById 返回行数={}, id={}"
,
updatedRows
,
id
);
// 显式更新图片字段,绕过 FieldStrategy.ALWAYS 可能不生效的问题,确保 null 值写入 DB
int
imageRows
=
wxPhoneMapper
.
updateImages
(
id
,
newImage1
,
newImage2
);
log
.
info
(
"updateImages 返回行数={}, id={}, image1={}, image2={}"
,
imageRows
,
id
,
newImage1
==
null
?
"null"
:
"长度="
+
newImage1
.
length
(),
newImage2
==
null
?
"null"
:
"长度="
+
newImage2
.
length
());
WxPhoneEntity
updated
=
wxPhoneMapper
.
selectById
(
id
);
log
.
info
(
"更新完成:id={}, image_attachment_1={}, image_attachment_2={}"
,
id
,
updated
.
getImageAttachment1
()
!=
null
?
"存在(长度="
+
updated
.
getImageAttachment1
().
length
()
+
")"
:
"null"
,
updated
.
getImageAttachment2
()
!=
null
?
"存在(长度="
+
updated
.
getImageAttachment2
().
length
()
+
")"
:
"null"
);
return
normalizeEntity
(
updated
);
}
/**
...
...
index.html
View file @
755bba6d
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"zh-CN"
>
<head>
...
...
@@ -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"
/>
<link
rel=
"stylesheet"
href=
"styles-v2.css
?v=20260707
"
/>
</head>
<body>
...
...
@@ -91,8 +91,8 @@
<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-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-image-cell.js
?v=20260707
"
></script>
<script
src=
"src/modules/phone/phone-list-runtime.js
?v=20260707
"
></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/phone-api-client.js"
></script>
...
...
src/modules/phone/phone-image-cell.js
View file @
755bba6d
(
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
;
}
if
(
!
image
)
{
return
;
}
image
.
style
.
display
=
'none'
;
const
placeholder
=
image
.
nextElementSibling
;
if
(
placeholder
)
{
placeholder
.
style
.
display
=
'flex'
;
}
if
(
placeholder
)
{
placeholder
.
style
.
display
=
'flex'
;
}
}
const
PhoneCardImageCell
=
{
...
...
@@ -21,76 +14,52 @@
props
:
{
images
:
{
type
:
Array
,
default
:
()
=>
[]
},
recordId
:
{
type
:
[
String
,
Number
],
default
:
null
},
clearImage
:
{
type
:
Function
,
default
:
null
}
clearImage
:
{
type
:
Function
,
default
:
null
},
uploadImage
:
{
type
:
Function
,
default
:
null
}
},
setup
(
props
)
{
const
previewVisible
=
ref
(
false
);
const
previewIndex
=
ref
(
0
);
const
imageInputRef
=
ref
(
null
);
const
uploading
=
ref
(
false
);
function
openPreview
(
index
)
{
previewIndex
.
value
=
index
;
previewVisible
.
value
=
true
;
}
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
);
}
}
function
closePreview
()
{
previewVisible
.
value
=
false
;
function
triggerUpload
()
{
if
(
uploading
.
value
)
{
return
;
}
if
(
typeof
props
.
uploadImage
!==
'function'
)
{
return
;
}
imageInputRef
.
value
?.
click
();
}
function
handleDelete
(
index
)
{
if
(
typeof
props
.
clearImage
===
'function'
)
{
props
.
clearImage
(
index
);
}
async
function
handleFileChange
(
event
)
{
const
input
=
event
?.
target
;
const
files
=
Array
.
from
(
input
?.
files
||
[]);
if
(
!
files
.
length
)
{
if
(
input
)
{
input
.
value
=
''
;
}
return
;
}
uploading
.
value
=
true
;
try
{
await
props
.
uploadImage
(
files
);
}
finally
{
uploading
.
value
=
false
;
if
(
input
)
{
input
.
value
=
''
;
}
}
}
return
{
previewVisible
,
previewIndex
,
openPreview
,
closePreview
,
handleDelete
,
handleImageError
};
return
{
previewVisible
,
previewIndex
,
imageInputRef
,
openPreview
,
closePreview
,
handleDelete
,
handleImageError
,
triggerUpload
,
handleFileChange
};
},
template
:
`
<div class="phone-image-cell">
<div class="phone-image-cell" @click.stop @mousedown.stop @dblclick.stop>
<input ref="imageInputRef" type="file" accept="image/*" multiple class="phone-image-input" @change="handleFileChange" style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;" />
<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 v-for="(image, index) in images" :key="(recordId ?? 'row') + '-img-' + index" class="phone-image-thumb" @click.stop @mousedown.stop @dblclick.stop>
<img :src="image" alt="thumbnail" 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>
<button type="button" class="phone-image-action phone-image-action--preview" title="预览" @click.stop="openPreview(index)" @mousedown.stop @dblclick.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 @dblclick.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 v-else class="phone-image-thumb phone-image-thumb--empty"
title="双击上传" @dblclick.stop="triggerUpload" @mousedown.stop @click.stop
>
<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"
/>
<el-image-viewer v-if="previewVisible" :url-list="images" :initial-index="previewIndex" :z-index="3000" :hide-on-click-modal="true" teleported @close="closePreview" />
</div>
`
};
...
...
src/modules/phone/phone-list-runtime.js
View file @
755bba6d
This diff is collapsed.
Click to expand it.
src/modules/shared/phone-api-client.js
View file @
755bba6d
(
function
attachPhoneApiClient
()
{
(
function
attachPhoneApiClient
()
{
const
BASE_URL
=
'http://localhost:8080/api/wx-phones'
;
/**
...
...
@@ -50,12 +50,19 @@
const
payload
=
{
...
record
};
const
isEdit
=
Boolean
(
payload
.
id
);
const
targetUrl
=
isEdit
?
`
${
BASE_URL
}
/
${
payload
.
id
}
`
:
BASE_URL
;
console
.
info
(
'[phone-api] savePhone 请求:id='
,
payload
.
id
,
'imageAttachment1 长度='
,
(
payload
.
imageAttachment1
||
''
).
length
,
'imageAttachment2 长度='
,
(
payload
.
imageAttachment2
||
''
).
length
);
const
json
=
await
requestJson
(
targetUrl
,
{
method
:
isEdit
?
'PUT'
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
},
body
:
JSON
.
stringify
(
payload
)
},
'手机号保存失败,请确认本地后端已启动'
);
return
json
.
data
||
json
;
const
data
=
json
.
data
||
json
;
console
.
info
(
'[phone-api] savePhone 响应:id='
,
payload
.
id
,
'imageAttachment1 长度='
,
(
data
?.
imageAttachment1
||
data
?.
image_attachment_1
||
''
).
length
,
'imageAttachment2 长度='
,
(
data
?.
imageAttachment2
||
data
?.
image_attachment_2
||
''
).
length
);
return
data
;
}
/**
...
...
styles-v2.css
View file @
755bba6d
...
...
@@ -1274,10 +1274,14 @@
width
:
100%
;
height
:
100%
;
font-size
:
11px
;
color
:
#
94a3b8
;
color
:
#
BBBFCF
!important
;
background
:
#f8fafc
;
}
.phone-table-header-nowrap
span
[
title
=
"双击编辑"
]
{
color
:
#BBBFCF
!important
;
}
.phone-image-thumb--empty
.phone-image-fallback
{
display
:
flex
;
}
...
...
@@ -1329,3 +1333,42 @@
color
:
#ef4444
;
background
:
rgba
(
255
,
255
,
255
,
0.18
);
}
/* Hidden file input used by the phone image cell for double-click upload */
.phone-image-input
{
display
:
none
;
}
/* Empty placeholder: hint interactivity on hover and double-click */
.phone-image-thumb--empty
{
cursor
:
pointer
;
user-select
:
none
;
}
.phone-image-thumb--empty
:hover
{
border-color
:
#BBBFCF
;
background
:
linear-gradient
(
135deg
,
#f1f5f9
0%
,
#e2e8f0
100%
);
}
/* Inline edit cell: input/select used when double-clicking an editable table cell */
.phone-inline-edit-cell
{
width
:
100%
;
min-width
:
80px
;
}
.phone-inline-edit-cell
.el-input__wrapper
,
.phone-inline-edit-cell
.el-select
.el-input__wrapper
{
border-color
:
#BBBFCF
!important
;
box-shadow
:
none
!important
;
background
:
#ffffff
;
}
.phone-inline-edit-cell
.el-input__wrapper
:hover
,
.phone-inline-edit-cell
.el-select
.el-input__wrapper
:hover
{
border-color
:
#9ca3af
!important
;
}
.phone-inline-edit-cell
.el-input__inner
{
font-size
:
13px
;
color
:
#111827
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment