zhanglun_wd

Merge remote-tracking branch 'origin/main' into main

... ... @@ -7,6 +7,7 @@ import { HostEnum, HostManager } from './HttpHostManager';
* 网络请求参数工具类,TODO 不对外暴露,收缩权限
*/
export class HttpParams {
static buildHeaders(): Record<string, string> {
let headers: Record<string, string> = {};
// 通用请求头
... ... @@ -90,8 +91,17 @@ export class HttpParams {
return '10000';
}
private static getVersionName() {
public static getVersionName() {
// TODO 读取配置
return '1.0.0';
}
//获取机型
static getPhoneModel() {
return 'getPhoneModel'
}
//获取当前手机系统版本号
static getSystemVersion() {
return 'getSystemVersion'
}
}
\ No newline at end of file
... ...
... ... @@ -349,6 +349,11 @@ export class HttpUrlUtils {
*/
static readonly HISTORY_PUSH_MESSAGE_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/push";
/**
* 意见反馈-提交
*/
static readonly FEEDBACK_COMMIT_PATH: string = "/api/rmrb-interact/interact/zh/c/user/feedBack";
static getHost(): string {
return HostManager.getHost();
}
... ...
import { Action, ContentDTO, Params, PhotoListBean, commentInfo } from 'wdBean';
import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO';
import { Logger } from 'wdKit';
import { Logger, SPHelper } from 'wdKit';
import { StringUtils } from 'wdKit/src/main/ets/utils/StringUtils';
import { WDRouterRule, WDRouterPage } from '../../../../Index';
import { ContentConstants } from 'wdConstant';
import { ContentConstants, SpConstants } from 'wdConstant';
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { CompAdvMatInfoBean } from 'wdBean/src/main/ets/bean/adv/CompAdvInfoBean';
... ... @@ -462,7 +462,13 @@ export class ProcessUtils {
/**
* 意见反馈
*/
public static gotoFeedBackActivity() {
public static async gotoFeedBackActivity() {
// 未登录,跳转登录
const user_id = await SPHelper.default.get(SpConstants.USER_ID, '')
if (!user_id) {
WDRouterRule.jumpWithPage(WDRouterPage.loginPage)
return
}
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
... ...
... ... @@ -122,7 +122,9 @@ function handleJsCallReceiveH5Data(data: Message) {
width: item.width,
height: item.height,
picPath: item.pic,
picDesc: ''
picDesc: '',
itemType:2,
id:0
}
return photo
})
... ...
... ... @@ -174,4 +174,4 @@ export { ReserveItemBean } from './src/main/ets/bean/live/ReserveItemBean';
export { FeedbackTypeBean } from './src/main/ets/bean/detail/FeedbackTypeBean';
\ No newline at end of file
export { FeedbackTypeBean } from './src/main/ets/bean/detail/FeedbackTypeBean';
... ...
... ... @@ -4,10 +4,13 @@
// 【图文、图集稿件正文图片】图片信息数组
export interface PhotoListBean {
id: number;
height: number;
width: number;
picPath: string;
picDesc: string;
//1添加图片,2图片
itemType: number;
}
export interface InputMethodProperty {
... ...
... ... @@ -45,6 +45,10 @@ import { detailedSkeleton } from './skeleton/detailSkeleton';
const TAG = 'DynamicDetailComponent'
const PATTERN_DATE_CN_RN: string = 'yyyy年MM月dd日 HH:mm';
/**
* @author wd-zsz
* */
// @Preview
@Component
export struct DynamicDetailComponent {
... ...
import { FeedbackTypeBean } from 'wdBean/Index';
import { NetworkUtil } from 'wdKit/Index';
import { FeedbackTypeBean, PhotoListBean } from 'wdBean/Index';
import { FastClickUtil, Logger, NetworkUtil, StringUtils, ToastUtils, UserDataLocal } from 'wdKit/Index';
import { MultiPictureDetailViewModel } from '../viewmodel/MultiPictureDetailViewModel';
import { CustomTitleUI } from './reusable/CustomTitleUI'
import { ArrayList } from '@kit.ArkTS';
import { picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { router } from '@kit.ArkUI';
import { CommonConstants } from 'wdConstant/Index';
import { ProcessUtils } from 'wdRouter/Index';
import { HashMap } from '@kit.ArkTS';
import { HttpParams } from 'wdNetwork/src/main/ets/http/HttpCommonParams';
const TAG = 'FeedBackActivity'
// 意见反馈页面
/**
* 意见反馈页面
* @author wd-zsz
* */
@Entry
@Component
export struct FeedBackActivity {
@State canSubmit: boolean = false;
@State textNumLabel: string = '0/500';
contact: string = "";
email: string = "";
//UI
scroller: Scroller = new Scroller();
@State isNetConnected: boolean = true
@State feedbackTypeBeans: FeedbackTypeBean[] = [] as FeedbackTypeBean[]
//添加图片
addPic: PhotoListBean = {itemType:1} as PhotoListBean
@State pics: PhotoListBean[] = [this.addPic] as PhotoListBean[]
// 选择媒体文件的最大数目
selectNum = 3;
async aboutToAppear() {
await this.getContentDetailData()
... ... @@ -23,97 +42,209 @@ export struct FeedBackActivity {
build() {
Column() {
//标题栏目
CustomTitleUI({ titleName: "意见反馈" })
CustomTitleUI({ titleName: $r('app.string.feedback') })
Stack({ alignContent: Alignment.Bottom }) {
Scroll(this.scroller) {
Column() {
Text('请选择问题类型')
Text($r('app.string.feedback_opinion_type'))
.fontColor($r('app.color.color_222222'))
.fontSize($r('app.float.font_size_16'))
.fontWeight(FontWeight.Bold)
.width('100%')
.margin({ left: $r('app.float.vp_15'), top: $r('app.float.vp_14') })
GridRow({
gutter: { x: 2, y: 2 }
columns:3,
}) {
ForEach(this.feedbackTypeBeans, (item: FeedbackTypeBean, index: number) => {
ForEach(this.feedbackTypeBeans, (feedbackTypeBean: FeedbackTypeBean, index: number) => {
GridCol({
span: 12
}) {
Row(){
Toggle({ type: ToggleType.Checkbox, isOn: false })
Text(item.classifyName)
.onChange((select) => {
feedbackTypeBean.isselect = select
this.canSubmit = this.checkSubmit()
})
Text(feedbackTypeBean.classifyName)
.fontColor($r('app.color.color_222222'))
.fontSize($r('app.float.font_size_14'))
.fontWeight(FontWeight.Bold)
.margin({ left: $r('app.float.vp_4') })
}
.width(115)
.height(22)
.width($r('app.float.margin_115'))
.height($r('app.float.vp_22'))
.margin({bottom:$r('app.float.margin_16')})
.backgroundColor($r('app.color.color_fff'))
}
})
}
.width('100%')
.margin({top:$r('app.float.vp_16')})
Blank()
.height(0.5)
.margin({ left: $r('app.float.vp_16'), top: $r('app.float.vp_12'), right: $r('app.float.vp_16') })
.backgroundColor($r('app.color.color_EDEDED'))
Text('描述您的问题')
.height($r('app.float.margin_5'))
.backgroundColor($r('app.color.color_F5F5F5'))
Text($r('app.string.feedback_opinion_tv'))
.fontColor($r('app.color.color_222222'))
.fontSize($r('app.float.font_size_16'))
.fontWeight(FontWeight.Bold)
.width(CommonConstants.FULL_WIDTH)
.margin({ left: $r('app.float.vp_16'), top: $r('app.float.vp_12') })
Stack() {
TextInput({ placeholder: '您的宝贵意见是我们前行的动力' })
GridRow({
gutter: { x: 2, y: 2 }
}) {
ForEach(this.feedbackTypeBeans, (item: FeedbackTypeBean, index: number) => {
GridCol({
span: 12
}) {
}
})
Stack({ alignContent: Alignment.BottomEnd }) {
TextArea({ placeholder: $r('app.string.feedback_comments') })
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
.padding({bottom:96})
.backgroundColor($r('app.color.color_F5F5F5'))
.align(Alignment.TopStart)
.maxLength(500)
.onChange((value) => {
// Logger.debug(TAG, "onChange" + value + "/" + this.passwordContent)
this.contact = value
this.textNumLabel = value.length+"/500"
this.canSubmit = this.checkSubmit()
})
GridRow({
columns:5,
}) {
ForEach(this.pics, (feedbackImageItem: PhotoListBean, index: number) => {
GridCol({
}) {
if(1 == feedbackImageItem.itemType){
Image($r('app.media.feekback_add'))
.width(60)
.height(60)
.onClick(async (event: ClickEvent) => {
if(await FastClickUtil.isMinDelayTime()){
return
}
this.callFilePickerSelectImage();
})
}else{
Stack({alignContent: Alignment.TopEnd}) {
Image(feedbackImageItem.picPath)
.width(60)
.height(60)
.borderRadius($r('app.float.margin_1'))
.onClick(async (event: ClickEvent) => {
if(await FastClickUtil.isMinDelayTime()){
return
}
//查看图片 fixme 去除添加按钮
ProcessUtils.gotoMultiPictureListPage(this.pics, index)
})
Image($r('app.media.icon_feekback_delete'))
.width(24)
.height(24)
.borderRadius($r('app.float.margin_1'))
.onClick(async (event: ClickEvent) => {
if(await FastClickUtil.isMinDelayTime()){
return
}
let temp: PhotoListBean[] = [] as PhotoListBean[]
temp.length = this.pics.length - 1;
let tempIndex = 0;
for (let index = 0; index < this.pics.length; index++) {
const element = this.pics[index];
if(!StringUtils.isEmpty(element.picPath) && element.id != feedbackImageItem.id){
temp[tempIndex] = element;
tempIndex = tempIndex+1
}
}
if(tempIndex < 3){
temp[tempIndex] = this.addPic
}
this.pics = temp
})
}
.width(60)
.height(60)
}
}
})
}
.margin({bottom: $r('app.float.vp_12'), right: $r('app.float.vp_12'),left: $r('app.float.vp_12')})
Text(this.textNumLabel)
.margin({bottom: $r('app.float.vp_12'), right: $r('app.float.vp_11')})
}
.height(200)
.width('90%')
.margin({ top: $r('app.float.vp_12') })
.backgroundColor($r('app.color.color_F5F5F5'))
.borderRadius(4)
Text('0/500')
}
.height(200)
.width('100%')
.margin({ left: $r('app.float.vp_16'), top: $r('app.float.vp_12'), right: $r('app.float.vp_16') })
.backgroundColor($r('app.color.color_F5F5F5'))
.borderRadius(4)
Text('期待您留下联系方式,我们将提供更好的服务')
Text($r('app.string.feedback_email'))
.fontColor($r('app.color.color_222222'))
.fontSize($r('app.float.font_size_14'))
.fontWeight(FontWeight.Bold)
.width('100%')
.margin({ left: $r('app.float.vp_16'), top: $r('app.float.margin_24') })
Row() {
Text('电话或者邮箱')
Text($r('app.string.feedback_mail'))
.fontColor($r('app.color.color_222222'))
.fontSize($r('app.float.font_size_14'))
.fontWeight(FontWeight.Bold)
.margin({ left: $r('app.float.vp_12') })
TextInput({ placeholder: '请输入电话或者邮箱' })
TextInput({ placeholder: $r('app.string.feedback_hideemail') })
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
.backgroundColor($r('app.color.color_F5F5F5'))
.onChange((value) => {
// Logger.debug(TAG, "onChange" + value + "/" + this.passwordContent)
this.email = value
})
}
.height(44)
.margin({ left: $r('app.float.vp_16'), right: $r('app.float.vp_12'), top: $r('app.float.margin_16') })
.width('90%')
.backgroundColor($r('app.color.color_F5F5F5'))
.margin({top: $r('app.float.margin_16') })
.borderRadius(4)
Blank().layoutWeight(1)
}
}
Text($r('app.string.submit'))
.height(44)
.fontColor($r('app.color.color_9E9E9E_40'))
.fontSize($r('app.float.font_size_18'))
.margin({ left: $r('app.float.vp_16'), right: $r('app.float.vp_16'), top: $r('app.float.vp_15') })
.backgroundColor($r('app.color.color_ED2800_99'))
.borderRadius(4)
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
.scrollBar(BarState.Off)
.alignSelf(ItemAlign.Start)
.padding({ bottom: 44 })
Column(){
Text($r('app.string.submit'))
.align(Alignment.Center)
.height(44)
.width('90%')
.fontColor(this.canSubmit?$r('app.color.color_9E9E9E_40'):$r('app.color.color_fff'))
.fontSize($r('app.float.font_size_18'))
.backgroundColor(this.canSubmit?$r('app.color.color_ED2800_99'):$r('app.color.color_EDEDED'))
.borderRadius(4)
.onClick(async (event: ClickEvent) => {
if(await FastClickUtil.isMinDelayTime()){
return
}
this.reportCommit()
})
Blank().height(15).width('100%')
}
.height(59)
}
}
}
/**
* 校验可提交状态
* */
checkSubmit(): boolean {
if(StringUtils.isEmpty(this.contact) || this.contact.length < 10){
return false
}
if(this.feedbackTypeBeans == null || this.feedbackTypeBeans.length == 0){
return false
}
return true
}
/**
* 请求接口数据
* */
... ... @@ -126,4 +257,117 @@ export struct FeedBackActivity {
console.log('请求失败',JSON.stringify(exception))
}
}
/**
* 拉起picker选择图片/视频
*/
async callFilePickerSelectImage(): Promise<void> { // async 用于申明一个 function 是异步的
let array: string[];
try {
// 设置photoPicker的参数
let PhotoSelectOptions = new picker.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型
PhotoSelectOptions.maxSelectNumber = this.selectNum; // 选择媒体文件的最大数目
let mediaFlag = false;
let photoPicker = new picker.PhotoViewPicker(); // 使用图库选择器对象前,需要先创建PhotoViewPicker实例
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
Logger.info(TAG, 'PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult)); // 日志中记录成功信息
if (PhotoSelectResult !== null && PhotoSelectResult !== undefined) { // 接口采用callback异步返回形式,返回PhotoSelectResult对象,故进行下一步操作前要先判断是否已经成功返回PhotoSelectResult对象了
// PhotoSelectResult为返回的结果集。
// 其中包含Array<string>类型的photoUris,为返回图库选择后的媒体文件的uri数组;还包含boolean类型的isOriginalPhoto,指示返回图库选择后的媒体文件是否为原图。
// 声明变量array,其取值为PhotoSelectResult中的数组。
array = PhotoSelectResult['photoUris'];
let startIndex = this.pics.length-1;
let totalLen = this.pics.length+array.length;
if(totalLen > 3){
totalLen = 3
}
this.pics.length = totalLen;
array.forEach((value) => {
let pic: PhotoListBean = {itemType:2,picPath:value} as PhotoListBean
pic.id = startIndex
this.pics[startIndex] = pic
startIndex = startIndex+1;
mediaFlag = true;
Logger.info(TAG, `select image/video uri: ${value}`);
})
if(this.pics.length<3){
this.addPic.id = startIndex
this.pics[this.pics.length-1]=this.addPic;
}
}
if (mediaFlag) {
this.getFilenameByUriForMedia(array);
}
})
.catch((err: BusinessError) => {
Logger.error(TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'PhotoViewPicker failed with err: ' + err);
}
}
async getFilenameByUriForMedia(myUris: string[]) {
router.pushUrl({
url: 'pages/ViewMedia',
params: {
uris: myUris
}
}, router.RouterMode.Standard);
}
//提交
async reportCommit(){
//问题类型必选
let selectType = ""
this.feedbackTypeBeans.forEach((value) => {
if(value.isselect){
selectType = selectType+","
}
})
if(!StringUtils.isEmpty(selectType)){
selectType = selectType.substring(0,selectType.length-1)
}else{
//
ToastUtils.shortToast($r('app.string.feedback_opinion_type'))
return
}
//内容必填
if(StringUtils.isEmpty(this.contact) || this.contact.length < 10 || this.contact.length>500){
ToastUtils.shortToast($r('app.string.res_feedback_commentsFail'))
return
}
try {
let map: HashMap<String,String> = {} as HashMap<String,String>
//反馈内容
map.set("content", this.contact);
//投诉类型 id
map.set("classifyFlagIds", selectType);
if(!StringUtils.isEmpty(this.email)){
//邮箱
map.set("userContact", this.email);
}
//用户名称
if (!StringUtils.isEmpty(UserDataLocal.getUserName())) {
map.set("userName", UserDataLocal.getUserName());
}
//设备
map.set("appVersion", "V" + HttpParams.getVersionName());
map.set("appDevice", "harmony" + HttpParams.getSystemVersion() + " " + HttpParams.getPhoneModel());
// //投诉图片
// if (imageUrl.size() > 0) {
// String[] str = imageUrl.toArray(new String[imageUrl.size()]);
// map.set("imageUrls", str);
// }
await MultiPictureDetailViewModel.feedBackCommit(map)
} catch (exception) {
console.log('请求失败',JSON.stringify(exception))
}
}
}
\ No newline at end of file
... ...
... ... @@ -68,7 +68,9 @@ export struct Card19Component {
width: item.weight,
height: item.height,
picPath: item.fullUrl||item.url,
picDesc: ''
picDesc: '',
itemType:2,
id:0
}
return photo
})
... ...
... ... @@ -3,7 +3,7 @@ import router from '@ohos.router'
@Component
export struct CustomTitleUI {
imgBack:boolean = true
titleName:string = "默认标题"
titleName:ResourceStr = "默认标题"
build() {
RelativeContainer() {
... ...
import { Logger } from 'wdKit';
import { ResponseDTO } from 'wdNetwork';
import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork';
import { HashMap } from '@kit.ArkTS';
import { ContentDetailDTO,
batchLikeAndCollectParams,
batchLikeAndCollectResult,
... ... @@ -156,4 +157,17 @@ export class MultiPictureDetailViewModel {
})
})
}
static async feedBackCommit(params:HashMap<String,String>): Promise<ResponseDTO> {
return new Promise<ResponseDTO>((success, error) => {
Logger.info(TAG, `fetchDetailData start`);
WDHttp.post(HttpUrlUtils.getHost() + HttpUrlUtils.FEEDBACK_COMMIT_PATH,params).then((resDTO: ResponseDTO) => {
success(resDTO);
}).catch((err: Error) => {
Logger.error(TAG, `fetchDetailData catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
}
... ...
... ... @@ -307,6 +307,10 @@
{
"name": "vp_13",
"value": "13vp"
},
{
"name": "margin_115",
"value": "115vp"
}
]
}
... ...
... ... @@ -67,5 +67,40 @@
"name": "feedback",
"value": "意见反馈"
}
,
{
"name": "res_feedback_commentsFail",
"value": "请输入 10-500 个字以内"
}
,
{
"name": "feedback_opinion_type",
"value": "请选择问题类型"
}
,
{
"name": "feedback_comments",
"value": "您的宝贵意见是我们前行的动力"
}
,
{
"name": "feedback_opinion_tv",
"value": "描述您的问题"
}
,
{
"name": "feedback_email",
"value": "期待您留下联系方式,我们将提供更好的服务"
}
,
{
"name": "feedback_mail",
"value": "电话或者邮箱"
}
,
{
"name": "feedback_hideemail",
"value": "请输入电话或者邮箱"
}
]
}
\ No newline at end of file
... ...