视频详情评论

This commit is contained in:
xiaoxiao 2025-05-29 17:13:23 +08:00
parent 5375c26462
commit fc801e1345
23 changed files with 899 additions and 33 deletions

View File

@ -1,6 +1,20 @@
{
"app": {
"signingConfigs": [],
"signingConfigs": [
{
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": "/Users/gandanxiangzhao/.ohos/config/default_harmony_0p9qf45UN48IqoSyKhLtcLhTMwMj81GJRnBkhg7Axm4=.cer",
"keyAlias": "debugKey",
"keyPassword": "0000001AA50378305356D7D7EEDE463DB4E4B1B23C35A2615C29ED413C2E2DC30778DFE346C51C100F7D",
"profile": "/Users/gandanxiangzhao/.ohos/config/default_harmony_0p9qf45UN48IqoSyKhLtcLhTMwMj81GJRnBkhg7Axm4=.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "/Users/gandanxiangzhao/.ohos/config/default_harmony_0p9qf45UN48IqoSyKhLtcLhTMwMj81GJRnBkhg7Axm4=.p12",
"storePassword": "0000001A29D969B0C08E79F7AC25E39AEB74F09540DED4C7BEF6ABF0671F85B598C8F911C2943D3B741C"
}
}
],
"products": [
{
"name": "default",

View File

@ -49,3 +49,7 @@ export { EmptyViewComp } from './src/main/ets/Views/EmptyViewComp'
export { HdLoadingDialog } from './src/main/ets/components/HdLoadingDialog'
export { EditUserDataItem } from './src/main/ets/Views/EditUserDataItem'
export { Huanzhelast444Model } from './src/main/ets/models/Huanzhelast444Model'
export { huanzheDb } from './src/main/ets/utils/HuanzhelasDbHelper'

View File

@ -7,7 +7,7 @@ export class BasicConstant {
//测试环境
static readonly urlExpertAPI = "https://dev-app.igandan.com/app/expertAPI/";
static readonly urlExpertApp = "https://dev-app.igandan.com//app/expertApp/"
static readonly urlExpertApp = "https://dev-app.igandan.com/app/expertApp/"
static readonly urlHtml = "http://dev-doc.igandan.com/app/"
static readonly urlImage = "https://dev-doc.igandan.com/app/"
static readonly urlExpert = "https://dev-app.igandan.com/app/expert/"
@ -29,6 +29,9 @@ export class BasicConstant {
static readonly zhibourl = BasicConstant.wxUrl+"hcp/setInfo";
static readonly videoByTypeNew = BasicConstant.urlExpertApp + 'videoByTypeNew'
static readonly videoDetail = BasicConstant.urlExpertAPI + "videoDetail";
static readonly videoCommentListV2 = BasicConstant.urlExpertAPI + "videoCommentListV2";//视频详情评价列表
static readonly addCommentV2 = BasicConstant.urlExpertAPI+'addCommentV2';//评论回复
static readonly deleteComment = BasicConstant.urlExpertApp+'deleteComment';//删除评论
static readonly meetingHistoryList = BasicConstant.urlExpertAPI + "meetingHistoryList";
static readonly videoRoll = BasicConstant.urlExpertAPI + "videoRoll";
static readonly expertVideoTypeList = BasicConstant.urlExpertAPI + "expertVideoTypeList";

View File

@ -0,0 +1,82 @@
import { Entity, Columns, Id, ColumnType } from '@ohos/dataorm';
// 表名需与sqlite一致
@Entity('t_huanzhelast444')
export class Huanzhelast444Model {
@Id()
@Columns({ columnName: '_id', types: ColumnType.num }) // 主键字段映射
_id: number = 0;
@Columns({ columnName: 'id', types: ColumnType.num })
id: number = 0;
@Columns({ columnName: 'fullname', types: ColumnType.str })
fullname: string = '';
@Columns({ columnName: 'name', types: ColumnType.str })
name: string = '';
@Columns({ columnName: 'parent', types: ColumnType.num })
parent: number = 0;
@Columns({ columnName: 'treePath', types: ColumnType.str })
treePath: string = '';
// 必须包含所有非静态变量的构造函数
constructor(
_id: number = 0,
id: number = 0,
fullname: string = '',
name: string = '',
parent: number = 0,
treePath: string = ''
) {
this._id = _id;
this.id = id;
this.fullname = fullname;
this.name = name;
this.parent = parent;
this.treePath = treePath;
}
setTreePath(treePath:string) {
this.treePath = treePath;
}
getTreePath():string {
return this.treePath;
}
setParent(parent:number) {
this.parent = parent;
}
getParent():number {
return this.parent;
}
setName(name:string) {
this.name = name;
}
getName():string {
return this.name;
}
setFullname(fullname:string) {
this.fullname = fullname;
}
getFullname():string {
return this.fullname;
}
getId():number {
return this.id;
}
setId(id:number) {
this.id = id;
}
}

View File

@ -0,0 +1,153 @@
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import relationalStore from '@ohos.data.relationalStore';
import util from '@ohos.util';
import { Huanzhelast444Model } from '../models/Huanzhelast444Model'
const huanzhelastFile: string = 'huanzhelas.sqlite';
// 步骤1将rawfile数据库文件复制到应用沙箱
async function copyDatabase(context: common.Context): Promise<void> {
try {
const resourceMgr = context.resourceManager;
const rawFile = await resourceMgr.getRawFileContent(huanzhelastFile);
// 将Uint8Array转为ArrayBuffer
const arrayBuffer = rawFile.buffer;
// 创建沙箱路径
const dbPath = context.filesDir + '/' + huanzhelastFile;
console.info(`[DB] context.filesDir: ${context.filesDir}`);
console.info(`[DB] dbPath: ${dbPath}`);
// 确保目录存在
try {
fs.accessSync(context.filesDir);
} catch (e) {
fs.mkdirSync(context.filesDir);
}
// 写入文件
const file = fs.openSync(dbPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
fs.writeSync(file.fd, arrayBuffer);
fs.closeSync(file);
// 检查文件是否存在
try {
fs.accessSync(dbPath);
console.info(`[DB] DB file exists after copy: ${dbPath}`);
} catch (e) {
console.error(`[DB] DB file does not exist after copy: ${dbPath}`);
}
} catch (error) {
console.error(`Copy database failed: ${error}`);
}
}
// 步骤2数据库操作封装类
class HuanzhelasDbHelper {
private rdbStore: relationalStore.RdbStore | null = null;
// 初始化数据库连接
async initDatabase(context: common.Context): Promise<void> {
await copyDatabase(context);
const storeConfig: relationalStore.StoreConfig = {
name: huanzhelastFile,
securityLevel: relationalStore.SecurityLevel.S1
};
try {
this.rdbStore = await relationalStore.getRdbStore(context, storeConfig);
console.info('Database connection established');
} catch (error) {
console.error(`Init database failed: ${error}`);
}
}
async queryHuanzhelastData():Promise<Array<HuanzhelastEntity>> {
if (!this.rdbStore) {
console.error('Database not initialized');
throw new Error('Database not initialized');
}
// const resultSet = await this.rdbStore.querySql('SELECT * FROM t_huanzhelast444', []);
// if (resultSet.rowCount > 0) {
// resultSet.goToFirstRow();
// do {
// console.info('[DB] Table:', resultSet.getString(0));
// } while (resultSet.goToNextRow());
// }
// resultSet.close();
// try {
// const predicates = new relationalStore.RdbPredicates('t_huanzhelast444');
// console.info('[DB] Querying table: t_huanzhelast444');
// const resultSet = await this.rdbStore.query(predicates);
//
// if (resultSet.isClosed) {
// console.error('[DB] ResultSet is closed immediately after query!');
// return;
// }
// console.info('[DB] ResultSet columnNames:', resultSet.columnNames);
// console.info('[DB] Query finished, rowCount:', resultSet.rowCount);
//
// if (resultSet.rowCount > 0) {
// resultSet.goToFirstRow();
// do {
// // // 打印每一行
// // let row: Required = {};
// // for (let i = 0; i < resultSet.columnNames.length; i++) {
// // row[resultSet.columnNames[i]] = resultSet.getString(i);
// // }
// // console.info('[DB] Row:', JSON.stringify(row));
// console.info('[DB] Row:');
// } while (resultSet.goToNextRow());
// } else {
// console.warn('[DB] No data found, please check table name and data!');
// }
// resultSet.close();
// } catch (e) {
// console.error('[DB] Query error:', e);
// throw new Error('Database query error');
// }
try {///data/app/el2/100/base/com.example.expert/haps/default/files/databases/huanzhelas.sqlite
const predicates = new relationalStore.RdbPredicates('cn_shangyu_gdxzExpert_bean_City');
const resultSet = await this.rdbStore.query(predicates);
const dataList: Array<HuanzhelastEntity> = [];
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
do {
dataList.push(this.parseResultSet(resultSet));
} while (resultSet.goToNextRow());
} else {
console.error(`Query failed: ${predicates}`);
}
resultSet.close();
return dataList;
} catch (error) {
console.error(`Query failed: ${error}`);
throw new Error('Database query error');
}
}
private parseResultSet(resultSet: relationalStore.ResultSet): HuanzhelastEntity {
return {
_id: resultSet.getDouble(resultSet.getColumnIndex('_id')),
id: resultSet.getDouble(resultSet.getColumnIndex('id')),
fullname: resultSet.getString(resultSet.getColumnIndex('fullname')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
parent: resultSet.getDouble(resultSet.getColumnIndex('parent')),
treePath: resultSet.getString(resultSet.getColumnIndex('treePath'))
};
}
}
// 实体类型定义
interface HuanzhelastEntity {
_id: number;
id: number;
fullname: string;
name: string;
parent: number;
treePath: string;
}
export const huanzheDb = new HuanzhelasDbHelper()

View File

@ -151,7 +151,7 @@ class HdHttp {
logger.info('Response httpReq:' + data.result);
let json:TimestampBean = JSON.parse(data.result.toString()) as TimestampBean;
let tp = json.timestamp;
datas.set("user_uuid", authStore.getUser().uuid?authStore.getUser().uuid:'5kO57cuAL8seXQpxgtc');
datas.set("user_uuid", authStore.getUser().uuid?authStore.getUser().uuid:'');
datas.set("client_type", 'A');
datas.set("version",'4.0.0' );
datas.set('timestamp',tp+'');

View File

@ -8,8 +8,12 @@ export { VideoMore } from './src/main/ets/pages/VideoMore'
export { VideoDetailModel } from './src/main/ets/model/VideoDetailModel'
export { VideoCommentModel,commentModel } from './src/main/ets/model/VideoCommentModel'
export { PastVideo } from './src/main/ets/pages/PastVideo';
export { VideoGandan } from './src/main/ets/pages/VideoGandan';
export { PLVMockMediaResourceData } from './src/main/ets/polyv/PLVMockMediaResourceData'
export { VideoDetailsComment } from './src/main/ets/components/VideoDetailsComment'

View File

@ -0,0 +1,37 @@
import { BasicConstant, authStore } from '@itcast/basic'
import { commentModel } from '../model/VideoCommentModel'
@Preview
@Component
export struct CommentChildView {
@Prop model:commentModel;
@State isShowMoreComment:boolean = false;
build() {
Column() {
Row() {
Row({ space: 10 }) {
Image(BasicConstant.urlHtml + this.model.photo)
.alt($r('app.media.userPhoto_default'))
.width(34).height(34)
.borderRadius(3.4)
Text(this.model.user_status == 1 ? this.model.name : '账号已注销')
.fontSize(16).fontColor('#333333')
.height('100%')
.alignSelf(ItemAlign.Start)
}
.margin({ left: 10, right: authStore.getUser().uuid == this.model.user_uuid ? 35 : 65 })
.layoutWeight(1)//权重自定义
.justifyContent(FlexAlign.Start)
}.width('100%').height(40).margin({top:15}).alignItems(VerticalAlign.Center)
Column() {
Text(this.model.content)
.fontSize(15).fontColor('#666666')
Text(this.model.create_date)
.margin({top:5})
.fontSize(14)
.fontColor('#999999')
}.margin({left:50}).alignItems(HorizontalAlign.Start).width('calc(100% - 70vp)')
}
}
}

View File

@ -66,8 +66,7 @@ export struct ItemCompVideo {
this.goPLVMediaPlayerSingleVideoPage(json.video.polyv_uuid,video_uuid)
}).catch((err: BusinessError) => {
this.goPLVMediaPlayerSingleVideoPage('','')
})
}

View File

@ -0,0 +1,138 @@
import { BasicConstant, authStore } from '@itcast/basic'
import { commentModel } from '../model/VideoCommentModel'
import { CommentChildView } from '../components/CommentChildView'
import { router,promptAction } from '@kit.ArkUI';
import { hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import HashMap from '@ohos.util.HashMap';
import { BusinessError,emitter } from '@kit.BasicServicesKit';
import { rcp } from '@kit.RemoteCommunicationKit';
@Preview
@Component
export struct VideoDetailsComment {
@Prop model:commentModel;
@Prop videoCommentUuid:string;
@State isShowMoreComment:boolean = false;
deleteComment() {
const updateDataUrl:string = BasicConstant.deleteComment;
const postContent = new rcp.MultipartForm({
'uuid': this.model.comment_uuid
})
const session = rcp.createSession();
session.post(updateDataUrl, postContent)
.then((response) => {
if (response.statusCode == 200) {
emitter.emit({
eventId: 250529,
priority: emitter.EventPriority.HIGH
})
promptAction.showToast({ message: '删除评论成功', duration: 1000 })
}
})
.catch((err: BusinessError) => {
console.error(`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`);
})
}
build() {
Column() {
Row() {
Row({ space: 10 }) {
Image(BasicConstant.urlHtml + this.model.photo)
.alt($r('app.media.userPhoto_default'))
.width(40).height(40)
.borderRadius(4)
Text(this.model.user_status == 1 ? this.model.name : '账号已注销')
.fontSize(16).fontColor('#333333')
.height('100%')
.alignSelf(ItemAlign.Start)
}
.margin({ left: 10, right: authStore.getUser().uuid == this.model.user_uuid ? 35 : 65 })
.layoutWeight(1)//权重自定义
.justifyContent(FlexAlign.Start)
if (authStore.getUser().uuid == this.model.user_uuid) {
Image($r('app.media.video_comment_delete'))
.width(20).height(20).margin({right:15})
.onClick(()=>{
promptAction.showDialog({ title: '温馨提示', message: '确定要删除评论?',
buttons: [{ text: '取消', color: '#666666' }, { text: '确定', color: $r('app.color.main_color') }],
})
.then(data => {
if (data.index == 1) {
this.deleteComment();
}
})
})
} else {
Text('回复')
.textAlign(TextAlign.Center)
.width(50).height(25).margin({right:15})
.borderRadius(10)
.backgroundColor('#f4f4f4')
.borderWidth(1).borderColor($r('app.color.main_color'))
.fontSize(16).fontColor($r('app.color.main_color'))
.onClick(() => {
if (this.model.user_status === 1) {
router.pushUrl({
params:{'replyName':this.model.name,'comment_id':this.videoCommentUuid,'comment':this.model.content},
url: 'pages/VideoPage/CommentReplyPage'
})
} else {
promptAction.showToast({ message: '该评论无法回复', duration: 1000 })
}
})
}
}.width('100%').height(40).margin({top:15}).alignItems(VerticalAlign.Center)
Column() {
Text(this.model.content)
.fontSize(15).fontColor('#666666')
Text(this.model.create_date)
.margin({top:5})
.fontSize(14)
.fontColor('#999999')
}.margin({left:50}).alignItems(HorizontalAlign.Start).width('calc(100% - 70vp)')
Column() {
if (this.model.childs.length > 3) {
ForEach(this.model.childs.slice(0, this.isShowMoreComment ? this.model.childs.length : 3),
(childModels: commentModel) => {
ListItem() {
CommentChildView({model:childModels});
}
.width('100%')
})
this.dynamicFooter((isShow: boolean) => {
this.isShowMoreComment = isShow;
});
} else {
ForEach(this.model.childs, (childModels: commentModel) => {
CommentChildView({model:childModels});
})
}
}
.margin({left:50}).alignItems(HorizontalAlign.Start).width('calc(100% - 70vp)')
Divider()
.color(Color.White)
.width('100%').strokeWidth(1).margin({top:5})
}
}
// Footer构建器
@Builder
dynamicFooter(onClick: (isShow:boolean) => void ) {
Row({space:5}) {
Text(this.isShowMoreComment ? '--收起' : '--展开更多回复')
.fontColor($r('app.color.main_color'))
.fontSize(13)
Image(this.isShowMoreComment?$r('app.media.closePinglun'):$r('app.media.openPinglun'))
.width(15).height(15)
}
.width(200)
.height(30)
.justifyContent(FlexAlign.Start)
.onClick(()=>onClick(!this.isShowMoreComment))
}
}

View File

@ -0,0 +1,22 @@
export interface VideoCommentModel{
code:string;
data:commentModel[];
message:string;
msg:string
}
export interface commentModel{
name:string;
id:number;
create_date:string;
user_uuid:string;
parent_id:string;
comment_uuid:string;
status:number;
content:string;
examine_status:number;
childs:commentModel[];
is_parent:boolean;
photo:string;
user_status:number;
}

View File

@ -121,6 +121,7 @@ export struct PastVideo {
}
}, (item: string) => JSON.stringify(item))
} .width('100%')
.zIndex(2)
.height('100%').backgroundColor(Color.White)
}
if(this.typelistStatus)
@ -162,6 +163,8 @@ export struct PastVideo {
}
}, (item: string) => JSON.stringify(item))
} .width('100%')
.zIndex(3)
.height('100%').backgroundColor(Color.White)
}
}

View File

@ -170,7 +170,7 @@ export struct PlayBack {
.height('100%').backgroundColor(Color.White)
}
}
.layoutWeight(1)
}
.width('100%')
.height('100%')

View File

@ -90,7 +90,7 @@ export struct LoginComp {
getSaveUserInfor(type:number,objs:LoginInfo) {
let state:number=objs.data.state
if(state!=6) {
perfactAuth.initUser(this.mobile)
// perfactAuth.initUser(this.mobile)
router.pushUrl({
url: 'pages/LoginPage/LoginSetInfoPage', // 目标url
params: {

View File

@ -6,8 +6,10 @@
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@ohos/crypto-js@^2.0.4": "@ohos/crypto-js@2.0.4",
"@ohos/dataorm@^2.2.6": "@ohos/dataorm@2.2.6",
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
"@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
"@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21",
"reflect-metadata@^0.1.13": "reflect-metadata@0.2.1"
},
"packages": {
"@ohos/crypto-js@2.0.4": {
@ -17,6 +19,16 @@
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/crypto-js/-/crypto-js-2.0.4.har",
"registryType": "ohpm"
},
"@ohos/dataorm@2.2.6": {
"name": "@ohos/dataorm",
"version": "2.2.6",
"integrity": "sha512-qwAQnMxfuG5Imsrq3jjikEUCC/FGqddj0YXe40zUELGdhHegEqkDaxtTp9KIq4fg1ZU/c8fxYNfApx3XZ7E6cA==",
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/dataorm/-/dataorm-2.2.6.har",
"registryType": "ohpm",
"dependencies": {
"reflect-metadata": "^0.1.13"
}
},
"@ohos/hamock@1.0.0": {
"name": "@ohos/hamock",
"version": "1.0.0",
@ -30,6 +42,14 @@
"integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
"resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
"registryType": "ohpm"
},
"reflect-metadata@0.2.1": {
"name": "reflect-metadata",
"version": "0.2.1",
"integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==",
"resolved": "https://repo.harmonyos.com/ohpm/reflect-metadata/-/reflect-metadata-0.2.1.tgz",
"shasum": "8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74",
"registryType": "ohpm"
}
}
}

View File

@ -2,7 +2,8 @@
"modelVersion": "5.0.2",
"description": "Please describe the basic information.",
"dependencies": {
"@ohos/crypto-js": "^2.0.4"
"@ohos/crypto-js": "^2.0.4",
"@ohos/dataorm": "^2.2.6"
},
"devDependencies": {
"@ohos/hypium": "1.0.21",

View File

@ -14,16 +14,17 @@ export class PLVOrientationManager {
}
readonly isPortrait: MutableState<boolean> = new MutableState(isPortrait())
requestOrientation(orientation: 'port' | 'land') {
const context = PLVAbilityContexts.getInstance().lastContext()
console.info('requestOrientation', orientation, context)
const windowOrientation = orientation === 'port' ? window.Orientation.PORTRAIT : window.Orientation.LANDSCAPE
if (!context) {
console.info('No context found')
return
}
window.getLastWindow(context).then((lastWindow) => {
console.info('Got lastWindow', lastWindow)
lastWindow.setPreferredOrientation(windowOrientation)
})
}
}

View File

@ -0,0 +1,177 @@
import { huanzheDb } from '@itcast/basic';
import { Huanzhelast444Model } from '@itcast/basic';
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import relationalStore from '@ohos.data.relationalStore';
export interface Huanzhelast444Result {
code: number; // 0: 成功, 1: 文件不存在, 2: 表不存在, 3: 其它错误
msg: string;
data?: Huanzhelast444Model[];
}
export class Huanzhelast444Dao {
/**
* 获取所有患者数据,并检查数据库文件和表是否存在。
* @param context 应用上下文
* @returns Huanzhelast444Result
*/
// static async getAll(context: common.Context): Promise<Huanzhelast444Result> {
// console.info('getAll called');
// const dbFileName = 'huanzhelas.sqlite';
// const dbPath = context.filesDir + '/' + dbFileName;
// // 1. 检查数据库文件是否存在
// let fileExists = false;
// try {
// fileExists = fs.accessSync(dbPath);
// } catch (e) {
// fileExists = false;
// }
// // 2. 如不存在则尝试复制
// if (!fileExists) {
// try {
// const resourceMgr = context.resourceManager;
// const rawFile = await resourceMgr.getRawFileContent(dbFileName);
// const arrayBuffer = rawFile.buffer;
// // 确保目录存在
// try { fs.accessSync(context.filesDir); } catch (e) { fs.mkdirSync(context.filesDir); }
// // 复制前删除旧文件
// if (fs.accessSync(dbPath)) {
// fs.unlinkSync(dbPath);
// }
// // 复制数据库文件(确保完整写入)
// const file = fs.openSync(dbPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
// const buffer = new Uint8Array(arrayBuffer);
// fs.writeSync(file.fd, buffer, 0, buffer.length);
// fs.closeSync(file);
// // 复制后校验文件大小
// const stat = fs.statSync(dbPath);
// console.info('数据库文件大小:', stat.size, '原始大小:', buffer.length);
// fs.accessSync(dbPath); // 再次检查
// fileExists = true;
// } catch (e) {
// return { code: 1, msg: '数据库文件移动失败: ' + e };
// }
// }
// // 3. 初始化数据库并查询
// try {
// await huanzheDb.initDatabase(context);
// // 直接用 helper 的查询方法
// const rawList = await huanzheDb.queryHuanzhelastData() as Partial<Huanzhelast444Model>[];
// // 用 Huanzhelast444Model 构造实例数组
// const dataList: Huanzhelast444Model[] = rawList.map((item) => new Huanzhelast444Model(
// item._id ?? 0,
// item.id ?? 0,
// item.fullname ?? '',
// item.name ?? '',
// item.parent ?? 0,
// item.treePath ?? ''
// ));
// console.info('getAll return:', JSON.stringify({ code: 0, msg: '查询成功', data: dataList }));
// return { code: 0, msg: '查询成功', data: dataList };
// } catch (e) {
// // 判断表不存在的情况
// if (typeof e === 'string' && e.indexOf('no such table') !== -1) {
// return { code: 2, msg: '表 t_huanzhelast444 不存在' };
// }
// return { code: 3, msg: '数据查询失败: ' + e };
// }
// }
/**
* 直接独立实现:获取所有患者数据,判断文件移动、表存在、数据查询。
* @param context 应用上下文
* @returns Huanzhelast444Result
*/
static async getAllDirect(context: common.Context): Promise<Huanzhelast444Result> {
const dbFileName = 'huanzhelas.sqlite';
const dbPath = context.databaseDir + '/' + dbFileName;
// 1. 检查数据库文件是否存在
let fileExists = fs.accessSync(dbPath);
// 2. 如不存在则尝试复制
if (!fileExists) {
try {
const resourceMgr = context.resourceManager;
const rawFile = await resourceMgr.getRawFileContent(dbFileName);
const arrayBuffer = rawFile.buffer;
// 确保目录存在
try { fs.accessSync(context.databaseDir); } catch (e) { fs.mkdirSync(context.databaseDir); }
// 复制前删除旧文件
if (fs.accessSync(dbPath)) {
fs.unlinkSync(dbPath);
}
// 复制数据库文件(确保完整写入)
const file = fs.openSync(dbPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
const buffer = new Uint8Array(arrayBuffer);
fs.writeSync(file.fd, buffer); // offset=0, length=buffer.length
fs.closeSync(file);
// 复制后校验文件大小
const stat = fs.statSync(dbPath);
console.info('数据库文件大小:', stat.size, '原始大小:', buffer.length);
fileExists = true;
} catch (e) {
return { code: 1, msg: '数据库文件移动失败: ' + e } as Huanzhelast444Result;
}
}
// 3. 用 relationalStore 直接操作数据库
let rdbStore: relationalStore.RdbStore | null = null;
try {
const storeConfig: relationalStore.StoreConfig = { name: dbFileName, securityLevel: relationalStore.SecurityLevel.S1 };
rdbStore = await relationalStore.getRdbStore(context, storeConfig);
} catch (e) {
return { code: 1, msg: '数据库文件打开失败: ' + e } as Huanzhelast444Result;
}
// 4. 检查表是否存在
try {
// 复制后,打印所有表名
const resultSet = await rdbStore.querySql("SELECT name FROM sqlite_master WHERE type='table'", []);
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
do {
console.info('数据库中存在的表:', resultSet.getString(0));
} while (resultSet.goToNextRow());
}
resultSet.close();
// const resultSet = await rdbStore.querySql("SELECT name FROM sqlite_master WHERE type='table' AND name='t_huanzhelast444'", []);
// let hasTable = false;
// if (resultSet.rowCount > 0) {
// resultSet.goToFirstRow();
// do {
// if (resultSet.getString(0) === 't_huanzhelast444') {
// hasTable = true;
// break;
// }
// } while (resultSet.goToNextRow());
// }
// resultSet.close();
// if (!hasTable) {
// return { code: 2, msg: '表 t_huanzhelast444 不存在' } as Huanzhelast444Result;
// }
} catch (e) {
return { code: 3, msg: '表检查失败: ' + e } as Huanzhelast444Result;
}
// 5. 查询所有数据
try {
const resultSet = await rdbStore.querySql('SELECT _id, id, fullname, name, parent, treePath FROM t_huanzhelast444', []);
const dataList: Huanzhelast444Model[] = [];
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
do {
dataList.push(new Huanzhelast444Model(
resultSet.getDouble(0),
resultSet.getDouble(1),
resultSet.getString(2),
resultSet.getString(3),
resultSet.getDouble(4),
resultSet.getString(5)
));
} while (resultSet.goToNextRow());
}
resultSet.close();
return { code: 0, msg: '查询成功', data: dataList } as Huanzhelast444Result;
} catch (e) {
return { code: 3, msg: '数据查询失败: ' + e } as Huanzhelast444Result;
}
}
}

View File

@ -1,5 +1,4 @@
import { MyHomePage } from 'mypage'
import { emitter } from '@kit.BasicServicesKit';
@Entry
@Component

View File

@ -0,0 +1,76 @@
import { HdNav,BasicConstant } from '@itcast/basic'
import { emitter } from '@kit.BasicServicesKit'
import { router,promptAction } from '@kit.ArkUI';
import { hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import HashMap from '@ohos.util.HashMap';
import { BusinessError } from '@kit.BasicServicesKit';
import inputMethod from '@ohos.inputMethod';
@Entry
@Component
struct CommentReplyPage {
@State params:Record<string, string> = router.getParams() as Record<string, string>;
@State finalContent: string = '';
hashMap: HashMap<string, string> = new HashMap();
aboutToAppear() {
emitter.on({ eventId: 250516 }, () => {
this.commitAction()
})
}
aboutToDisappear() {
emitter.off(250516)
}
commitAction() {
inputMethod.getController().hideTextInput();//关闭键盘
if (this.finalContent.length === 0) {
promptAction.showToast({ message: '请输入回复内容', duration: 1000 })
return;
}
this.hashMap.clear();
this.hashMap.set('article_uuid', this.params.comment_id)
this.hashMap.set('comment', `${this.finalContent}||${this.params.replyName}${this.params.comment}`)
this.hashMap.set('type', '8')
hdHttp.httpReq<string>(BasicConstant.addCommentV2,this.hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response replyComment:'+res);
let json:CommentV2Model = JSON.parse(res+'') as CommentV2Model;
if(json.code == 200) {
emitter.emit({
eventId: 250529,
priority: emitter.EventPriority.HIGH
})
promptAction.showToast({ message: '回复评论成功', duration: 1000 })
router.back();
} else {
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
})
}
build() {
Column() {
HdNav({ title: '回复', showRightIcon: false, showLeftIcon: true,showRightText:true,rightText:'确定'})
TextArea({placeholder:`回复:${this.params.replyName}`})
.fontSize(14)
.width('100%')
.height('50%')
.backgroundColor(Color.White)
.onChange((value: string) => {
this.finalContent = value; // 实时更新临时内容[3](@ref)
console.info('回复输入框内容:', this.finalContent);
})
}
.height('100%')
.width('100%')
}
}
export interface CommentV2Model{
code:number;
data:Object[];
message:string;
msg:string
}

View File

@ -10,16 +10,18 @@ import {
} from 'media-player-common';
import common from '@ohos.app.ability.common';
import window from '@ohos.window';
import router from '@ohos.router';
import { createDependScope } from '@polyvharmony/media-player-sdk'
import {
commonPageModule,
commonPageModule,getDisplayWindowWidth
} from 'media-player-common'
import { HdNav,BasicConstant } from '@itcast/basic'
import HashMap from '@ohos.util.HashMap';
import { hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import { VideoDetailModel } from 'home'
import { emitter,BusinessError } from '@kit.BasicServicesKit';
import { VideoDetailModel,VideoCommentModel,commentModel,VideoDetailsComment } from 'home'
import { router,promptAction } from '@kit.ArkUI';
import inputMethod from '@ohos.inputMethod';
@Entry
@Component
export struct PLVMediaPlayerSingleVideoPage {
@ -32,7 +34,10 @@ export struct PLVMediaPlayerSingleVideoPage {
private pageControlViewModel: PLVMPPageControlViewModel = this.pageDependScope.get(PLVMPPageControlViewModel)
private onBackPressDisposable: Disposable | undefined = undefined
private readonly plv_media_player_single_video_background: string = createId()
hashMap: HashMap<string, string> = new HashMap();
@State isPortrait: boolean = true;//是否竖屏
@State commentList:Array<commentModel> = [];//评论列表
@State commentContent:string = '';//评论内容
@State note:string=''
aboutToAppear(): void {
@ -43,7 +48,19 @@ export struct PLVMediaPlayerSingleVideoPage {
windowInstance.setWindowKeepScreenOn(true)
})
this.getVideoDetail(this.params.video_uuid)
this.getCommentdata(this.params.video_uuid)
PLVOrientationManager.getInstance().isPortrait.observe((isPortrait) => {
if (typeof isPortrait === 'boolean') {
this.isPortrait = isPortrait
}
})
emitter.on({ eventId: 250529 }, () => {
this.getCommentdata(this.params.video_uuid)
})
}
@State currentIndex: number = 0;
@Builder tabBuilder(title: string, targetIndex: number) {
@ -61,7 +78,10 @@ export struct PLVMediaPlayerSingleVideoPage {
}
build() {
Column(){
if (this.isPortrait) {
HdNav({ title: '视频详情', showRightIcon: false, showLeftIcon: true })
}
Stack() {
// 背景图
// Image($r('app.media.plv_media_player_video_item_background_portrait'))
@ -78,21 +98,62 @@ export struct PLVMediaPlayerSingleVideoPage {
PLVOrientationManagerObserver()
}
.width('100%')
.height(204)
.height(this.getPlayerAreaHeight())
Tabs() {
TabContent() {
Text(this.note).fontSize(14).fontColor(Color.Black)
}
.align(Alignment.TopStart)
.padding(15)
.tabBar(this.tabBuilder('视频简介', 0))
.customTabbar('视频简介')
TabContent() {
Text('推荐的内容').fontSize(30).alignSelf(ItemAlign.Start)
Column() {
List(){
ForEach(this.commentList,(model:commentModel)=>{
ListItem(){
VideoDetailsComment({model:model,videoCommentUuid:this.params.video_uuid});
}
.tabBar(this.tabBuilder('评论', 1))
})
}.height('calc(100% - 100vp)').width('100%').backgroundColor('#f4f4f4').scrollBar(BarState.Off)
Row({space:10}) {
Row() {
TextInput({ placeholder: '我也说一句',text:this.commentContent })
.fontSize(17)
.backgroundColor(Color.White)
.width('95%')
.onChange((value: string) => {
this.commentContent = value; // 实时更新临时内容[3](@ref)
console.info('视频详情评论输入框内容:', this.commentContent);
})
}.borderRadius(5).borderWidth(1).borderColor('#333333').backgroundColor(Color.White).height(50).width('calc(100% - 100vp)')
.margin({ left: 10,top: 10 })
}.layoutWeight(1)
Button('发送')
.borderRadius(5)
.type(ButtonType.ROUNDED_RECTANGLE)
.backgroundColor($r('app.color.main_color'))
.fontColor(Color.White)
.fontSize(17)
.width(70).height(50)
.margin({top:10})
.onClick(()=>{
this.addComment();
})
}.backgroundColor(Color.White).width('100%').height(100).justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Top)
// Button('推荐的内容').fontSize(30).alignSelf(ItemAlign.Start)
}
.justifyContent(FlexAlign.End)
}
.backgroundColor('#f4f4f4')
.customTabbar('评论')
}
.divider( {
strokeWidth: 1,
color: $r('app.color.common_gray_border'),
})
.layoutWeight(1)
.onChange((index: number) => {
this.currentIndex = index;
})
@ -100,6 +161,14 @@ export struct PLVMediaPlayerSingleVideoPage {
}
getPlayerAreaHeight(): string | number {
if (this.isPortrait) {
return getDisplayWindowWidth().vp / 16 * 9
} else {
return '100%'
}
}
onBackPress(): boolean {
if (!PLVOrientationManager.getInstance().isPortrait.value) {
PLVOrientationManager.getInstance().requestOrientation('port');
@ -114,26 +183,84 @@ export struct PLVMediaPlayerSingleVideoPage {
const windowInstance = await window.getLastWindow(this.context)
windowInstance.setWindowKeepScreenOn(false)
})
emitter.off(250529)
}
getVideoDetail(video_uuid:string)
{
this.hashMap.clear();
this.hashMap.set('video_uuid', video_uuid)
hdHttp.httpReq<string>(BasicConstant.videoDetail,this.hashMap).then(async (res: HdResponse<string>) => {
getVideoDetail(video_uuid:string) {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.clear();
hashMap.set('video_uuid', video_uuid)
hdHttp.httpReq<string>(BasicConstant.videoDetail,hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response videoDetails'+video_uuid);
logger.info('Response videoDetail'+res);
let json:VideoDetailModel = JSON.parse(res+'') as VideoDetailModel;
this.note=json.video.note
}).catch((err: BusinessError) => {
})
}
getCommentdata(video_uuid:string) {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.clear();
hashMap.set('uuid', video_uuid)
hdHttp.httpReq<string>(BasicConstant.videoCommentListV2,hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response videoDetails commentList:'+video_uuid);
logger.info('Response videoDetail commentList:'+res);
let json:VideoCommentModel = JSON.parse(res+'') as VideoCommentModel;
if(json.data != null && json.data!) {
this.commentList = json.data;
}
}).catch((err: BusinessError) => {
})
}
addComment() {
inputMethod.getController().hideTextInput();//关闭键盘
if (this.commentContent.length == 0) {
promptAction.showToast({ message: '请输入评论内容', duration: 1000 })
return;
}
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('article_uuid', this.params.video_uuid)
hashMap.set('comment', this.commentContent)
hashMap.set('type', '8')
hdHttp.httpReq<string>(BasicConstant.addCommentV2,hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response replyComment:'+res);
let json:CommentV2Model = JSON.parse(res+'') as CommentV2Model;
if(json.code == 200) {
promptAction.showToast({ message: '发表评论成功', duration: 1000 })
this.getCommentdata(this.params.video_uuid);
this.commentContent = '';
} else {
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
})
}
}
interface VideoPageParam
{
@Extend(TabContent)
function customTabbar(name:string) {
.tabBar(SubTabBarStyle.of(name)
.labelStyle({ unselectedColor: '#848284', selectedColor:'#8D2316' , font: { size: 17 }})
.indicator({
color: '#8D2316', //下划线颜色
height: 1, //下划线高度
marginTop:16 //下划线与文字间距
}))
.height('100%')
}
interface VideoPageParam {
video_uuid:string
param:PLVMediaPlayerSingleVideoPageParam
}
export interface CommentV2Model{
code:number;
data:Object[];
message:string;
msg:string
}

View File

@ -24,6 +24,7 @@
"pages/VideoPage/PLVMediaPlayerSingleVideoPage",
"pages/WebView/LivebroadcastPages",
"pages/VideoPage/PastVideoPage",
"pages/VideoPage/VideoGandanPage"
"pages/VideoPage/VideoGandanPage",
"pages/VideoPage/CommentReplyPage"
]
}

View File

@ -25,6 +25,8 @@ import {
import { PLVMediaPlayerAuxiliaryLayout } from './component/PLVMediaPlayerAuxiliaryLayout';
import { PLVMediaPlayerSingleVideoControllerLayout } from './layout/PLVMediaPlayerSingleVideoControllerLayout';
import { PLVMediaPlayerSingleVideoFloatActionLayout } from './layout/PLVMediaPlayerSingleVideoFloatActionLayout';
import {PLVAbilityContexts} from 'media-player-common';
import common from '@ohos.app.ability.common';
@Preview
@Component
@ -55,6 +57,8 @@ export struct PLVMediaPlayerSingleVideoLayout {
aboutToAppear(): void {
requireNotNull(this.mediaResource, () => 'mediaResource must not be null')
const context = getContext(this) as common.UIAbilityContext;
PLVAbilityContexts.getInstance().registerContext(context)
this.observeMediaViewState()
this.observeOrientation()
this.downloadItemViewModel.setDownloadActionVisible(!this.enterFromDownloadCenter)
@ -71,6 +75,7 @@ export struct PLVMediaPlayerSingleVideoLayout {
this.viewModel.setPlayerOption([
PLVMediaPlayerOptionEnum.ENABLE_ACCURATE_SEEK.value("1"),
PLVMediaPlayerOptionEnum.SKIP_ACCURATE_SEEK_AT_START.value("1"),
PLVMediaPlayerOptionEnum.START_ON_PREPARED.value("0"),
])
this.viewModel.setMediaResource(this.mediaResource)
}