Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gk
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
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
micro_app
gk
Commits
d6457ba4
Commit
d6457ba4
authored
Jul 08, 2025
by
daniel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(feedback): feedback联调完成
parent
9b63338f
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
577 additions
and
131 deletions
+577
-131
FeedbackCategoryMapper.xml
...e/jadp/plugins/cmpt/dao/mapper/FeedbackCategoryMapper.xml
+4
-4
FeedbackMapper.xml
.../dlbridge/jadp/plugins/cmpt/dao/mapper/FeedbackMapper.xml
+10
-5
Feedback.java
...va/com/dlbridge/jadp/plugins/cmpt/dao/model/Feedback.java
+18
-1
FeedbackCategory.java
...lbridge/jadp/plugins/cmpt/dao/model/FeedbackCategory.java
+11
-0
FeedbackQueryDTO.java
.../com/dlbridge/jadp/plugins/cmpt/dto/FeedbackQueryDTO.java
+1
-0
feedback.jsp
src/main/webapp/WEB-INF/views/cmpt/feedback.jsp
+533
-121
No files found.
src/main/java/com/dlbridge/jadp/plugins/cmpt/dao/mapper/FeedbackCategoryMapper.xml
View file @
d6457ba4
...
@@ -30,9 +30,9 @@
...
@@ -30,9 +30,9 @@
WHERE id = #{id}
WHERE id = #{id}
</update>
</update>
<
dele
te
id=
"delete"
parameterType=
"java.lang.Integer"
>
<
upda
te
id=
"delete"
parameterType=
"java.lang.Integer"
>
DELETE FROM feedback_category
WHERE id = #{id}
UPDATE feedback_category SET del_flag = 1
WHERE id = #{id}
</
dele
te>
</
upda
te>
<select
id=
"selectById"
parameterType=
"java.lang.Integer"
resultType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.FeedbackCategory"
>
<select
id=
"selectById"
parameterType=
"java.lang.Integer"
resultType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.FeedbackCategory"
>
SELECT * FROM feedback_category WHERE id = #{id}
SELECT * FROM feedback_category WHERE id = #{id}
...
@@ -53,7 +53,7 @@
...
@@ -53,7 +53,7 @@
<if
test=
"isActive != null"
>
<if
test=
"isActive != null"
>
AND is_active = #{isActive}
AND is_active = #{isActive}
</if>
</if>
AND del_flag = 0
AND del_flag = 0
order by sort_order asc
</where>
</where>
</select>
</select>
...
...
src/main/java/com/dlbridge/jadp/plugins/cmpt/dao/mapper/FeedbackMapper.xml
View file @
d6457ba4
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.dlbridge.jadp.plugins.cmpt.dao.mapper.FeedbackMapper"
>
<mapper
namespace=
"com.dlbridge.jadp.plugins.cmpt.dao.mapper.FeedbackMapper"
>
<insert
id=
"insert"
parameterType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.Feedback"
>
<insert
id=
"insert"
parameterType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.Feedback"
>
INSERT INTO feedback (user_id, category_id, content, contact_info,
feedback_image_url, current_status, admin_notes, resolution_result,feedback_no
, resolve_image_url, del_flag,cmpt_id)
INSERT INTO feedback (user_id, category_id, content, contact_info,
feedback_no, feedback_image_url, current_status, admin_notes, resolution_result
, resolve_image_url, del_flag,cmpt_id)
VALUES (#{userId}, #{categoryId}, #{content}, #{contactInfo},#{feedbackNo}, #{feedbackImageUrl}, #{currentStatus}, #{adminNotes}, #{resolutionResult}, #{resolveImageUrl}, 0,#{cmptId})
VALUES (#{userId}, #{categoryId}, #{content}, #{contactInfo},#{feedbackNo}, #{feedbackImageUrl}, #{currentStatus}, #{adminNotes}, #{resolutionResult}, #{resolveImageUrl}, 0,#{cmptId})
</insert>
</insert>
...
@@ -36,6 +36,9 @@
...
@@ -36,6 +36,9 @@
<if
test=
"resolveImageUrl != null"
>
<if
test=
"resolveImageUrl != null"
>
resolve_image_url = #{resolveImageUrl},
resolve_image_url = #{resolveImageUrl},
</if>
</if>
<if
test=
"resolvedAt != null"
>
resolved_at = #{resolvedAt},
</if>
<if
test=
"delFlag != null"
>
<if
test=
"delFlag != null"
>
del_flag = #{delFlag}
del_flag = #{delFlag}
</if>
</if>
...
@@ -43,9 +46,11 @@
...
@@ -43,9 +46,11 @@
WHERE id = #{id}
WHERE id = #{id}
</update>
</update>
<delete
id=
"delete"
parameterType=
"java.lang.Integer"
>
<update
id=
"delete"
parameterType=
"java.lang.Integer"
>
DELETE FROM feedback WHERE id = #{id}
UPDATE feedback
</delete>
SET del_flag = 1
WHERE id = #{id}
</update>
<select
id=
"selectById"
parameterType=
"java.lang.Integer"
resultType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.Feedback"
>
<select
id=
"selectById"
parameterType=
"java.lang.Integer"
resultType=
"com.dlbridge.jadp.plugins.cmpt.dao.model.Feedback"
>
SELECT * FROM feedback WHERE id = #{id}
SELECT * FROM feedback WHERE id = #{id}
...
@@ -63,7 +68,7 @@
...
@@ -63,7 +68,7 @@
<if
test=
"categoryId != null"
>
<if
test=
"categoryId != null"
>
AND category_id = #{categoryId}
AND category_id = #{categoryId}
</if>
</if>
<if
test=
"feedbackNo != null"
>
<if
test=
"feedbackNo != null
and feedbackNo !=''
"
>
AND feedback_no = #{feedbackNo}
AND feedback_no = #{feedbackNo}
</if>
</if>
<if
test=
"currentStatus != null and currentStatus != ''"
>
<if
test=
"currentStatus != null and currentStatus != ''"
>
...
...
src/main/java/com/dlbridge/jadp/plugins/cmpt/dao/model/Feedback.java
View file @
d6457ba4
...
@@ -2,10 +2,13 @@ package com.dlbridge.jadp.plugins.cmpt.dao.model;
...
@@ -2,10 +2,13 @@ package com.dlbridge.jadp.plugins.cmpt.dao.model;
import
com.dlbridge.jadp.common.persistence.JaapRecord
;
import
com.dlbridge.jadp.common.persistence.JaapRecord
;
import
com.dlbridge.jadp.plugins.partner.bean.BagDelivery
;
import
com.dlbridge.jadp.plugins.partner.bean.BagDelivery
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
import
lombok.experimental.Accessors
;
import
org.springframework.format.annotation.DateTimeFormat
;
import
java.util.Date
;
import
java.util.Date
;
...
@@ -16,18 +19,32 @@ import java.util.Date;
...
@@ -16,18 +19,32 @@ import java.util.Date;
@Accessors
(
chain
=
true
)
@Accessors
(
chain
=
true
)
public
class
Feedback
extends
JaapRecord
<
BagDelivery
>
{
public
class
Feedback
extends
JaapRecord
<
BagDelivery
>
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
final
long
serialVersionUID
=
1L
;
@ApiModelProperty
(
value
=
"反馈编号,后台自主生成"
,
notes
=
"反馈编号,后台自主生成"
)
private
String
feedbackNo
;
// 反馈编号,后台自主生成
private
String
feedbackNo
;
// 反馈编号,后台自主生成
@ApiModelProperty
(
value
=
"用户ID"
,
notes
=
"用户ID"
)
private
Integer
userId
;
private
Integer
userId
;
@ApiModelProperty
(
value
=
"赛事ID"
,
notes
=
"赛事ID"
)
private
Integer
cmptId
;
// 赛事id
private
Integer
cmptId
;
// 赛事id
@ApiModelProperty
(
value
=
"反馈类别ID"
,
notes
=
"反馈类别ID"
)
private
Integer
categoryId
;
// 反馈类别ID
private
Integer
categoryId
;
// 反馈类别ID
@ApiModelProperty
(
value
=
"问题描述内容"
,
notes
=
"问题描述内容"
)
private
String
content
;
// 问题描述内容
private
String
content
;
// 问题描述内容
@ApiModelProperty
(
value
=
"联系方式(手机/邮箱"
,
notes
=
"联系方式(手机/邮箱"
)
private
String
contactInfo
;
// 联系方式(手机/邮箱
private
String
contactInfo
;
// 联系方式(手机/邮箱
@ApiModelProperty
(
value
=
"反馈图片URL,多张以逗号分隔"
,
notes
=
"反馈图片URL,多张以逗号分隔"
)
private
String
feedbackImageUrl
;
// 反馈图片URL,多张以逗号分隔
private
String
feedbackImageUrl
;
// 反馈图片URL,多张以逗号分隔
private
String
currentStatus
;
// 当前状态 'pending','processing','resolved'(待处理/处理中/已解决)
@ApiModelProperty
(
value
=
"当前状态0,1,2(待处理/处理中/已解决) 当前状态:待处理/处理中/已解决"
,
notes
=
"当前状态0,1,2(待处理/处理中/已解决) 当前状态:待处理/处理中/已解决"
)
private
Integer
currentStatus
;
// 当前状态0,1,2(待处理/处理中/已解决) 当前状态:待处理/处理中/已解决
@ApiModelProperty
(
value
=
"管理员备注"
,
notes
=
"管理员备注"
)
private
String
adminNotes
;
// 管理员备注
private
String
adminNotes
;
// 管理员备注
@ApiModelProperty
(
value
=
"解决结果"
,
notes
=
"解决结果"
)
private
String
resolutionResult
;
// 解决结果
private
String
resolutionResult
;
// 解决结果
@ApiModelProperty
(
value
=
"解决图片URL,多张以逗号分隔"
,
notes
=
"解决图片URL,多张以逗号分隔"
)
private
String
resolveImageUrl
;
// 解决图片URL,多张以逗号分隔
private
String
resolveImageUrl
;
// 解决图片URL,多张以逗号分隔
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
resolvedAt
;
// 解决时间
private
Date
resolvedAt
;
// 解决时间
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
createdAt
;
private
Date
createdAt
;
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
updatedAt
;
private
Date
updatedAt
;
}
}
src/main/java/com/dlbridge/jadp/plugins/cmpt/dao/model/FeedbackCategory.java
View file @
d6457ba4
...
@@ -4,7 +4,9 @@ package com.dlbridge.jadp.plugins.cmpt.dao.model;
...
@@ -4,7 +4,9 @@ package com.dlbridge.jadp.plugins.cmpt.dao.model;
import
com.dlbridge.jadp.common.persistence.JaapRecord
;
import
com.dlbridge.jadp.common.persistence.JaapRecord
;
import
com.dlbridge.jadp.plugins.partner.bean.BagDelivery
;
import
com.dlbridge.jadp.plugins.partner.bean.BagDelivery
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
import
lombok.experimental.Accessors
;
...
@@ -17,11 +19,20 @@ import java.util.Date;
...
@@ -17,11 +19,20 @@ import java.util.Date;
@Accessors
(
chain
=
true
)
@Accessors
(
chain
=
true
)
public
class
FeedbackCategory
extends
JaapRecord
<
BagDelivery
>
{
public
class
FeedbackCategory
extends
JaapRecord
<
BagDelivery
>
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
final
long
serialVersionUID
=
1L
;
@ApiModelProperty
(
value
=
"用户id"
,
notes
=
"用户id"
)
private
Integer
userId
;
private
Integer
userId
;
@ApiModelProperty
(
value
=
"赛事id"
,
notes
=
"赛事id"
)
private
Integer
cmptId
;
// 赛事id
private
Integer
cmptId
;
// 赛事id
@ApiModelProperty
(
value
=
"分类名称"
,
notes
=
"分类名称"
)
private
String
name
;
// 分类名称
private
String
name
;
// 分类名称
@ApiModelProperty
(
value
=
"排序顺序"
,
notes
=
"排序顺序"
)
private
Integer
sortOrder
;
// 排序顺序
private
Integer
sortOrder
;
// 排序顺序
@ApiModelProperty
(
value
=
"是否启用"
,
notes
=
"是否启用"
)
private
Integer
isActive
;
// 是否启用
private
Integer
isActive
;
// 是否启用
@ApiModelProperty
(
value
=
"创建时间"
,
notes
=
"创建时间"
)
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
private
Date
createdAt
;
private
Date
createdAt
;
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
@ApiModelProperty
(
value
=
"更新时间"
,
notes
=
"更新时间"
)
private
Date
updatedAt
;
private
Date
updatedAt
;
}
}
src/main/java/com/dlbridge/jadp/plugins/cmpt/dto/FeedbackQueryDTO.java
View file @
d6457ba4
...
@@ -10,4 +10,5 @@ public class FeedbackQueryDTO extends PageDTO {
...
@@ -10,4 +10,5 @@ public class FeedbackQueryDTO extends PageDTO {
private
Integer
categoryId
;
private
Integer
categoryId
;
private
Integer
cmptId
;
private
Integer
cmptId
;
private
String
currentStatus
;
private
String
currentStatus
;
private
String
feedbackNo
;
}
}
src/main/webapp/WEB-INF/views/cmpt/feedback.jsp
View file @
d6457ba4
...
@@ -82,7 +82,7 @@
...
@@ -82,7 +82,7 @@
<div
class=
"page-content d-flex align-items-stretch main-body"
>
<div
class=
"page-content d-flex align-items-stretch main-body"
>
<jsp:include
page=
"../common/menu.jsp"
></jsp:include>
<jsp:include
page=
"../common/menu.jsp"
></jsp:include>
<div
id=
"app"
class=
"flex-1"
v-cloak
>
<div
id=
"app"
class=
"flex-1"
v-cloak
>
<n-config-provider>
<n-config-provider
:locale=
"locale"
:date-locale=
"dateLocale"
>
<n-modal-provider>
<n-modal-provider>
<n-message-provider>
<n-message-provider>
<n-notification-provider>
<n-notification-provider>
...
@@ -94,42 +94,57 @@
...
@@ -94,42 +94,57 @@
</div>
</div>
</div>
</div>
<script
type=
"text/x-template"
id=
"my-app"
>
<script
type=
"text/x-template"
id=
"my-app"
>
<
n
-
space
vertical
>
<
n
-
space
vertical
>
<!--
顶部的搜索框
-->
<!--
顶部的搜索框
-->
<
n
-
card
:
bordered
=
"false"
>
<
n
-
card
:
bordered
=
"false"
>
<
div
class
=
"w-full flex flex-row items-center gap-x-2"
>
<
div
class
=
"w-full flex flex-row items-center gap-x-2"
>
<
div
style
=
"width: 200px"
>
<
div
style
=
"width: 200px"
>
<
n
-
tabs
type
=
"segment"
@
update
:
value
=
"updateStatus"
:
value
=
"status"
animated
pane
-
style
=
"padding:0;"
>
<
n
-
tabs
type
=
"segment"
@
update
:
value
=
"updateStatus"
:
value
=
"status"
animated
pane
-
style
=
"padding:0;"
>
<
n
-
tab
-
pane
v
-
for
=
"item in statusOptions
"
:
name
=
"item.value"
:
tab
=
"item.name"
><
/n-tab-pane
>
<
n
-
tab
-
pane
v
-
for
=
"item in [{name:'全部',value:''},...statusOptions]
"
:
name
=
"item.value"
:
tab
=
"item.name"
><
/n-tab-pane
>
<
/n-tabs
>
<
/n-tabs
>
<
/div
>
<
/div
>
<
div
class
=
"ml-auto"
><
n
-
input
placeholder
=
"请输入搜索内容"
/><
/div
>
<
div
class
=
"ml-auto"
><
n
-
input
placeholder
=
"请输入搜索内容"
/><
/div
>
<
n
-
button
type
=
"primary"
>
搜索
<
/n-button
>
<
n
-
button
type
=
"primary"
>
搜索
<
/n-button
>
<
n
-
button
type
=
"primary"
@
click
=
"addFeedBack"
>
新增测试
<
/n-button
>
<
/div
>
<
/div
>
<
/n-card
>
<
/n-card
>
<!--
搜索框
-->
<!--
搜索框
-->
<
div
class
=
"w-full flex flex-row items-start gap-x-3"
>
<
div
class
=
"w-full flex flex-row items-start gap-x-3"
>
<
div
class
=
"bg-white flex flex-col gap-y-2 p-3"
>
<
div
class
=
"bg-white flex flex-col gap-y-2 p-3"
>
<
h4
>
<
h4
class
=
"flex flex-row items-center justify-between w-full"
>
分类列表
分类列表
<
n
-
button
type
=
"primary"
@
click
=
"onEditCategory(null)"
size
=
"tiny"
>
<
n
-
button
type
=
"primary"
@
click
=
"onEditCategory(null)"
size
=
"tiny"
>
新增
新增
<
/n-button
>
<
/n-button
>
<
/h4
>
<
/h4
>
<
div
:
class
=
"[categoryIndex===index?'bg-primary text-white':'']"
v
-
for
=
"(item,index) in feedbackCategories"
:
key
=
"item.value"
class
=
"flex py-1 px-2
rounded-sm flex-row items-center gap-x-1"
>
<
div
v
-
for
=
"(item,index) in feedbackCategories"
:
key
=
"item.value"
class
=
"flex
rounded-sm flex-row items-center gap-x-1"
>
<
span
class
=
"flex-1"
@
click
=
"changeCategory(index)"
>
{{
item
.
name
}}
<
span
class
=
"py-1 px-4 rounded-sm animate-fade-in"
:
class
=
"[categoryIndex===index?'bg-primary text-white':'']"
class
=
"flex-1"
@
click
=
"changeCategory(index)"
>
{{
item
.
name
}}
<
/span
>
<
/span
>
<
n
-
tag
round
:
bordered
=
"false"
size
=
"small"
:
type
=
"item.isActive?'success':'error'"
class
=
"cursor-pointer"
>
{{
item
.
isActive
?
'开启'
:
'关闭'
}}
<
/n-tag
>
<
ion
-
icon
@
click
=
"onEditCategory(item)"
class
=
"cursor-pointer"
name
=
"create-outline"
><
/ion-icon
>
<
ion
-
icon
@
click
=
"onEditCategory(item)"
class
=
"cursor-pointer"
name
=
"create-outline"
><
/ion-icon
>
<
ion
-
icon
@
click
=
"onDelCategory"
class
=
"text-red cursor-pointer"
name
=
"trash-outline"
><
/ion-icon
>
<
n
-
popconfirm
@
positive
-
click
=
"onDelCategory(item)"
>
<
template
#
trigger
>
<
ion
-
icon
class
=
"text-red cursor-pointer"
name
=
"trash-outline"
><
/ion-icon
>
<
/template
>
是否删除该分类
<
/n-popconfirm
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"flex-1"
>
<
div
class
=
"flex-1"
>
<
n
-
data
-
table
:
columns
=
"columns"
:
data
=
"data
"
:
pagination
=
"pagination"
<
n
-
data
-
table
:
columns
=
"columns"
:
loading
=
"loading"
:
data
=
"feedbacks
"
:
pagination
=
"pagination"
:
bordered
=
"false"
/>
:
bordered
=
"false"
@
update
:
page
=
"handlePageChange"
/>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
n
-
modal
:
mask
-
closable
=
"false"
:
loading
=
"loading"
style
=
"width: 400px"
:
title
=
"categoryFormValue.id?'编辑分类':'新增分类'"
<
n
-
modal
:
loading
=
"loading"
style
=
"width: 400px"
:
title
=
"categoryFormValue.id?'编辑分类':'新增分类'"
preset
=
"card"
preset
=
"card"
draggable
v
-
model
:
show
=
"showCategoryModal"
>
draggable
v
-
model
:
show
=
"showCategoryModal"
>
...
@@ -164,22 +179,104 @@
...
@@ -164,22 +179,104 @@
<
/n-form
>
<
/n-form
>
<
template
#
footer
>
<
template
#
footer
>
<
div
class
=
"flex gap-x-2 flex-row items-center"
>
<
div
class
=
"flex gap-x-2 flex-row items-center"
>
<
n
-
button
:
loading
=
"loading"
class
=
"flex-1"
@
click
=
"onCategoryCancel"
>
<
n
-
button
class
=
"flex-1"
:
loading
=
"loading"
@
click
=
"onCategoryCancel"
>
取消
取消
<
/n-button
>
<
/n-button
>
<
n
-
button
:
loading
=
"loading"
class
=
"flex-1"
type
=
'primary'
@
click
=
"onCategorySubmit"
>
<
n
-
button
class
=
"flex-1"
:
loading
=
"loading"
type
=
'primary'
@
click
=
"onCategorySubmit"
>
保存
保存
<
/n-button
>
<
/n-button
>
<
/div
>
<
/div
>
<
/template
>
<
/template
>
<
/n-modal
>
<
/n-modal
>
<
/n-space
>
<
n
-
modal
:
mask
-
closable
=
"false"
:
loading
=
"loading"
style
=
"width: 600px"
:
title
=
"feedbackFormValue.id?'处理反馈':'新增反馈'"
preset
=
"card"
draggable
v
-
model
:
show
=
"showFeedbackModal"
>
<
n
-
form
ref
=
"feedbackFormRef"
:
model
=
"feedbackFormValue"
:
rules
=
"feedbackRules"
size
=
"small"
label
-
placement
=
"left"
label
-
width
=
"auto"
>
<
n
-
form
-
item
label
=
"反馈图片"
path
=
"feedbackImageUrl"
>
<
n
-
upload
:
action
=
"uploadUrl"
:
disabled
=
"true"
v
-
model
:
file
-
list
=
"fileList"
list
-
type
=
"image-card"
>
点击上传
<
/n-upload
>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"联系信息"
path
=
"contactInfo"
>
<
n
-
input
:
disabled
=
"true"
v
-
model
:
value
=
"feedbackFormValue.contactInfo"
placeholder
=
"请输入联系信息"
/>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"反馈内容"
path
=
"content"
>
<
n
-
input
:
disabled
=
"true"
type
=
"textarea"
v
-
model
:
value
=
"feedbackFormValue.content"
placeholder
=
"请输入反馈内容"
/>
<
/n-form-item
>
<!--
后台填写的内容
-->
<
n
-
form
-
item
label
=
"处理图片"
path
=
"resolveImageUrl"
>
<
n
-
upload
:
action
=
"uploadUrl"
v
-
model
:
file
-
list
=
"resultFileList"
list
-
type
=
"image-card"
@
finish
=
"uploadFinish"
>
点击上传
<
/n-upload
>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"处理结果"
path
=
"resolutionResult"
>
<
n
-
input
clearable
type
=
"textarea"
v
-
model
:
value
=
"feedbackFormValue.resolutionResult"
placeholder
=
"请输入处理结果"
/>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"管理员备注"
path
=
"adminNotes"
>
<
n
-
input
clearable
type
=
"textarea"
v
-
model
:
value
=
"feedbackFormValue.adminNotes"
placeholder
=
"请输入管理员备注"
/>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"处理时间"
path
=
"resolvedAt"
>
<
n
-
date
-
picker
value
-
format
=
"yyyy-MM-dd HH:mm:ss"
date
-
format
=
"yyyy-MM-dd HH:mm:ss"
class
=
"w-full"
:
value
=
"feedbackFormValue.resolvedAt"
type
=
"datetime"
clearable
@
update
:
formatted
-
value
=
"updateFormattedValue"
/>
<
/n-form-item
>
<
n
-
form
-
item
label
=
"处理状态"
path
=
"currentStatus"
>
<
n
-
radio
-
group
v
-
model
:
value
=
"feedbackFormValue.currentStatus"
name
=
"radiogroup"
>
<
n
-
space
>
<
n
-
radio
v
-
for
=
"statusOpt in statusOptions"
:
key
=
"statusOpt.value"
:
value
=
"statusOpt.value"
>
{{
statusOpt
.
name
}}
<
/n-radio
>
<
/n-space
>
<
/n-radio-group
>
<
/n-form-item
>
<
/n-form
>
<
template
#
footer
>
<
div
class
=
"flex gap-x-2 flex-row items-center"
>
<
n
-
button
class
=
"flex-1"
:
loading
=
"loading"
@
click
=
"onFeedbackCancel"
>
取消
<
/n-button
>
<
n
-
button
class
=
"flex-1"
:
loading
=
"loading"
type
=
'primary'
@
click
=
"onFeedbackSubmit"
>
保存
<
/n-button
>
<
/div
>
<
/template
>
<
/n-modal
>
<
n
-
modal
v
-
model
:
show
=
"showFeedbackDelModal"
preset
=
"dialog"
title
=
"确认"
content
=
"你确定要删除该反馈吗?"
positive
-
text
=
"确认"
negative
-
text
=
"算了"
@
positive
-
click
=
"deleteFeedback"
/>
<
/n-space
>
</script>
</script>
<script>
<script>
const
{
createApp
,
defineComponent
,
reactive
,
ref
,
onMounted
}
=
Vue
;
const
{
createApp
,
defineComponent
,
reactive
,
ref
,
onMounted
,
h
}
=
Vue
;
const
{
useMessage
,
useNotification
}
=
naive
const
{
useMessage
,
useNotification
,
dateZhCN
,
NButton
,
NTag
,
zhCN
,
NSpace
,
NImageGroup
,
NImage
,
NText
}
=
naive
const
BASE_URL
=
window
.
location
.
origin
+
'/gk/feedback-category'
// 添加全局 loading 指令
const
FC_BASE_URL
=
window
.
location
.
origin
+
'/gk/feedback-category'
const
F_BASE_URL
=
window
.
location
.
origin
+
'/gk/feedback'
const
uploadUrl
=
window
.
location
.
origin
+
'/api-common/v1/upload?folder='
+
'gk/feedback'
+
'&cmptId='
+
getCId
()
// to 方法,封装try catch
// to 方法,封装try catch
const
to
=
async
(
const
to
=
async
(
promise
,
promise
,
...
@@ -225,6 +322,8 @@
...
@@ -225,6 +322,8 @@
// 分类切换,刷新table
// 分类切换,刷新table
const
changeCategory
=
(
index
)
=>
{
const
changeCategory
=
(
index
)
=>
{
categoryIndex
.
value
=
index
categoryIndex
.
value
=
index
pagination
.
value
.
page
=
1
getFeedBacks
()
}
}
// 编辑分类
// 编辑分类
const
onEditCategory
=
(
item
)
=>
{
const
onEditCategory
=
(
item
)
=>
{
...
@@ -238,8 +337,26 @@
...
@@ -238,8 +337,26 @@
showCategoryModal
.
value
=
true
showCategoryModal
.
value
=
true
}
}
// 删除分类
// 删除分类
const
onDelCategory
=
(
item
)
=>
{
const
onDelCategory
=
async
(
item
)
=>
{
console
.
log
(
item
)
loading
.
value
=
true
const
messageReactive
=
message
.
loading
(
'删除中...'
,
{
duration
:
0
})
// 发起请求
const
[
err
,
data
]
=
await
to
(
fetch
(
FC_BASE_URL
+
'/'
+
item
.
id
,
{
method
:
'DELETE'
,
headers
:
{
'Content-Type'
:
'application/json'
},
}).
then
(
res
=>
res
.
json
()))
loading
.
value
=
false
messageReactive
.
destroy
()
if
(
data
.
code
===
200
)
{
message
.
success
(
'删除成功'
)
getCategories
()
}
else
{
message
.
error
(
data
.
msg
)
}
}
}
// 获取分类列表
// 获取分类列表
const
getCategories
=
async
()
=>
{
const
getCategories
=
async
()
=>
{
...
@@ -248,8 +365,9 @@
...
@@ -248,8 +365,9 @@
pageSize
:
20
,
pageSize
:
20
,
cmptId
:
getCId
()
cmptId
:
getCId
()
}
}
loading
.
value
=
true
;
// 发起请求
// 发起请求
const
[
err
,
data
]
=
await
to
(
fetch
(
BASE_URL
+
'/page'
,
{
const
[
err
,
data
]
=
await
to
(
fetch
(
FC_
BASE_URL
+
'/page'
,
{
method
:
"POST"
,
method
:
"POST"
,
headers
:
{
headers
:
{
'Content-Type'
:
'application/json'
'Content-Type'
:
'application/json'
...
@@ -260,6 +378,7 @@
...
@@ -260,6 +378,7 @@
if
(
data
.
code
===
200
)
{
if
(
data
.
code
===
200
)
{
feedbackCategories
.
value
=
data
.
content
.
content
feedbackCategories
.
value
=
data
.
content
.
content
showCategoryModal
.
value
=
false
showCategoryModal
.
value
=
false
getFeedBacks
()
}
else
{
}
else
{
message
.
error
(
data
.
msg
)
message
.
error
(
data
.
msg
)
}
}
...
@@ -277,8 +396,11 @@
...
@@ -277,8 +396,11 @@
cmptId
:
getCId
()
cmptId
:
getCId
()
}
}
loading
.
value
=
true
loading
.
value
=
true
const
messageReactive
=
message
.
loading
(
categoryFormValue
.
id
?
'数据更新中...'
:
'数据添加中...'
,
{
duration
:
0
})
// 发起请求
// 发起请求
const
[
err
,
data
]
=
await
to
(
fetch
(
BASE_URL
,
{
const
[
err
,
data
]
=
await
to
(
fetch
(
FC_
BASE_URL
,
{
method
:
method
,
method
:
method
,
headers
:
{
headers
:
{
'Content-Type'
:
'application/json'
'Content-Type'
:
'application/json'
...
@@ -286,6 +408,7 @@
...
@@ -286,6 +408,7 @@
body
:
JSON
.
stringify
(
params
)
body
:
JSON
.
stringify
(
params
)
}).
then
(
res
=>
res
.
json
()))
}).
then
(
res
=>
res
.
json
()))
loading
.
value
=
false
loading
.
value
=
false
messageReactive
.
destroy
()
if
(
data
.
code
===
200
)
{
if
(
data
.
code
===
200
)
{
message
.
success
(
'操作成功'
)
message
.
success
(
'操作成功'
)
showCategoryModal
.
value
=
false
showCategoryModal
.
value
=
false
...
@@ -305,42 +428,345 @@
...
@@ -305,42 +428,345 @@
showCategoryModal
.
value
=
false
showCategoryModal
.
value
=
false
}
}
/***----------------分类相关 end-----------------*/
/***----------------分类相关 end-----------------*/
/***---------------- 反馈相关 start-----------------*/
const
columns
=
[{
title
:
'选手反馈'
,
key
:
'content'
,
render
:
(
row
)
=>
{
// 用h函数实现
const
images
=
row
.
feedbackImageUrl
?.
split
(
','
)
??
[]
return
h
(
NSpace
,
{
vertical
:
true
,
},
[
h
(
NText
,
{},
"反馈编号:"
+
row
.
feedbackNo
),
h
(
NText
,
{},
"选手反馈:"
+
row
.
content
),
h
(
NText
,
{},
"反馈时间:"
+
row
.
createdAt
),
h
(
NImageGroup
,
{},
[
...
images
.
map
((
img
)
=>
h
(
NImage
,
{
height
:
"100"
,
src
:
img
}))
]),
])
}
},
{
title
:
'组委会处理'
,
key
:
'resolutionResult'
,
render
:
(
row
)
=>
{
const
images
=
row
.
resolveImageUrl
?.
split
(
','
)
??
[]
return
h
(
NSpace
,
{
vertical
:
true
,
},
[
h
(
NText
,
{},
"处理结果:"
+
(
row
.
resolutionResult
??
'--'
)),
h
(
NText
,
{},
"组委会备注:"
+
(
row
.
adminNotes
??
'--'
)),
h
(
NText
,
{},
"处理时间:"
+
(
row
.
resolvedAt
??
'--'
)),
h
(
NImageGroup
,
{},
[
...
images
.
map
((
img
)
=>
h
(
NImage
,
{
height
:
"100"
,
src
:
img
}))
]),
])
}
},
{
title
:
'处理状态'
,
key
:
'currentStatus'
,
width
:
100
,
render
:
(
row
)
=>
{
const
status
=
statusOptions
.
find
(
v
=>
row
.
currentStatus
===
v
.
value
)
return
h
(
NTag
,
{
type
:
status
.
type
},
status
.
name
)
}
},
{
title
:
'操作'
,
key
:
'actions'
,
width
:
150
,
align
:
'center'
,
render
:
(
row
)
=>
{
// 两个按钮,一个 编辑 一个 删除
return
h
(
NSpace
,
{},
[
h
(
NButton
,
{
type
:
'primary'
,
size
:
'small'
,
onClick
:
()
=>
{
// 编辑
editFeedback
(
row
)
}
},
'编辑'
),
h
(
NButton
,
{
type
:
'error'
,
size
:
'small'
,
onClick
:
()
=>
{
// 删除
// deleteFeedback(row)
feedback
.
value
=
row
showFeedbackDelModal
.
value
=
true
}
},
'删除'
)
])
}
}]
const
pagination
=
ref
({
pageSize
:
20
,
page
:
1
})
// 文件列表
const
fileList
=
ref
([])
// 结果列表
const
resultFileList
=
ref
([])
// 反馈弹框
const
showFeedbackModal
=
ref
(
false
)
// 删除反馈
const
showFeedbackDelModal
=
ref
(
false
)
const
feedback
=
ref
()
// 反馈的formRef
const
feedbackFormRef
=
ref
(
null
)
// 反馈的数据列表
const
feedbacks
=
ref
([])
// 反馈表单
const
feedbackFormValue
=
reactive
({
id
:
undefined
,
feedbackImageUrl
:
''
,
contactInfo
:
''
,
content
:
''
,
currentStatus
:
0
,
adminNotes
:
''
,
// 管理员备注
resolutionResult
:
''
,
// 解决结果
resolveImageUrl
:
''
,
// 解决图片URL,多张以逗号分隔
resolvedAt
:
undefined
// 解决时间
})
// 反馈的校验规则
feedbackRules
=
{
resolutionResult
:
{
required
:
true
,
message
:
'请输入解决结果'
,
trigger
:
'blur'
}
}
// 状态类型
// 状态类型
const
statusOptions
=
[
const
statusOptions
=
[
{
{
name
:
'未处理'
,
name
:
'未处理'
,
value
:
'pending'
value
:
0
,
type
:
'warning'
},
},
{
{
name
:
'处理中'
,
name
:
'处理中'
,
value
:
'processing'
value
:
1
,
type
:
'info'
},
},
{
{
name
:
'已处理'
,
name
:
'已处理'
,
value
:
'resolved'
value
:
2
,
type
:
'success'
}
}
]
]
// 当前状态
// 当前状态
const
status
=
ref
(
statusOptions
[
0
].
value
)
const
status
=
ref
(
''
)
// 状态更新
// 状态更新
const
updateStatus
=
(
value
)
=>
{
const
updateStatus
=
(
value
)
=>
{
pagination
.
value
.
page
=
1
status
.
value
=
value
status
.
value
=
value
getFeedBacks
()
}
// 新增反馈
const
addFeedBack
=
()
=>
{
showFeedbackModal
.
value
=
true
}
// 上传完成
const
uploadFinish
=
({
file
,
event
})
=>
{
const
response
=
JSON
.
parse
(
event
?.
target
?.
response
)
file
.
url
=
response
.
content
return
file
}
// 重置form数据
const
resetFeedbackValue
=
()
=>
{
feedbackFormValue
.
id
=
undefined
feedbackFormValue
.
feedbackImageUrl
=
''
feedbackFormValue
.
contactInfo
=
''
feedbackFormValue
.
content
=
''
feedbackFormValue
.
currentStatus
=
0
feedbackFormValue
.
adminNotes
=
''
feedbackFormValue
.
resolutionResult
=
''
feedbackFormValue
.
resolveImageUrl
=
''
feedbackFormValue
.
resolvedAt
=
undefined
}
// 删除反馈
const
deleteFeedback
=
()
=>
{
if
(
!
feedback
.
value
)
{
showFeedbackDelModal
.
value
=
false
return
}
loading
.
value
=
true
const
messageReactive
=
message
.
loading
(
'删除中...'
,
{
duration
:
0
})
// 发起请求
fetch
(
F_BASE_URL
+
'/'
+
feedback
.
value
.
id
,
{
method
:
'DELETE'
,
headers
:
{
'Content-Type'
:
'application/json'
}
}).
then
(
res
=>
res
.
json
()).
then
(
data
=>
{
if
(
data
.
code
===
200
)
{
message
.
success
(
'删除成功'
)
getFeedBacks
()
}
else
{
message
.
error
(
data
.
msg
)
}
}).
finally
(()
=>
{
loading
.
value
=
true
messageReactive
.
destroy
()
showFeedbackDelModal
.
value
=
false
})
}
// 编辑反馈
const
editFeedback
=
(
feedback
)
=>
{
resetFeedbackValue
()
showFeedbackModal
.
value
=
true
feedbackFormValue
.
id
=
feedback
.
id
feedbackFormValue
.
feedbackImageUrl
=
''
feedbackFormValue
.
contactInfo
=
feedback
.
contactInfo
feedbackFormValue
.
content
=
feedback
.
content
feedbackFormValue
.
currentStatus
=
feedback
.
currentStatus
feedbackFormValue
.
adminNotes
=
feedback
.
adminNotes
feedbackFormValue
.
resolutionResult
=
feedback
.
resolutionResult
feedbackFormValue
.
resolvedAt
=
feedback
.
resolvedAt
// 图片的处理
if
(
feedback
?.
resolveImageUrl
)
{
resultFileList
.
value
=
feedback
.
resolveImageUrl
.
split
(
','
).
map
(
v
=>
({
url
:
v
,
status
:
'finished'
,
name
:
v
.
split
(
'/'
).
pop
(),
id
:
v
,
uid
:
v
}))
}
if
(
feedback
?.
feedbackImageUrl
)
{
fileList
.
value
=
feedback
.
feedbackImageUrl
.
split
(
','
).
map
(
v
=>
({
url
:
v
,
status
:
'finished'
,
name
:
v
.
split
(
'/'
).
pop
(),
id
:
v
,
uid
:
v
}))
}
showFeedbackModal
.
value
=
true
}
// 取消操作
const
onFeedbackCancel
=
()
=>
{
showFeedbackModal
.
value
=
false
resetFeedbackValue
()
}
// 提交
const
onFeedbackSubmit
=
(
e
)
=>
{
e
.
preventDefault
()
feedbackFormRef
.
value
?.
validate
(
async
(
errors
)
=>
{
if
(
errors
)
return
message
.
error
(
'请检查表单是否填写完整'
)
const
method
=
feedbackFormValue
.
id
?
'PUT'
:
'POST'
// 使用fetch发起请求
const
params
=
{
...
feedbackFormValue
,
categoryId
:
feedbackCategories
.
value
[
categoryIndex
.
value
].
id
,
cmptId
:
getCId
(),
resolveImageUrl
:
resultFileList
.
value
.
map
(
v
=>
v
.
url
).
join
()
}
}
const
notify
=
(
type
)
=>
{
// 移除这个参数
notification
[
type
]({
delete
params
.
content
content
:
'What to say?'
,
delete
params
.
contactInfo
meta
:
'I don
\'
t know'
,
delete
params
.
feedbackImageUrl
duration
:
2500
,
loading
.
value
=
true
keepAliveOnHover
:
true
const
messageReactive
=
message
.
loading
(
feedbackFormValue
.
id
?
'数据更新中...'
:
'数据添加中...'
,
{
duration
:
0
})
})
// 发起请求
const
[
err
,
data
]
=
await
to
(
fetch
(
F_BASE_URL
,
{
method
:
method
,
headers
:
{
'Content-Type'
:
'application/json'
},
body
:
JSON
.
stringify
(
params
)
}).
then
(
res
=>
res
.
json
()))
loading
.
value
=
false
messageReactive
.
destroy
()
if
(
data
.
code
===
200
)
{
message
.
success
(
'操作成功'
)
showFeedbackModal
.
value
=
false
resetFeedbackValue
()
getCategories
()
}
else
{
message
.
error
(
data
.
msg
)
}
}
})
}
// 获取反馈分页列表
const
getFeedBacks
=
async
()
=>
{
loading
.
value
=
true
// 发起请求
const
[
err
,
data
]
=
await
to
(
fetch
(
F_BASE_URL
+
'/page'
,
{
method
:
"POST"
,
headers
:
{
'Content-Type'
:
'application/json'
},
body
:
JSON
.
stringify
({
cmptId
:
getCId
(),
currentStatus
:
status
.
value
?
undefined
:
status
.
value
,
pageNum
:
pagination
.
value
.
page
,
pageSize
:
pagination
.
value
.
pageSize
,
categoryId
:
feedbackCategories
.
value
[
categoryIndex
.
value
].
id
})
}).
then
(
res
=>
res
.
json
()))
loading
.
value
=
false
if
(
data
.
code
===
200
)
{
feedbacks
.
value
=
data
.
content
.
content
}
else
{
message
.
error
(
data
.
msg
)
}
}
// 分页切换
const
handlePageChange
=
(
page
)
=>
{
pagination
.
value
.
page
=
page
getFeedBacks
()
}
// 日期处理
const
updateFormattedValue
=
(
val
)
=>
{
feedbackFormValue
.
resolvedAt
=
val
}
/***---------------- 反馈相关 end -----------------*/
onMounted
(()
=>
{
onMounted
(()
=>
{
getCategories
()
getCategories
()
})
})
return
{
return
{
// 反馈相关
addFeedBack
,
statusOptions
,
statusOptions
,
status
,
status
,
updateStatus
,
updateStatus
,
showFeedbackModal
,
feedbackFormRef
,
feedbackFormValue
,
onFeedbackCancel
,
onFeedbackSubmit
,
fileList
,
feedbacks
,
pagination
,
handlePageChange
,
columns
,
deleteFeedback
,
editFeedback
,
showFeedbackDelModal
,
feedbackRules
,
updateFormattedValue
,
resultFileList
,
// 反馈分类相关
feedbackCategories
,
feedbackCategories
,
categoryIndex
,
categoryIndex
,
changeCategory
,
changeCategory
,
...
@@ -352,35 +778,21 @@
...
@@ -352,35 +778,21 @@
showCategoryModal
,
showCategoryModal
,
categoryRules
,
categoryRules
,
onCategorySubmit
,
onCategorySubmit
,
// 公共数据
uploadUrl
,
uploadFinish
,
loading
,
loading
,
data
:
[
{
no
:
3
,
title
:
'Wonderwall'
,
length
:
'4:18'
},
{
no
:
4
,
title
:
'Don
\'
t Look Back in Anger'
,
length
:
'4:48'
},
{
no
:
12
,
title
:
'Champagne Supernova'
,
length
:
'7:27'
}
],
pagination
:
ref
({
pageSize
:
5
}),
columns
:
[{
title
:
'No'
,
key
:
'no'
},
{
title
:
'Title'
,
key
:
'title'
},
{
title
:
'Length'
,
key
:
'length'
},
{
title
:
'Action'
,
key
:
'actions'
}],
}
}
}
}
})
})
const
app
=
Vue
.
createApp
({})
const
app
=
Vue
.
createApp
({
setup
()
{
return
{
locale
:
zhCN
,
dateLocale
:
dateZhCN
}
}
})
app
.
component
(
'my-app'
,
MyApp
)
app
.
component
(
'my-app'
,
MyApp
)
app
.
use
(
naive
)
app
.
use
(
naive
)
app
.
mount
(
'#app'
)
app
.
mount
(
'#app'
)
...
...
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