Initial commit: Flutter 无书应用项目
This commit is contained in:
20
ohos/.gitignore
vendored
Normal file
20
ohos/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
**/BuildProfile.ets
|
||||
**/oh-package-lock.json5
|
||||
/package.json
|
||||
/package-lock.json
|
||||
|
||||
**/src/main/resources/rawfile/flutter_assets/
|
||||
**/libs/**/libapp.so
|
||||
**/libs/**/libflutter.so
|
||||
**/libs/**/libvmservice_snapshot.so
|
||||
10
ohos/AppScope/app.json5
Normal file
10
ohos/AppScope/app.json5
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "app.whushu.poes",
|
||||
"vendor": "example",
|
||||
"versionCode": 26032601,
|
||||
"versionName": "1.5.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
||||
8
ohos/AppScope/resources/base/element/string.json
Normal file
8
ohos/AppScope/resources/base/element/string.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "flutter_application_2"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
ohos/AppScope/resources/base/media/app_icon.png
Normal file
BIN
ohos/AppScope/resources/base/media/app_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
67
ohos/build-profile.json5
Normal file
67
ohos/build-profile.json5
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [
|
||||
{
|
||||
"name": "default",
|
||||
"type": "HarmonyOS",
|
||||
"material": {
|
||||
"certpath": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.cer",
|
||||
"keyAlias": "debugKey",
|
||||
"keyPassword": "0000001BF7F4F2744D33517095133386B3CAD90A3AB42BFD0069CF7CBFDFCAEE521062FD5D9C3EBA827534",
|
||||
"profile": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p7b",
|
||||
"signAlg": "SHA256withECDSA",
|
||||
"storeFile": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p12",
|
||||
"storePassword": "0000001B8B77ACFC8F396F2040DA9156A7482FCF2AADA0B573BCAD12D0612BC813F694D501263B5961FB96"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rele",
|
||||
"type": "HarmonyOS",
|
||||
"material": {
|
||||
"certpath": "C:/Users/无书/Desktop/签名/520kiss123.cer",
|
||||
"keyAlias": "520kiss123",
|
||||
"keyPassword": "0000001AFB03935394E980F7E15F953FCD2AE86B72D10BFA1CD63ED86241692114C64F73093C17F2B715",
|
||||
"profile": "C:/Users/无书/Desktop/签名/520kiss123.p7b",
|
||||
"signAlg": "SHA256withECDSA",
|
||||
"storeFile": "C:/Users/无书/Desktop/签名/520kiss123.p12",
|
||||
"storePassword": "0000001A7E63450C86AEA2810CF4C8A92877AA980D6BCE46E392AEA3F4446CEBB21D1733E5F7581EBF22"
|
||||
}
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
// "signingConfig": "default",
|
||||
"signingConfig": "default",
|
||||
"compatibleSdkVersion": "5.0.0(12)",
|
||||
"runtimeOS": "HarmonyOS",
|
||||
"targetSdkVersion": "6.0.2(22)"
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug"
|
||||
},
|
||||
{
|
||||
"name": "profile"
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
7
ohos/entry/.gitignore
vendored
Normal file
7
ohos/entry/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
GeneratedPluginRegistrant.ets
|
||||
15
ohos/entry/build-profile.json5
Normal file
15
ohos/entry/build-profile.json5
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
{
|
||||
"apiType": 'stageMode',
|
||||
"buildOption": {
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"runtimeOS": "HarmonyOS"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
||||
7
ohos/entry/hvigorfile.ts
Normal file
7
ohos/entry/hvigorfile.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
|
||||
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
export default {
|
||||
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
11
ohos/entry/oh-package.json5
Normal file
11
ohos/entry/oh-package.json5
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
{
|
||||
"name": "entry",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {},
|
||||
}
|
||||
|
||||
156
ohos/entry/src/main/ets/ability/WidgetMenuAbility.ets
Normal file
156
ohos/entry/src/main/ets/ability/WidgetMenuAbility.ets
Normal file
@@ -0,0 +1,156 @@
|
||||
import { UIAbility, Want, AbilityConstant, Configuration } from '@kit.AbilityKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { common } from '@kit.AbilityKit';
|
||||
|
||||
interface MenuOption {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
action: string;
|
||||
}
|
||||
|
||||
export default class WidgetMenuAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
console.info('[WidgetMenuAbility] onCreate');
|
||||
this.showWidgetMenu();
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
console.info('[WidgetMenuAbility] onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
console.info('[WidgetMenuAbility] onWindowStageCreate');
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
console.info('[WidgetMenuAbility] onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
console.info('[WidgetMenuAbility] onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
console.info('[WidgetMenuAbility] onBackground');
|
||||
}
|
||||
|
||||
onConfigurationUpdate(newConfig: Configuration): void {
|
||||
console.info('[WidgetMenuAbility] onConfigurationUpdate');
|
||||
}
|
||||
|
||||
private showWidgetMenu(): void {
|
||||
try {
|
||||
console.info('[WidgetMenuAbility] Show widget menu');
|
||||
|
||||
const menuOptions: MenuOption[] = [
|
||||
{
|
||||
id: 'open_app',
|
||||
name: '📱 打开应用',
|
||||
description: '启动诗词卡片主应用',
|
||||
icon: '📱',
|
||||
action: 'open_app'
|
||||
},
|
||||
{
|
||||
id: 'widget_settings',
|
||||
name: '⚙️ 卡片设置',
|
||||
description: '进入卡片详细设置页面',
|
||||
icon: '⚙️',
|
||||
action: 'open_widget_settings'
|
||||
},
|
||||
{
|
||||
id: 'classic',
|
||||
name: '🎨 经典风格',
|
||||
description: '传统诗词卡片样式',
|
||||
icon: '🎨',
|
||||
action: 'change_style'
|
||||
},
|
||||
{
|
||||
id: 'modern',
|
||||
name: '✨ 现代风格',
|
||||
description: '简洁现代的设计风格',
|
||||
icon: '✨',
|
||||
action: 'change_style'
|
||||
},
|
||||
{
|
||||
id: 'minimal',
|
||||
name: '◽ 极简风格',
|
||||
description: '最小化设计,突出内容',
|
||||
icon: '◽',
|
||||
action: 'change_style'
|
||||
},
|
||||
{
|
||||
id: 'elegant',
|
||||
name: '💎 优雅风格',
|
||||
description: '精致优雅的视觉效果',
|
||||
icon: '💎',
|
||||
action: 'change_style'
|
||||
}
|
||||
];
|
||||
|
||||
console.info('[WidgetMenuAbility] Menu options: ' + JSON.stringify(menuOptions));
|
||||
|
||||
// 处理菜单选择
|
||||
this.handleMenuSelection(menuOptions[0]);
|
||||
} catch (error) {
|
||||
console.error('[WidgetMenuAbility] showWidgetMenu error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private handleMenuSelection(option: MenuOption): void {
|
||||
console.info('[WidgetMenuAbility] Selected option: ' + option.id);
|
||||
|
||||
if (option.action === 'open_app') {
|
||||
this.openMainApp();
|
||||
} else if (option.action === 'open_widget_settings') {
|
||||
this.openWidgetSettings();
|
||||
} else if (option.action === 'change_style') {
|
||||
this.changeCardStyle(option.id);
|
||||
}
|
||||
}
|
||||
|
||||
private openMainApp(): void {
|
||||
try {
|
||||
const want: Want = {
|
||||
bundleName: this.context.applicationInfo.name,
|
||||
abilityName: 'EntryAbility'
|
||||
};
|
||||
|
||||
this.context.startAbility(want).then(() => {
|
||||
console.info('[WidgetMenuAbility] Open main app success');
|
||||
}).catch((error: BusinessError) => {
|
||||
console.error('[WidgetMenuAbility] Open main app error: ' + JSON.stringify(error));
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[WidgetMenuAbility] openMainApp error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private openWidgetSettings(): void {
|
||||
try {
|
||||
const want: Want = {
|
||||
bundleName: this.context.applicationInfo.name,
|
||||
abilityName: 'EntryAbility',
|
||||
parameters: {
|
||||
'route': '/widgets_page'
|
||||
}
|
||||
};
|
||||
|
||||
this.context.startAbility(want).then(() => {
|
||||
console.info('[WidgetMenuAbility] Open widget settings success');
|
||||
}).catch((error: BusinessError) => {
|
||||
console.error('[WidgetMenuAbility] Open widget settings error: ' + JSON.stringify(error));
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[WidgetMenuAbility] openWidgetSettings error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private changeCardStyle(style: string): void {
|
||||
console.info('[WidgetMenuAbility] Change card style to: ' + style);
|
||||
// 保存样式设置到本地存储
|
||||
// 触发卡片更新
|
||||
}
|
||||
}
|
||||
74
ohos/entry/src/main/ets/entryability/EntryAbility.ets
Normal file
74
ohos/entry/src/main/ets/entryability/EntryAbility.ets
Normal file
@@ -0,0 +1,74 @@
|
||||
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
|
||||
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
|
||||
import { Want, AbilityConstant } from '@kit.AbilityKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { router, window } from '@kit.ArkUI';
|
||||
|
||||
export default class EntryAbility extends FlutterAbility {
|
||||
private targetPage: string = '';
|
||||
private formName: string = '';
|
||||
|
||||
configureFlutterEngine(flutterEngine: FlutterEngine): void {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
GeneratedPluginRegistrant.registerWith(flutterEngine)
|
||||
|
||||
hilog.info(0x0000, 'EntryAbility', 'FlutterEngine configured');
|
||||
}
|
||||
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
super.onCreate(want, launchParam);
|
||||
hilog.info(0x0000, 'EntryAbility', 'onCreate called');
|
||||
|
||||
if (want.parameters) {
|
||||
this.targetPage = want.parameters['targetPage'] as string || '';
|
||||
this.formName = want.parameters['formName'] as string || '';
|
||||
hilog.info(0x0000, 'EntryAbility', 'targetPage: ' + this.targetPage + ', formName: ' + this.formName);
|
||||
}
|
||||
}
|
||||
|
||||
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
super.onNewWant(want, launchParam);
|
||||
hilog.info(0x0000, 'EntryAbility', 'onNewWant called');
|
||||
|
||||
if (want.parameters) {
|
||||
this.targetPage = want.parameters['targetPage'] as string || '';
|
||||
this.formName = want.parameters['formName'] as string || '';
|
||||
hilog.info(0x0000, 'EntryAbility', 'targetPage: ' + this.targetPage + ', formName: ' + this.formName);
|
||||
|
||||
if (this.targetPage) {
|
||||
this.navigateToTargetPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
super.onWindowStageCreate(windowStage);
|
||||
hilog.info(0x0000, 'EntryAbility', 'onWindowStageCreate called');
|
||||
|
||||
if (this.targetPage) {
|
||||
setTimeout(() => {
|
||||
this.navigateToTargetPage();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
private navigateToTargetPage(): void {
|
||||
try {
|
||||
hilog.info(0x0000, 'EntryAbility', 'Navigating to: ' + this.targetPage);
|
||||
router.replaceUrl({
|
||||
url: this.targetPage,
|
||||
params: {
|
||||
formName: this.formName
|
||||
}
|
||||
}).then(() => {
|
||||
hilog.info(0x0000, 'EntryAbility', 'Navigation success');
|
||||
this.targetPage = '';
|
||||
this.formName = '';
|
||||
}).catch((err: Error) => {
|
||||
hilog.error(0x0000, 'EntryAbility', 'Navigation failed: ' + err.message);
|
||||
});
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'EntryAbility', 'navigateToTargetPage error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
603
ohos/entry/src/main/ets/formability/WidgetFormAbility.ets
Normal file
603
ohos/entry/src/main/ets/formability/WidgetFormAbility.ets
Normal file
@@ -0,0 +1,603 @@
|
||||
import { FormExtensionAbility, formBindingData, formProvider } from '@kit.FormKit';
|
||||
import { Want } from '@kit.AbilityKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { preferences } from '@kit.ArkData';
|
||||
import { http } from '@kit.NetworkKit';
|
||||
|
||||
interface FormDataContent {
|
||||
title: string;
|
||||
quote: string;
|
||||
author: string;
|
||||
dynasty: string;
|
||||
time: string;
|
||||
weather: string;
|
||||
city: string;
|
||||
style: string;
|
||||
showTime: boolean;
|
||||
showWeather: boolean;
|
||||
showQuote: boolean;
|
||||
formName: string;
|
||||
}
|
||||
|
||||
interface SettingsData {
|
||||
style: string;
|
||||
showTime: boolean;
|
||||
showWeather: boolean;
|
||||
showQuote: boolean;
|
||||
quote: string;
|
||||
author: string;
|
||||
dynasty: string;
|
||||
autoUpdate: boolean;
|
||||
updateInterval: number;
|
||||
selectedSource: string;
|
||||
smallQuote: string;
|
||||
smallAuthor: string;
|
||||
smallDynasty: string;
|
||||
smallShowQuote: boolean;
|
||||
mediumQuote: string;
|
||||
mediumAuthor: string;
|
||||
mediumDynasty: string;
|
||||
mediumShowQuote: boolean;
|
||||
largeQuote: string;
|
||||
largeAuthor: string;
|
||||
largeDynasty: string;
|
||||
largeShowQuote: boolean;
|
||||
}
|
||||
|
||||
interface QuoteData {
|
||||
id: number;
|
||||
name: string;
|
||||
url: string;
|
||||
alias: string;
|
||||
}
|
||||
|
||||
interface ApiResponse {
|
||||
code: number;
|
||||
msg: string;
|
||||
data: QuoteData | null;
|
||||
}
|
||||
|
||||
interface QuoteResult {
|
||||
name: string;
|
||||
url: string;
|
||||
alias: string;
|
||||
}
|
||||
|
||||
interface WeatherData {
|
||||
city: string;
|
||||
weather: string;
|
||||
temp: string;
|
||||
}
|
||||
|
||||
interface WeatherInfo {
|
||||
city: string;
|
||||
weather: string;
|
||||
temp: string;
|
||||
}
|
||||
|
||||
interface CityDZ {
|
||||
weatherinfo: WeatherInfo;
|
||||
}
|
||||
|
||||
interface DataInner {
|
||||
cityDZ: CityDZ;
|
||||
}
|
||||
|
||||
interface DataOuter {
|
||||
data: DataInner;
|
||||
}
|
||||
|
||||
interface WeatherApiResponse {
|
||||
status: string;
|
||||
city: string;
|
||||
data: DataOuter;
|
||||
}
|
||||
|
||||
export default class WidgetFormAbility extends FormExtensionAbility {
|
||||
async onCreate(want: Want): Promise<formBindingData.FormBindingData> {
|
||||
console.info('[WidgetFormAbility] onCreate');
|
||||
const formName = want.parameters?.['formName'] as string || 'WidgetCardSmall';
|
||||
const settings = await this.loadSettings();
|
||||
|
||||
const content = await this.buildFormData(formName, settings);
|
||||
return formBindingData.createFormBindingData(content);
|
||||
}
|
||||
|
||||
private async buildFormData(formName: string, settings: SettingsData): Promise<FormDataContent> {
|
||||
let quote: string;
|
||||
let author: string;
|
||||
let dynasty: string;
|
||||
let showQuote: boolean;
|
||||
|
||||
switch (formName) {
|
||||
case 'WidgetCardSmall':
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
break;
|
||||
case 'WidgetCardMedium':
|
||||
quote = settings.mediumQuote;
|
||||
author = settings.mediumAuthor;
|
||||
dynasty = settings.mediumDynasty;
|
||||
showQuote = settings.mediumShowQuote;
|
||||
break;
|
||||
case 'WidgetCardLarge':
|
||||
quote = settings.largeQuote;
|
||||
author = settings.largeAuthor;
|
||||
dynasty = settings.largeDynasty;
|
||||
showQuote = settings.largeShowQuote;
|
||||
break;
|
||||
default:
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
}
|
||||
|
||||
if (settings.selectedSource === 'api') {
|
||||
const apiQuote = await this.fetchRandomQuote();
|
||||
if (apiQuote) {
|
||||
quote = apiQuote.name;
|
||||
author = apiQuote.url;
|
||||
dynasty = apiQuote.alias;
|
||||
await this.saveQuoteToPreferences(formName, quote, author, dynasty);
|
||||
}
|
||||
}
|
||||
|
||||
let weatherData: WeatherData = {
|
||||
city: '昆明',
|
||||
weather: '晴',
|
||||
temp: '11'
|
||||
};
|
||||
|
||||
if (settings.showWeather) {
|
||||
const fetchedWeather = await this.fetchWeather();
|
||||
if (fetchedWeather) {
|
||||
weatherData = fetchedWeather;
|
||||
}
|
||||
}
|
||||
|
||||
const content: FormDataContent = {
|
||||
title: this.getTitleByFormName(formName),
|
||||
quote: quote,
|
||||
author: author,
|
||||
dynasty: dynasty,
|
||||
time: this.getCurrentTime(),
|
||||
weather: weatherData.weather + ' ' + weatherData.temp + '°C',
|
||||
city: weatherData.city,
|
||||
style: settings.style,
|
||||
showTime: settings.showTime,
|
||||
showWeather: settings.showWeather,
|
||||
showQuote: showQuote,
|
||||
formName: formName
|
||||
};
|
||||
return content;
|
||||
}
|
||||
|
||||
private async loadSettings(): Promise<SettingsData> {
|
||||
try {
|
||||
const preference = await preferences.getPreferences(this.context, 'widget_quote_settings');
|
||||
const result: SettingsData = {
|
||||
style: await preference.get('style', 'classic') as string,
|
||||
showTime: Boolean(await preference.get('showTime', true)),
|
||||
showWeather: Boolean(await preference.get('showWeather', true)),
|
||||
showQuote: Boolean(await preference.get('showQuote', true)),
|
||||
quote: await preference.get('quote', '床前明月光,疑是地上霜。') as string,
|
||||
author: await preference.get('author', '李白《静夜思》') as string,
|
||||
dynasty: await preference.get('dynasty', '唐代') as string,
|
||||
autoUpdate: Boolean(await preference.get('autoUpdate', false)),
|
||||
updateInterval: await preference.get('updateInterval', 60) as number,
|
||||
selectedSource: await preference.get('selectedSource', 'local') as string,
|
||||
smallQuote: await preference.get('small_quote', '床前明月光,疑是地上霜。') as string,
|
||||
smallAuthor: await preference.get('small_author', '李白《静夜思》') as string,
|
||||
smallDynasty: await preference.get('small_dynasty', '唐代') as string,
|
||||
smallShowQuote: Boolean(await preference.get('small_showQuote', true)),
|
||||
mediumQuote: await preference.get('medium_quote', '春眠不觉晓,处处闻啼鸟。') as string,
|
||||
mediumAuthor: await preference.get('medium_author', '孟浩然《春晓》') as string,
|
||||
mediumDynasty: await preference.get('medium_dynasty', '唐代') as string,
|
||||
mediumShowQuote: Boolean(await preference.get('medium_showQuote', true)),
|
||||
largeQuote: await preference.get('large_quote', '白日依山尽,黄河入海流。') as string,
|
||||
largeAuthor: await preference.get('large_author', '王之涣《登鹳雀楼》') as string,
|
||||
largeDynasty: await preference.get('large_dynasty', '唐代') as string,
|
||||
largeShowQuote: Boolean(await preference.get('large_showQuote', true))
|
||||
};
|
||||
console.info('[WidgetFormAbility] Settings loaded - showTime: ' + result.showTime + ', showWeather: ' + result.showWeather);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] loadSettings error: ' + JSON.stringify(error));
|
||||
const result: SettingsData = {
|
||||
style: 'classic',
|
||||
showTime: true,
|
||||
showWeather: true,
|
||||
showQuote: true,
|
||||
quote: '床前明月光,疑是地上霜。',
|
||||
author: '李白《静夜思》',
|
||||
dynasty: '唐代',
|
||||
autoUpdate: false,
|
||||
updateInterval: 60,
|
||||
selectedSource: 'local',
|
||||
smallQuote: '床前明月光,疑是地上霜。',
|
||||
smallAuthor: '李白《静夜思》',
|
||||
smallDynasty: '唐代',
|
||||
smallShowQuote: true,
|
||||
mediumQuote: '春眠不觉晓,处处闻啼鸟。',
|
||||
mediumAuthor: '孟浩然《春晓》',
|
||||
mediumDynasty: '唐代',
|
||||
mediumShowQuote: true,
|
||||
largeQuote: '白日依山尽,黄河入海流。',
|
||||
largeAuthor: '王之涣《登鹳雀楼》',
|
||||
largeDynasty: '唐代',
|
||||
largeShowQuote: true
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private async saveQuoteToPreferences(formName: string, quote: string, author: string, dynasty: string): Promise<void> {
|
||||
try {
|
||||
const preference = await preferences.getPreferences(this.context, 'widget_quote_settings');
|
||||
await preference.put('quote', quote);
|
||||
await preference.put('author', author);
|
||||
await preference.put('dynasty', dynasty);
|
||||
|
||||
switch (formName) {
|
||||
case 'WidgetCardSmall':
|
||||
await preference.put('small_quote', quote);
|
||||
await preference.put('small_author', author);
|
||||
await preference.put('small_dynasty', dynasty);
|
||||
break;
|
||||
case 'WidgetCardMedium':
|
||||
await preference.put('medium_quote', quote);
|
||||
await preference.put('medium_author', author);
|
||||
await preference.put('medium_dynasty', dynasty);
|
||||
break;
|
||||
case 'WidgetCardLarge':
|
||||
await preference.put('large_quote', quote);
|
||||
await preference.put('large_author', author);
|
||||
await preference.put('large_dynasty', dynasty);
|
||||
break;
|
||||
}
|
||||
|
||||
await preference.flush();
|
||||
console.info('[WidgetFormAbility] Quote saved to preferences for ' + formName);
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] saveQuoteToPreferences error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchWeather(): Promise<WeatherData | null> {
|
||||
try {
|
||||
const httpRequest = http.createHttp();
|
||||
const response = await httpRequest.request('https://yy.vogov.cn/api/tq/api.php', {
|
||||
method: http.RequestMethod.GET,
|
||||
connectTimeout: 10000,
|
||||
readTimeout: 10000
|
||||
});
|
||||
|
||||
httpRequest.destroy();
|
||||
|
||||
if (response.responseCode === 200) {
|
||||
const result = JSON.parse(response.result as string) as WeatherApiResponse;
|
||||
if (result.status === 'success' && result.data && result.data.data) {
|
||||
const weatherInfo = result.data.data.cityDZ.weatherinfo;
|
||||
const weatherData: WeatherData = {
|
||||
city: weatherInfo.city,
|
||||
weather: weatherInfo.weather,
|
||||
temp: weatherInfo.temp
|
||||
};
|
||||
console.info('[WidgetFormAbility] Fetched weather: ' + JSON.stringify(weatherData));
|
||||
return weatherData;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] fetchWeather error: ' + JSON.stringify(error));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchRandomQuote(): Promise<QuoteResult | null> {
|
||||
try {
|
||||
const httpRequest = http.createHttp();
|
||||
const response = await httpRequest.request('https://yy.vogov.cn/api/pms.php', {
|
||||
method: http.RequestMethod.GET,
|
||||
connectTimeout: 10000,
|
||||
readTimeout: 10000
|
||||
});
|
||||
|
||||
httpRequest.destroy();
|
||||
|
||||
if (response.responseCode === 200) {
|
||||
const result = JSON.parse(response.result as string) as ApiResponse;
|
||||
if (result.code === 0 && result.data) {
|
||||
const quoteResult: QuoteResult = {
|
||||
name: result.data.name,
|
||||
url: result.data.url,
|
||||
alias: result.data.alias
|
||||
};
|
||||
console.info('[WidgetFormAbility] Fetched quote: ' + quoteResult.name);
|
||||
return quoteResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] fetchRandomQuote error: ' + JSON.stringify(error));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private getTitleByFormName(formName: string): string {
|
||||
switch (formName) {
|
||||
case 'WidgetCardSmall':
|
||||
return '🎋 诗词短句';
|
||||
case 'WidgetCardMedium':
|
||||
return '📖 经典诗词';
|
||||
case 'WidgetCardLarge':
|
||||
return '🎨 诗词意境';
|
||||
default:
|
||||
return '🎋 诗词短句';
|
||||
}
|
||||
}
|
||||
|
||||
onUpdate(formId: string): void {
|
||||
console.info('[WidgetFormAbility] onUpdate, formId: ' + formId);
|
||||
this.updateForm(formId);
|
||||
}
|
||||
|
||||
onFormEvent(formId: string, message: string): void {
|
||||
console.info('[WidgetFormAbility] onFormEvent, formId: ' + formId + ', message: ' + message);
|
||||
|
||||
if (message === 'refreshQuote') {
|
||||
console.info('[WidgetFormAbility] Refresh quote requested');
|
||||
this.refreshQuoteOnly(formId);
|
||||
} else if (message === 'refreshWeather') {
|
||||
console.info('[WidgetFormAbility] Refresh weather requested');
|
||||
this.refreshWeatherOnly(formId);
|
||||
} else if (message === 'refresh' || message.includes('refresh')) {
|
||||
console.info('[WidgetFormAbility] Full refresh requested');
|
||||
this.refreshForm(formId);
|
||||
}
|
||||
}
|
||||
|
||||
async refreshQuoteOnly(formId: string): Promise<void> {
|
||||
console.info('[WidgetFormAbility] refreshQuoteOnly start for formId: ' + formId);
|
||||
try {
|
||||
const settings = await this.loadSettings();
|
||||
const formName = await this.getFormNameByFormId(formId);
|
||||
|
||||
let quote: string;
|
||||
let author: string;
|
||||
let dynasty: string;
|
||||
let showQuote: boolean;
|
||||
|
||||
switch (formName) {
|
||||
case 'WidgetCardSmall':
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
break;
|
||||
case 'WidgetCardMedium':
|
||||
quote = settings.mediumQuote;
|
||||
author = settings.mediumAuthor;
|
||||
dynasty = settings.mediumDynasty;
|
||||
showQuote = settings.mediumShowQuote;
|
||||
break;
|
||||
case 'WidgetCardLarge':
|
||||
quote = settings.largeQuote;
|
||||
author = settings.largeAuthor;
|
||||
dynasty = settings.largeDynasty;
|
||||
showQuote = settings.largeShowQuote;
|
||||
break;
|
||||
default:
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
}
|
||||
|
||||
if (settings.selectedSource === 'api') {
|
||||
const apiQuote = await this.fetchRandomQuote();
|
||||
if (apiQuote) {
|
||||
quote = apiQuote.name;
|
||||
author = apiQuote.url;
|
||||
dynasty = apiQuote.alias;
|
||||
await this.saveQuoteToPreferences(formName, quote, author, dynasty);
|
||||
}
|
||||
}
|
||||
|
||||
const content: FormDataContent = {
|
||||
title: this.getTitleByFormName(formName),
|
||||
quote: quote,
|
||||
author: author,
|
||||
dynasty: dynasty,
|
||||
time: this.getCurrentTime(),
|
||||
weather: '',
|
||||
city: '',
|
||||
style: settings.style,
|
||||
showTime: settings.showTime,
|
||||
showWeather: false,
|
||||
showQuote: showQuote,
|
||||
formName: formName
|
||||
};
|
||||
|
||||
const bindingData = formBindingData.createFormBindingData(content);
|
||||
await formProvider.updateForm(formId, bindingData);
|
||||
console.info('[WidgetFormAbility] refreshQuoteOnly success');
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] refreshQuoteOnly error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
async refreshWeatherOnly(formId: string): Promise<void> {
|
||||
console.info('[WidgetFormAbility] refreshWeatherOnly start for formId: ' + formId);
|
||||
try {
|
||||
const settings = await this.loadSettings();
|
||||
const formName = await this.getFormNameByFormId(formId);
|
||||
|
||||
let quote: string;
|
||||
let author: string;
|
||||
let dynasty: string;
|
||||
let showQuote: boolean;
|
||||
|
||||
switch (formName) {
|
||||
case 'WidgetCardSmall':
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
break;
|
||||
case 'WidgetCardMedium':
|
||||
quote = settings.mediumQuote;
|
||||
author = settings.mediumAuthor;
|
||||
dynasty = settings.mediumDynasty;
|
||||
showQuote = settings.mediumShowQuote;
|
||||
break;
|
||||
case 'WidgetCardLarge':
|
||||
quote = settings.largeQuote;
|
||||
author = settings.largeAuthor;
|
||||
dynasty = settings.largeDynasty;
|
||||
showQuote = settings.largeShowQuote;
|
||||
break;
|
||||
default:
|
||||
quote = settings.smallQuote;
|
||||
author = settings.smallAuthor;
|
||||
dynasty = settings.smallDynasty;
|
||||
showQuote = settings.smallShowQuote;
|
||||
}
|
||||
|
||||
let weatherData: WeatherData = {
|
||||
city: '昆明',
|
||||
weather: '晴',
|
||||
temp: '11'
|
||||
};
|
||||
|
||||
const fetchedWeather = await this.fetchWeather();
|
||||
if (fetchedWeather) {
|
||||
weatherData = fetchedWeather;
|
||||
}
|
||||
|
||||
const content: FormDataContent = {
|
||||
title: this.getTitleByFormName(formName),
|
||||
quote: quote,
|
||||
author: author,
|
||||
dynasty: dynasty,
|
||||
time: this.getCurrentTime(),
|
||||
weather: weatherData.weather + ' ' + weatherData.temp + '°C',
|
||||
city: weatherData.city,
|
||||
style: settings.style,
|
||||
showTime: settings.showTime,
|
||||
showWeather: settings.showWeather,
|
||||
showQuote: showQuote,
|
||||
formName: formName
|
||||
};
|
||||
|
||||
const bindingData = formBindingData.createFormBindingData(content);
|
||||
await formProvider.updateForm(formId, bindingData);
|
||||
console.info('[WidgetFormAbility] refreshWeatherOnly success');
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] refreshWeatherOnly error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
async refreshForm(formId: string): Promise<void> {
|
||||
console.info('[WidgetFormAbility] refreshForm start for formId: ' + formId);
|
||||
try {
|
||||
const settings = await this.loadSettings();
|
||||
console.info('[WidgetFormAbility] Loaded settings, selectedSource: ' + settings.selectedSource);
|
||||
|
||||
const formName = await this.getFormNameByFormId(formId);
|
||||
console.info('[WidgetFormAbility] Form name: ' + formName);
|
||||
|
||||
const content = await this.buildFormData(formName, settings);
|
||||
|
||||
const bindingData = formBindingData.createFormBindingData(content);
|
||||
await formProvider.updateForm(formId, bindingData);
|
||||
console.info('[WidgetFormAbility] refreshForm success');
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] refreshForm error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private async getFormNameByFormId(formId: string): Promise<string> {
|
||||
try {
|
||||
const formInfos = await formProvider.getPublishedRunningFormInfos();
|
||||
for (const info of formInfos) {
|
||||
if (info.formId === formId) {
|
||||
return info.formName;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] getFormNameByFormId error: ' + JSON.stringify(error));
|
||||
}
|
||||
return 'WidgetCardSmall';
|
||||
}
|
||||
|
||||
onCastToNormal(formId: string): void {
|
||||
console.info('[WidgetFormAbility] onCastToNormal, formId: ' + formId);
|
||||
}
|
||||
|
||||
onVisibilityChange(newStatus: Record<string, number>): void {
|
||||
console.info('[WidgetFormAbility] onVisibilityChange, newStatus: ' + JSON.stringify(newStatus));
|
||||
}
|
||||
|
||||
onDestroy(formId: string): void {
|
||||
console.info('[WidgetFormAbility] onDestroy, formId: ' + formId);
|
||||
}
|
||||
|
||||
onAcquireFormState?(want: Want): number {
|
||||
console.info('[WidgetFormAbility] onAcquireFormState');
|
||||
return 0;
|
||||
}
|
||||
|
||||
private async updateForm(formId: string, formName: string = 'WidgetCardSmall'): Promise<void> {
|
||||
try {
|
||||
const settings = await this.loadSettings();
|
||||
|
||||
const content = await this.buildFormData(formName, settings);
|
||||
|
||||
const bindingData = formBindingData.createFormBindingData(content);
|
||||
formProvider.updateForm(formId, bindingData).then(() => {
|
||||
console.info('[WidgetFormAbility] updateForm success');
|
||||
}).catch((error: BusinessError) => {
|
||||
console.error('[WidgetFormAbility] updateForm error: ' + JSON.stringify(error));
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[WidgetFormAbility] updateForm exception: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private getChineseTimePeriod(): string {
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 23 || hour < 1) {
|
||||
return '子时';
|
||||
} else if (hour >= 1 && hour < 3) {
|
||||
return '丑时';
|
||||
} else if (hour >= 3 && hour < 5) {
|
||||
return '寅时';
|
||||
} else if (hour >= 5 && hour < 7) {
|
||||
return '卯时';
|
||||
} else if (hour >= 7 && hour < 9) {
|
||||
return '辰时';
|
||||
} else if (hour >= 9 && hour < 11) {
|
||||
return '巳时';
|
||||
} else if (hour >= 11 && hour < 13) {
|
||||
return '午时';
|
||||
} else if (hour >= 13 && hour < 15) {
|
||||
return '未时';
|
||||
} else if (hour >= 15 && hour < 17) {
|
||||
return '申时';
|
||||
} else if (hour >= 17 && hour < 19) {
|
||||
return '酉时';
|
||||
} else if (hour >= 19 && hour < 21) {
|
||||
return '戌时';
|
||||
} else {
|
||||
return '亥时';
|
||||
}
|
||||
}
|
||||
|
||||
private getCurrentTime(): string {
|
||||
return this.getChineseTimePeriod();
|
||||
}
|
||||
}
|
||||
24
ohos/entry/src/main/ets/pages/Index.ets
Normal file
24
ohos/entry/src/main/ets/pages/Index.ets
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
import common from '@ohos.app.ability.common';
|
||||
import { FlutterPage } from '@ohos/flutter_ohos'
|
||||
|
||||
let storage = LocalStorage.getShared()
|
||||
const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'
|
||||
|
||||
@Entry(storage)
|
||||
@Component
|
||||
struct Index {
|
||||
private context = getContext(this) as common.UIAbilityContext
|
||||
@LocalStorageLink('viewId') viewId: string = "";
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
FlutterPage({ viewId: this.viewId })
|
||||
}
|
||||
}
|
||||
|
||||
onBackPress(): boolean {
|
||||
this.context.eventHub.emit(EVENT_BACK_PRESS)
|
||||
return true
|
||||
}
|
||||
}
|
||||
532
ohos/entry/src/main/ets/pages/WidgetCard.ets
Normal file
532
ohos/entry/src/main/ets/pages/WidgetCard.ets
Normal file
@@ -0,0 +1,532 @@
|
||||
@Entry
|
||||
|
||||
@Component
|
||||
struct WidgetCard {
|
||||
@LocalStorageProp('formName') formName: string = 'WidgetCardSmall';
|
||||
@LocalStorageProp('style') style: string = 'classic';
|
||||
@LocalStorageProp('showTime') showTime: boolean = true;
|
||||
@LocalStorageProp('showWeather') showWeather: boolean = true;
|
||||
@LocalStorageProp('showQuote') showQuote: boolean = true;
|
||||
@LocalStorageProp('quote') quote: string = '床前明月光,疑是地上霜。';
|
||||
@LocalStorageProp('author') author: string = '李白《静夜思》';
|
||||
@LocalStorageProp('dynasty') dynasty: string = '唐代';
|
||||
@LocalStorageProp('time') time: string = '12:00';
|
||||
@LocalStorageProp('weather') weather: string = '晴 16°C';
|
||||
@LocalStorageProp('city') city: string = '昆明';
|
||||
|
||||
private getTimePeriod(): string {
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 0 && hour < 6) {
|
||||
return '凌晨';
|
||||
} else if (hour >= 6 && hour < 9) {
|
||||
return '早上';
|
||||
} else if (hour >= 9 && hour < 12) {
|
||||
return '上午';
|
||||
} else if (hour >= 12 && hour < 14) {
|
||||
return '中午';
|
||||
} else if (hour >= 14 && hour < 18) {
|
||||
return '下午';
|
||||
} else if (hour >= 18 && hour < 22) {
|
||||
return '晚上';
|
||||
} else {
|
||||
return '深夜';
|
||||
}
|
||||
}
|
||||
|
||||
private getChineseTimePeriod(): string {
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 23 || hour < 1) {
|
||||
return '子时';
|
||||
} else if (hour >= 1 && hour < 3) {
|
||||
return '丑时';
|
||||
} else if (hour >= 3 && hour < 5) {
|
||||
return '寅时';
|
||||
} else if (hour >= 5 && hour < 7) {
|
||||
return '卯时';
|
||||
} else if (hour >= 7 && hour < 9) {
|
||||
return '辰时';
|
||||
} else if (hour >= 9 && hour < 11) {
|
||||
return '巳时';
|
||||
} else if (hour >= 11 && hour < 13) {
|
||||
return '午时';
|
||||
} else if (hour >= 13 && hour < 15) {
|
||||
return '未时';
|
||||
} else if (hour >= 15 && hour < 17) {
|
||||
return '申时';
|
||||
} else if (hour >= 17 && hour < 19) {
|
||||
return '酉时';
|
||||
} else if (hour >= 19 && hour < 21) {
|
||||
return '戌时';
|
||||
} else {
|
||||
return '亥时';
|
||||
}
|
||||
}
|
||||
|
||||
private getWeekDay(): string {
|
||||
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
return weekDays[new Date().getDay()];
|
||||
}
|
||||
|
||||
private getGreeting(): string {
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 5 && hour < 7) {
|
||||
return '清晨了,呼吸新鲜空气';
|
||||
} else if (hour >= 7 && hour < 9) {
|
||||
return '早上好,元气满满';
|
||||
} else if (hour >= 9 && hour < 12) {
|
||||
return '上午好,努力工作';
|
||||
} else if (hour >= 12 && hour < 14) {
|
||||
return '中午了,吃顿好的';
|
||||
} else if (hour >= 14 && hour < 17) {
|
||||
return '下午了,喝杯咖啡';
|
||||
} else if (hour >= 17 && hour < 19) {
|
||||
return '傍晚了,休息一下';
|
||||
} else if (hour >= 19 && hour < 22) {
|
||||
return '晚上好,放松身心';
|
||||
} else {
|
||||
return '深夜了,注意身体';
|
||||
}
|
||||
}
|
||||
|
||||
private getRecommendation(): string {
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 5 && hour < 7) {
|
||||
return '推荐:山水田园诗';
|
||||
} else if (hour >= 7 && hour < 9) {
|
||||
return '推荐:励志诗词';
|
||||
} else if (hour >= 9 && hour < 12) {
|
||||
return '推荐:送别诗';
|
||||
} else if (hour >= 12 && hour < 14) {
|
||||
return '推荐:思乡诗';
|
||||
} else if (hour >= 14 && hour < 17) {
|
||||
return '推荐:咏史诗';
|
||||
} else if (hour >= 17 && hour < 19) {
|
||||
return '推荐:边塞诗';
|
||||
} else if (hour >= 19 && hour < 22) {
|
||||
return '推荐:爱情诗';
|
||||
} else {
|
||||
return '推荐:婉约词';
|
||||
}
|
||||
}
|
||||
|
||||
private isSmallCard(): boolean {
|
||||
return this.formName === 'WidgetCardSmall';
|
||||
}
|
||||
|
||||
private isDarkText(): boolean {
|
||||
return this.style === 'transparent' || this.style === 'liquid' || this.style === 'immersive';
|
||||
}
|
||||
|
||||
private getTextColor(): string {
|
||||
return this.isDarkText() ? '#1A1A1A' : '#FFFFFF';
|
||||
}
|
||||
|
||||
private getTextOpacity(): number {
|
||||
return this.isDarkText() ? 1 : 0.9;
|
||||
}
|
||||
|
||||
private getPoet(): string {
|
||||
const author = this.author;
|
||||
const titleMatch = author.match(/《.*?》/);
|
||||
if (titleMatch) {
|
||||
return author.replace(/《.*?》/, '').trim();
|
||||
}
|
||||
return author;
|
||||
}
|
||||
|
||||
private getTitle(): string {
|
||||
const author = this.author;
|
||||
const titleMatch = author.match(/《(.*?)》/);
|
||||
if (titleMatch) {
|
||||
return titleMatch[1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
build() {
|
||||
if (this.style === 'frosted') {
|
||||
this.buildCardFrosted()
|
||||
} else if (this.style === 'liquid') {
|
||||
this.buildCardLiquid()
|
||||
} else if (this.style === 'immersive') {
|
||||
this.buildCardImmersive()
|
||||
} else if (this.style === 'transparent') {
|
||||
this.buildCardTransparent()
|
||||
} else {
|
||||
this.buildCardGradient()
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildCardFrosted() {
|
||||
Column() {
|
||||
if (this.isSmallCard()) {
|
||||
this.buildSmallCard();
|
||||
} else {
|
||||
this.buildNormalCard();
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
.borderRadius(20)
|
||||
.backgroundColor('rgba(0,0,0,0.3)')
|
||||
.backdropBlur(20)
|
||||
.border({
|
||||
width: 1,
|
||||
color: 'rgba(255,255,255,0.2)'
|
||||
})
|
||||
.shadow({
|
||||
radius: 10,
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
offsetX: 0,
|
||||
offsetY: 4
|
||||
})
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'router',
|
||||
abilityName: 'EntryAbility',
|
||||
params: {
|
||||
targetPage: 'pages/WidgetQuoteSettings',
|
||||
formName: this.formName
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildCardLiquid() {
|
||||
Column() {
|
||||
if (this.isSmallCard()) {
|
||||
this.buildSmallCard();
|
||||
} else {
|
||||
this.buildNormalCard();
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: [['rgba(100,181,246,0.6)', 0.0], ['rgba(255,255,255,0.3)', 0.5], ['rgba(255,138,128,0.4)', 1.0]]
|
||||
})
|
||||
.backdropBlur(15)
|
||||
.shadow({
|
||||
radius: 10,
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
offsetX: 0,
|
||||
offsetY: 4
|
||||
})
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'router',
|
||||
abilityName: 'EntryAbility',
|
||||
params: {
|
||||
targetPage: 'pages/WidgetQuoteSettings',
|
||||
formName: this.formName
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildCardImmersive() {
|
||||
Column() {
|
||||
if (this.isSmallCard()) {
|
||||
this.buildSmallCard();
|
||||
} else {
|
||||
this.buildNormalCard();
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 180,
|
||||
colors: [['rgba(0,0,0,0.4)', 0.0], ['rgba(0,0,0,0.1)', 0.5], ['rgba(0,0,0,0.3)', 1.0]]
|
||||
})
|
||||
.backdropBlur(10)
|
||||
.shadow({
|
||||
radius: 10,
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
offsetX: 0,
|
||||
offsetY: 4
|
||||
})
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'router',
|
||||
abilityName: 'EntryAbility',
|
||||
params: {
|
||||
targetPage: 'pages/WidgetQuoteSettings',
|
||||
formName: this.formName
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildCardTransparent() {
|
||||
Column() {
|
||||
if (this.isSmallCard()) {
|
||||
this.buildSmallCard();
|
||||
} else {
|
||||
this.buildNormalCard();
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
.borderRadius(20)
|
||||
.backgroundColor('transparent')
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'router',
|
||||
abilityName: 'EntryAbility',
|
||||
params: {
|
||||
targetPage: 'pages/WidgetQuoteSettings',
|
||||
formName: this.formName
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildCardGradient() {
|
||||
Column() {
|
||||
if (this.isSmallCard()) {
|
||||
this.buildSmallCard();
|
||||
} else {
|
||||
this.buildNormalCard();
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.padding(16)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: this.getGradientColors()
|
||||
})
|
||||
.shadow({
|
||||
radius: 10,
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
offsetX: 0,
|
||||
offsetY: 4
|
||||
})
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'router',
|
||||
abilityName: 'EntryAbility',
|
||||
params: {
|
||||
targetPage: 'pages/WidgetQuoteSettings',
|
||||
formName: this.formName
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
private getGradientColors(): Array<[ResourceColor, number]> {
|
||||
switch (this.style) {
|
||||
case 'classic':
|
||||
return [['#7B1FA2', 0.0], ['#9C27B0', 1.0]];
|
||||
case 'modern':
|
||||
return [['#2E7D32', 0.0], ['#4CAF50', 1.0]];
|
||||
case 'minimal':
|
||||
return [['#8E8E93', 0.0], ['#C7C7CC', 1.0]];
|
||||
case 'elegant':
|
||||
return [['#FF9500', 0.0], ['#FFCC00', 1.0]];
|
||||
default:
|
||||
return [['#7B1FA2', 0.0], ['#9C27B0', 1.0]];
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildSmallCard() {
|
||||
Column() {
|
||||
Row() {
|
||||
if (this.showTime) {
|
||||
Row({ space: 3 }) {
|
||||
Text(this.getWeekDay())
|
||||
.fontSize(12)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.8 : 0.85)
|
||||
Text(this.time)
|
||||
.fontSize(12)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
}
|
||||
|
||||
Button(this.city)
|
||||
.fontSize(12)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.backgroundColor(this.isDarkText() ? 'rgba(0,122,255,0.15)' : 'rgba(255, 255, 255, 0.25)')
|
||||
.borderRadius(14)
|
||||
.height(28)
|
||||
.padding({ left: 10, right: 10 })
|
||||
.margin({ left: 6 })
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'message',
|
||||
params: {
|
||||
message: 'refreshWeather'
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
Blank()
|
||||
}
|
||||
.width('100%')
|
||||
.margin({ bottom: 12 })
|
||||
|
||||
Blank()
|
||||
|
||||
Column({ space: 8 }) {
|
||||
Text(this.getGreeting())
|
||||
.fontSize(16)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.textAlign(TextAlign.Center)
|
||||
|
||||
Text(this.getRecommendation())
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.7 : 0.85)
|
||||
.textAlign(TextAlign.Center)
|
||||
}
|
||||
|
||||
Blank()
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildNormalCard() {
|
||||
Column() {
|
||||
Row() {
|
||||
if (this.showTime) {
|
||||
Row({ space: 4 }) {
|
||||
Text(this.getWeekDay())
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.7 : 0.85)
|
||||
Text(this.getTimePeriod())
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.7 : 0.85)
|
||||
Text(this.time)
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.showWeather) {
|
||||
Button(this.city + ' ' + this.weather)
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.backgroundColor(this.isDarkText() ? 'rgba(0,122,255,0.15)' : 'rgba(255, 255, 255, 0.25)')
|
||||
.borderRadius(16)
|
||||
.height(30)
|
||||
.padding({ left: 10, right: 10 })
|
||||
.margin({ left: 8 })
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'message',
|
||||
params: {
|
||||
message: 'refreshWeather'
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
Blank()
|
||||
|
||||
Button('🔄 加载')
|
||||
.fontSize(13)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.backgroundColor(this.isDarkText() ? 'rgba(0,122,255,0.15)' : 'rgba(255, 255, 255, 0.25)')
|
||||
.borderRadius(16)
|
||||
.height(32)
|
||||
.padding({ left: 12, right: 12 })
|
||||
.onClick(() => {
|
||||
postCardAction(this, {
|
||||
action: 'message',
|
||||
params: {
|
||||
message: 'refreshQuote'
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
// .margin({ bottom: 16 })
|
||||
|
||||
if (this.showQuote) {
|
||||
Text(this.quote)
|
||||
.fontSize(20)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.lineHeight(32)
|
||||
.textAlign(TextAlign.Center)
|
||||
.maxLines(3)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
}
|
||||
|
||||
Blank()
|
||||
|
||||
Column() {
|
||||
if (this.showQuote) {
|
||||
if (this.getTitle()) {
|
||||
Text('《' + this.getTitle() + '》')
|
||||
.fontSize(14)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.8 : 0.9)
|
||||
.margin({ bottom: 8 })
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Start)
|
||||
}
|
||||
Row() {
|
||||
if (this.dynasty) {
|
||||
Text(this.dynasty)
|
||||
.fontSize(14)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.7 : 0.85)
|
||||
}
|
||||
if (this.getPoet()) {
|
||||
Text('·' + this.getPoet())
|
||||
.fontSize(14)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.opacity(this.isDarkText() ? 0.6 : 0.8)
|
||||
.fontStyle(FontStyle.Italic)
|
||||
}
|
||||
|
||||
Blank()
|
||||
|
||||
Text('✨ 精选诗句')
|
||||
.fontSize(14)
|
||||
.fontColor(this.getTextColor())
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.opacity(this.getTextOpacity())
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
1122
ohos/entry/src/main/ets/pages/WidgetQuoteSettings.ets
Normal file
1122
ohos/entry/src/main/ets/pages/WidgetQuoteSettings.ets
Normal file
File diff suppressed because it is too large
Load Diff
462
ohos/entry/src/main/ets/pages/WidgetSettings.ets
Normal file
462
ohos/entry/src/main/ets/pages/WidgetSettings.ets
Normal file
@@ -0,0 +1,462 @@
|
||||
import { router } from '@kit.ArkUI';
|
||||
import { preferences } from '@kit.ArkData';
|
||||
//todo 重要 后续 刷新按钮要求固定显示
|
||||
@Entry
|
||||
@Component
|
||||
struct WidgetSettings {
|
||||
@State selectedStyle: string = 'classic';
|
||||
@State showTime: boolean = true;
|
||||
@State showWeather: boolean = true;
|
||||
@State showQuote: boolean = true;
|
||||
@State quoteText: string = '床前明月光,疑是地上霜。';
|
||||
@State authorText: string = '李白《静夜思》';
|
||||
private preference: preferences.Preferences | null = null;
|
||||
|
||||
async aboutToAppear() {
|
||||
await this.loadSettings();
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
try {
|
||||
const context = getContext(this);
|
||||
this.preference = await preferences.getPreferences(context, 'widget_settings');
|
||||
this.selectedStyle = await this.preference.get('style', 'classic') as string;
|
||||
|
||||
const showTimeVal = await this.preference.get('showTime', true);
|
||||
this.showTime = Boolean(showTimeVal);
|
||||
console.info('[WidgetSettings] showTime raw value: ' + showTimeVal + ', type: ' + typeof showTimeVal + ', parsed: ' + this.showTime);
|
||||
|
||||
const showWeatherVal = await this.preference.get('showWeather', true);
|
||||
this.showWeather = Boolean(showWeatherVal);
|
||||
console.info('[WidgetSettings] showWeather raw value: ' + showWeatherVal + ', type: ' + typeof showWeatherVal + ', parsed: ' + this.showWeather);
|
||||
|
||||
const showQuoteVal = await this.preference.get('showQuote', true);
|
||||
this.showQuote = Boolean(showQuoteVal);
|
||||
|
||||
this.quoteText = await this.preference.get('quote', '床前明月光,疑是地上霜。') as string;
|
||||
this.authorText = await this.preference.get('author', '李白《静夜思》') as string;
|
||||
|
||||
console.info('[WidgetSettings] Settings loaded - showTime: ' + this.showTime + ', showWeather: ' + this.showWeather);
|
||||
} catch (error) {
|
||||
console.error('[WidgetSettings] loadSettings error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
try {
|
||||
if (!this.preference) {
|
||||
const context = getContext(this);
|
||||
this.preference = await preferences.getPreferences(context, 'widget_settings');
|
||||
}
|
||||
console.info('[WidgetSettings] Saving settings - showTime: ' + this.showTime + ', showWeather: ' + this.showWeather);
|
||||
await this.preference.put('style', this.selectedStyle);
|
||||
await this.preference.put('showTime', Boolean(this.showTime));
|
||||
await this.preference.put('showWeather', Boolean(this.showWeather));
|
||||
await this.preference.put('showQuote', Boolean(this.showQuote));
|
||||
await this.preference.put('quote', this.quoteText);
|
||||
await this.preference.put('author', this.authorText);
|
||||
await this.preference.flush();
|
||||
console.info('[WidgetSettings] Settings saved successfully');
|
||||
} catch (error) {
|
||||
console.error('[WidgetSettings] saveSettings error: ' + JSON.stringify(error));
|
||||
}
|
||||
}
|
||||
|
||||
private isDarkText(): boolean {
|
||||
return this.selectedStyle === 'transparent' || this.selectedStyle === 'frosted' || this.selectedStyle === 'liquid' || this.selectedStyle === 'immersive';
|
||||
}
|
||||
|
||||
build() {
|
||||
Navigation() {
|
||||
Scroll() {
|
||||
Column({ space: 16 }) {
|
||||
Text('卡片设置')
|
||||
.fontSize(24)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor('#1A1A1A')
|
||||
.margin({ top: 16, bottom: 8 })
|
||||
|
||||
this.buildPreview()
|
||||
|
||||
this.buildStyleSelector()
|
||||
|
||||
this.buildDisplayOptions()
|
||||
|
||||
this.buildContentSettings()
|
||||
|
||||
Button('保存设置')
|
||||
.width('100%')
|
||||
.height(48)
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.backgroundColor('#007AFF')
|
||||
.borderRadius(12)
|
||||
.margin({ top: 24, bottom: 32 })
|
||||
.onClick(() => {
|
||||
this.saveSettings();
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding(16)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
.title('卡片配置')
|
||||
.titleMode(NavigationTitleMode.Mini)
|
||||
.mode(NavigationMode.Stack)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreview() {
|
||||
Column() {
|
||||
Text('预览')
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.margin({ bottom: 8 })
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
if (this.selectedStyle === 'frosted') {
|
||||
this.buildPreviewCardFrosted()
|
||||
} else if (this.selectedStyle === 'liquid') {
|
||||
this.buildPreviewCardLiquid()
|
||||
} else if (this.selectedStyle === 'immersive') {
|
||||
this.buildPreviewCardImmersive()
|
||||
} else if (this.selectedStyle === 'transparent') {
|
||||
this.buildPreviewCardTransparent()
|
||||
} else {
|
||||
this.buildPreviewCardGradient()
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.padding(16)
|
||||
.backgroundColor('#F5F5F5')
|
||||
.borderRadius(12)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardFrosted() {
|
||||
Column() {
|
||||
this.buildPreviewCardContent()
|
||||
}
|
||||
.width('100%')
|
||||
.height(160)
|
||||
.padding(16)
|
||||
.borderRadius(16)
|
||||
.backgroundColor('rgba(255,255,255,0.25)')
|
||||
.backdropBlur(20)
|
||||
.border({
|
||||
width: 1,
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardLiquid() {
|
||||
Column() {
|
||||
this.buildPreviewCardContent()
|
||||
}
|
||||
.width('100%')
|
||||
.height(160)
|
||||
.padding(16)
|
||||
.borderRadius(16)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: [['rgba(100,181,246,0.6)', 0.0], ['rgba(255,255,255,0.3)', 0.5], ['rgba(255,138,128,0.4)', 1.0]]
|
||||
})
|
||||
.backdropBlur(15)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardImmersive() {
|
||||
Column() {
|
||||
this.buildPreviewCardContent()
|
||||
}
|
||||
.width('100%')
|
||||
.height(160)
|
||||
.padding(16)
|
||||
.borderRadius(16)
|
||||
.linearGradient({
|
||||
angle: 180,
|
||||
colors: [['rgba(0,0,0,0.4)', 0.0], ['rgba(0,0,0,0.1)', 0.5], ['rgba(0,0,0,0.3)', 1.0]]
|
||||
})
|
||||
.backdropBlur(10)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardTransparent() {
|
||||
Column() {
|
||||
this.buildPreviewCardContent()
|
||||
}
|
||||
.width('100%')
|
||||
.height(160)
|
||||
.padding(16)
|
||||
.borderRadius(16)
|
||||
.backgroundColor('transparent')
|
||||
.border({
|
||||
width: 1,
|
||||
color: '#E0E0E0',
|
||||
style: BorderStyle.Dashed
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardGradient() {
|
||||
Column() {
|
||||
this.buildPreviewCardContent()
|
||||
}
|
||||
.width('100%')
|
||||
.height(160)
|
||||
.padding(16)
|
||||
.borderRadius(16)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: this.getGradientColors()
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildPreviewCardContent() {
|
||||
if (this.showTime) {
|
||||
Row() {
|
||||
Text('12:00')
|
||||
.fontSize(15)
|
||||
.fontColor(this.isDarkText() ? '#1A1A1A' : '#FFFFFF')
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.End)
|
||||
}
|
||||
|
||||
if (this.showQuote) {
|
||||
Column() {
|
||||
Text(this.quoteText)
|
||||
.fontSize(18)
|
||||
.fontColor(this.isDarkText() ? '#1A1A1A' : '#FFFFFF')
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.margin({ bottom: 4 })
|
||||
Text(this.authorText)
|
||||
.fontSize(14)
|
||||
.fontColor(this.isDarkText() ? '#666666' : '#FFFFFFCC')
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.margin({ top: 12, bottom: 12 })
|
||||
}
|
||||
|
||||
if (this.showWeather) {
|
||||
Row() {
|
||||
Text('☀️')
|
||||
.fontSize(18)
|
||||
Text('25°C')
|
||||
.fontSize(15)
|
||||
.fontColor(this.isDarkText() ? '#1A1A1A' : '#FFFFFF')
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.margin({ left: 4 })
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.End)
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildStyleSelector() {
|
||||
Column({ space: 12 }) {
|
||||
Text('卡片样式')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor('#1A1A1A')
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 8 }) {
|
||||
this.buildStyleOption('classic', '经典', ['#7B1FA2', '#9C27B0'], 'gradient')
|
||||
this.buildStyleOption('modern', '护眼', ['#2E7D32', '#4CAF50'], 'gradient')
|
||||
this.buildStyleOption('minimal', '极简', ['#424242', '#757575'], 'gradient')
|
||||
this.buildStyleOption('elegant', '优雅', ['#FF6B6B', '#FF8E53'], 'gradient')
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.SpaceBetween)
|
||||
|
||||
Row({ space: 8 }) {
|
||||
this.buildStyleOption('frosted', '毛玻璃', ['rgba(255,255,255,0.25)', 'rgba(255,255,255,0.1)'], 'frosted')
|
||||
this.buildStyleOption('liquid', '柔光', ['rgba(100,181,246,0.4)', 'rgba(255,255,255,0.2)'], 'liquid')
|
||||
this.buildStyleOption('immersive', '沉浸式', ['rgba(0,0,0,0.3)', 'rgba(0,0,0,0.1)'], 'immersive')
|
||||
this.buildStyleOption('transparent', '纯白', ['transparent', 'transparent'], 'transparent')
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.SpaceBetween)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.padding(16)
|
||||
.backgroundColor('#F5F5F5')
|
||||
.borderRadius(12)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildStyleOption(style: string, label: string, colors: string[], type: string) {
|
||||
Column() {
|
||||
if (type === 'frosted') {
|
||||
Column()
|
||||
.width(40)
|
||||
.height(40)
|
||||
.borderRadius(20)
|
||||
.backgroundColor('rgba(0,0,0,0.3)')
|
||||
.backdropBlur(20)
|
||||
.border({
|
||||
width: 1,
|
||||
color: 'rgba(255,255,255,0.2)'
|
||||
})
|
||||
} else if (type === 'liquid') {
|
||||
Column()
|
||||
.width(40)
|
||||
.height(40)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: [['rgba(100,181,246,0.6)', 0.0], ['rgba(255,255,255,0.3)', 0.5], ['rgba(255,138,128,0.4)', 1.0]]
|
||||
})
|
||||
.backdropBlur(15)
|
||||
} else if (type === 'immersive') {
|
||||
Column()
|
||||
.width(40)
|
||||
.height(40)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 180,
|
||||
colors: [['rgba(0,0,0,0.4)', 0.0], ['rgba(0,0,0,0.1)', 0.5], ['rgba(0,0,0,0.3)', 1.0]]
|
||||
})
|
||||
.backdropBlur(10)
|
||||
} else if (type === 'transparent') {
|
||||
Column()
|
||||
.width(40)
|
||||
.height(40)
|
||||
.borderRadius(20)
|
||||
.border({
|
||||
width: 2,
|
||||
color: '#E0E0E0',
|
||||
style: BorderStyle.Dashed
|
||||
})
|
||||
} else {
|
||||
Column()
|
||||
.width(40)
|
||||
.height(40)
|
||||
.borderRadius(20)
|
||||
.linearGradient({
|
||||
angle: 135,
|
||||
colors: [[colors[0], 0.0], [colors[1], 1.0]]
|
||||
})
|
||||
}
|
||||
|
||||
Text(label)
|
||||
.fontSize(12)
|
||||
.fontColor(this.selectedStyle === style ? '#007AFF' : '#666666')
|
||||
.margin({ top: 4 })
|
||||
}
|
||||
.padding(8)
|
||||
.borderRadius(12)
|
||||
.border({
|
||||
width: this.selectedStyle === style ? 2 : 0,
|
||||
color: '#007AFF'
|
||||
})
|
||||
.backgroundColor(this.selectedStyle === style ? '#E3F2FD' : 'transparent')
|
||||
.onClick(() => {
|
||||
this.selectedStyle = style;
|
||||
})
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildDisplayOptions() {
|
||||
Column({ space: 12 }) {
|
||||
Text('显示选项(内测功能)')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor('#1A1A1A')
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
this.buildToggle('显示时间', this.showTime, (value) => { this.showTime = value; })
|
||||
this.buildToggle('显示天气', this.showWeather, (value) => { this.showWeather = value; })
|
||||
this.buildToggle('显示诗词', this.showQuote, (value) => { this.showQuote = value; })
|
||||
}
|
||||
.width('100%')
|
||||
.padding(16)
|
||||
.backgroundColor('#F5F5F5')
|
||||
.borderRadius(12)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildToggle(label: string, value: boolean, onChange: (value: boolean) => void) {
|
||||
Row() {
|
||||
Text(label)
|
||||
.fontSize(14)
|
||||
.fontColor('#1A1A1A')
|
||||
|
||||
Toggle({ type: ToggleType.Switch, isOn: value })
|
||||
.selectedColor('#007AFF')
|
||||
.onChange(onChange)
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.SpaceBetween)
|
||||
}
|
||||
|
||||
@Builder
|
||||
buildContentSettings() {
|
||||
Column({ space: 12 }) {
|
||||
Text('内容设置')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor('#1A1A1A')
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
Column({ space: 8 }) {
|
||||
Text('诗词内容')
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
TextArea({ text: $$this.quoteText })
|
||||
.width('100%')
|
||||
.height(80)
|
||||
.fontSize(14)
|
||||
.backgroundColor('#FFFFFF')
|
||||
.borderRadius(8)
|
||||
.padding(12)
|
||||
}
|
||||
|
||||
Column({ space: 8 }) {
|
||||
Text('作者信息')
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
TextInput({ text: $$this.authorText })
|
||||
.width('100%')
|
||||
.height(44)
|
||||
.fontSize(14)
|
||||
.backgroundColor('#FFFFFF')
|
||||
.borderRadius(8)
|
||||
.padding({ left: 12, right: 12 })
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.padding(16)
|
||||
.backgroundColor('#F5F5F5')
|
||||
.borderRadius(12)
|
||||
}
|
||||
|
||||
getGradientColors(): Array<[ResourceColor, number]> {
|
||||
switch (this.selectedStyle) {
|
||||
case 'classic':
|
||||
return [['#7B1FA2', 0.0], ['#9C27B0', 1.0]];
|
||||
case 'modern':
|
||||
return [['#2E7D32', 0.0], ['#4CAF50', 1.0]];
|
||||
case 'minimal':
|
||||
return [['#424242', 0.0], ['#757575', 1.0]];
|
||||
case 'elegant':
|
||||
return [['#FF6B6B', 0.0], ['#FF8E53', 1.0]];
|
||||
default:
|
||||
return [['#7B1FA2', 0.0], ['#9C27B0', 1.0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
17
ohos/entry/src/main/ets/plugins/ShortcutPlugin.ets
Normal file
17
ohos/entry/src/main/ets/plugins/ShortcutPlugin.ets
Normal file
@@ -0,0 +1,17 @@
|
||||
import { FlutterPlugin, FlutterPluginBinding, Log } from '@ohos/flutter_ohos';
|
||||
|
||||
const TAG = "ShortcutPlugin";
|
||||
|
||||
export default class ShortcutPlugin implements FlutterPlugin {
|
||||
getUniqueClassName(): string {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
onAttachedToEngine(binding: FlutterPluginBinding): void {
|
||||
Log.i(TAG, "ShortcutPlugin attached to engine");
|
||||
}
|
||||
|
||||
onDetachedFromEngine(binding: FlutterPluginBinding): void {
|
||||
Log.i(TAG, "ShortcutPlugin detached from engine");
|
||||
}
|
||||
}
|
||||
82
ohos/entry/src/main/module.json5
Normal file
82
ohos/entry/src/main/module.json5
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"phone"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:icon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": [
|
||||
{
|
||||
"name": "ohos.ability.shortcuts",
|
||||
"resource": "$profile:shortcuts_config"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility",
|
||||
"srcEntry": "./ets/ability/WidgetMenuAbility.ets",
|
||||
"description": "$string:WidgetMenuAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:WidgetMenuAbility_label",
|
||||
"startWindowIcon": "$media:icon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"extensionAbilities": [
|
||||
{
|
||||
"name": "WidgetFormAbility",
|
||||
"srcEntry": "./ets/formability/WidgetFormAbility.ets",
|
||||
"description": "$string:WidgetFormAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:WidgetFormAbility_label",
|
||||
"type": "form",
|
||||
"metadata": [
|
||||
{
|
||||
"name": "ohos.extension.form",
|
||||
"resource": "$profile:form_config"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{"name" : "ohos.permission.INTERNET"},
|
||||
{"name" : "ohos.permission.VIBRATE"}
|
||||
]
|
||||
}
|
||||
}
|
||||
8
ohos/entry/src/main/resources/base/element/color.json
Normal file
8
ohos/entry/src/main/resources/base/element/color.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
100
ohos/entry/src/main/resources/base/element/string.json
Normal file
100
ohos/entry/src/main/resources/base/element/string.json
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "📜 诗词卡片"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "📜 诗词卡片主程序"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "📜 诗词卡片"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_desc",
|
||||
"value": "每日诗词桌面卡片"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_label",
|
||||
"value": "📜 每日诗词"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_desc",
|
||||
"value": "卡片样式与快捷操作"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_label",
|
||||
"value": "⚙️ 卡片选项"
|
||||
},
|
||||
{
|
||||
"name": "shortcut_add_widget",
|
||||
"value": "➕ 笔记"
|
||||
},
|
||||
{
|
||||
"name": "shortcut_widget_settings",
|
||||
"value": "🔧 卡片信息"
|
||||
},
|
||||
{
|
||||
"name": "shortcut_open_app",
|
||||
"value": "📱 打开应用"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_classic",
|
||||
"value": "🎨 经典风格"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_classic_desc",
|
||||
"value": "传统诗词卡片样式"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_modern",
|
||||
"value": "✨ 现代风格"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_modern_desc",
|
||||
"value": "简洁现代的设计风格"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_minimal",
|
||||
"value": "◽ 极简风格"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_minimal_desc",
|
||||
"value": "最小化设计,突出内容"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_elegant",
|
||||
"value": "💎 优雅风格"
|
||||
},
|
||||
{
|
||||
"name": "menu_style_elegant_desc",
|
||||
"value": "精致优雅的视觉效果"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_small",
|
||||
"value": "🎋 诗词短句"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_medium",
|
||||
"value": "📖 经典诗词"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_large",
|
||||
"value": "🎨 诗词意境"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_small",
|
||||
"value": "📱 小尺寸2x2卡片,展示精选诗词短句"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_medium",
|
||||
"value": "📱 中等尺寸2x4卡片,展示经典诗词作品"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_large",
|
||||
"value": "📱 大尺寸4x4卡片,完整展示诗词意境"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
ohos/entry/src/main/resources/base/media/icon.png
Normal file
BIN
ohos/entry/src/main/resources/base/media/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
58
ohos/entry/src/main/resources/base/profile/form_config.json
Normal file
58
ohos/entry/src/main/resources/base/profile/form_config.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"forms": [
|
||||
{
|
||||
"name": "WidgetCardSmall",
|
||||
"displayName": "$string:widget_display_name_small",
|
||||
"description": "$string:widget_desc_small",
|
||||
"src": "./ets/pages/WidgetCard.ets",
|
||||
"uiSyntax": "arkts",
|
||||
"window": {
|
||||
"designWidth": 720,
|
||||
"autoDesignWidth": true
|
||||
},
|
||||
"colorMode": "auto",
|
||||
"isDefault": true,
|
||||
"updateEnabled": true,
|
||||
"scheduledUpdateTime": "00:00",
|
||||
"updateDuration": 1,
|
||||
"defaultDimension": "2*2",
|
||||
"supportDimensions": ["2*2"]
|
||||
},
|
||||
{
|
||||
"name": "WidgetCardMedium",
|
||||
"displayName": "$string:widget_display_name_medium",
|
||||
"description": "$string:widget_desc_medium",
|
||||
"src": "./ets/pages/WidgetCard.ets",
|
||||
"uiSyntax": "arkts",
|
||||
"window": {
|
||||
"designWidth": 720,
|
||||
"autoDesignWidth": true
|
||||
},
|
||||
"colorMode": "auto",
|
||||
"isDefault": false,
|
||||
"updateEnabled": true,
|
||||
"scheduledUpdateTime": "00:00",
|
||||
"updateDuration": 1,
|
||||
"defaultDimension": "2*4",
|
||||
"supportDimensions": ["2*4"]
|
||||
},
|
||||
{
|
||||
"name": "WidgetCardLarge",
|
||||
"displayName": "$string:widget_display_name_large",
|
||||
"description": "$string:widget_desc_large",
|
||||
"src": "./ets/pages/WidgetCard.ets",
|
||||
"uiSyntax": "arkts",
|
||||
"window": {
|
||||
"designWidth": 720,
|
||||
"autoDesignWidth": true
|
||||
},
|
||||
"colorMode": "auto",
|
||||
"isDefault": false,
|
||||
"updateEnabled": true,
|
||||
"scheduledUpdateTime": "00:00",
|
||||
"updateDuration": 1,
|
||||
"defaultDimension": "4*4",
|
||||
"supportDimensions": ["4*4"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index",
|
||||
"pages/WidgetSettings",
|
||||
"pages/WidgetQuoteSettings"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"shortcuts": [
|
||||
{
|
||||
"shortcutId": "open_app",
|
||||
"label": "$string:shortcut_open_app",
|
||||
"icon": "$media:icon",
|
||||
"wants": [
|
||||
{
|
||||
"bundleName": "app.whushu.poes",
|
||||
"moduleName": "entry",
|
||||
"abilityName": "EntryAbility"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
56
ohos/entry/src/main/resources/en_US/element/string.json
Normal file
56
ohos/entry/src/main/resources/en_US/element/string.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "Poetry Widget"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "Main App"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "📜 Poetry Card"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_desc",
|
||||
"value": "Daily Poetry Widget"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_label",
|
||||
"value": "📜 Daily Poetry"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_desc",
|
||||
"value": "Widget Style & Shortcuts"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_label",
|
||||
"value": "⚙️ Widget Options"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_small",
|
||||
"value": "🎋 Poetry Phrase"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_medium",
|
||||
"value": "📖 Classic Poetry"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_large",
|
||||
"value": "🎨 Poetry Mood"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_small",
|
||||
"value": "📱 Small 2x2 card, showing selected poetry phrases"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_medium",
|
||||
"value": "📱 Medium 2x4 card, showing classic poetry works"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_large",
|
||||
"value": "📱 Large 4x4 card, showing complete poetry mood"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
ohos/entry/src/main/resources/rawfile/buildinfo.json5
Normal file
8
ohos/entry/src/main/resources/rawfile/buildinfo.json5
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "enable_impeller",
|
||||
"value": "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
37
ohos/entry/src/main/resources/rawfile/framesconfig.json
Normal file
37
ohos/entry/src/main/resources/rawfile/framesconfig.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"SWITCH": 1,
|
||||
"TRANSLATE": [
|
||||
{
|
||||
"serial_number": 1,
|
||||
"min": 800,
|
||||
"max": -1,
|
||||
"preferred_fps": 90
|
||||
},
|
||||
{
|
||||
"serial_number": 2,
|
||||
"min": 77,
|
||||
"max": 800,
|
||||
"preferred_fps": 120
|
||||
},
|
||||
{
|
||||
"serial_number": 3,
|
||||
"min": 46,
|
||||
"max": 77,
|
||||
"preferred_fps": 90
|
||||
},
|
||||
{
|
||||
"serial_number": 4,
|
||||
"min": 10,
|
||||
"max": 46,
|
||||
"preferred_fps": 72
|
||||
},
|
||||
{
|
||||
"serial_number": 5,
|
||||
"min": 0,
|
||||
"max": 10,
|
||||
"preferred_fps": 60
|
||||
}
|
||||
],
|
||||
"SCALE": [],
|
||||
"ROTATION": []
|
||||
}
|
||||
56
ohos/entry/src/main/resources/zh_CN/element/string.json
Normal file
56
ohos/entry/src/main/resources/zh_CN/element/string.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "诗词桌面卡片"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "主应用"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "📜 诗词卡片"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_desc",
|
||||
"value": "每日诗词桌面卡片"
|
||||
},
|
||||
{
|
||||
"name": "WidgetFormAbility_label",
|
||||
"value": "📜 每日诗词"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_desc",
|
||||
"value": "卡片样式与快捷操作"
|
||||
},
|
||||
{
|
||||
"name": "WidgetMenuAbility_label",
|
||||
"value": "⚙️ 卡片选项"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_small",
|
||||
"value": "🎋 诗词短句"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_medium",
|
||||
"value": "📖 经典诗词"
|
||||
},
|
||||
{
|
||||
"name": "widget_display_name_large",
|
||||
"value": "🎨 诗词意境"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_small",
|
||||
"value": "📱 小尺寸2x2卡片,展示精选诗词短句"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_medium",
|
||||
"value": "📱 中等尺寸2x4卡片,展示经典诗词作品"
|
||||
},
|
||||
{
|
||||
"name": "widget_desc_large",
|
||||
"value": "📱 大尺寸4x4卡片,完整展示诗词意境"
|
||||
}
|
||||
]
|
||||
}
|
||||
35
ohos/entry/src/ohosTest/ets/test/Ability.test.ets
Normal file
35
ohos/entry/src/ohosTest/ets/test/Ability.test.ets
Normal file
@@ -0,0 +1,35 @@
|
||||
import hilog from '@ohos.hilog';
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
|
||||
|
||||
export default function abilityTest() {
|
||||
describe('ActsAbilityTest', function () {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll(function () {
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
beforeEach(function () {
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
afterEach(function () {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
afterAll(function () {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
it('assertContain',0, function () {
|
||||
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
|
||||
let a = 'abc'
|
||||
let b = 'b'
|
||||
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||
expect(a).assertContain(b)
|
||||
expect(a).assertEqual(a)
|
||||
})
|
||||
})
|
||||
}
|
||||
5
ohos/entry/src/ohosTest/ets/test/List.test.ets
Normal file
5
ohos/entry/src/ohosTest/ets/test/List.test.ets
Normal file
@@ -0,0 +1,5 @@
|
||||
import abilityTest from './Ability.test'
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest()
|
||||
}
|
||||
48
ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
Normal file
48
ohos/entry/src/ohosTest/ets/testability/TestAbility.ets
Normal file
@@ -0,0 +1,48 @@
|
||||
import UIAbility from '@ohos.app.ability.UIAbility';
|
||||
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
import hilog from '@ohos.hilog';
|
||||
import { Hypium } from '@ohos/hypium';
|
||||
import testsuite from '../test/List.test';
|
||||
import window from '@ohos.window';
|
||||
|
||||
export default class TestAbility extends UIAbility {
|
||||
onCreate(want, launchParam) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? '');
|
||||
var abilityDelegator: any
|
||||
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
var abilityDelegatorArguments: any
|
||||
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
|
||||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
|
||||
windowStage.loadContent('testability/pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
|
||||
JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
|
||||
}
|
||||
|
||||
onBackground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
|
||||
}
|
||||
}
|
||||
36
ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
Normal file
36
ohos/entry/src/ohosTest/ets/testability/pages/Index.ets
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
import hilog from '@ohos.hilog';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
aboutToAppear() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
|
||||
}
|
||||
@State message: string = 'Hello World'
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
Button() {
|
||||
Text('next page')
|
||||
.fontSize(20)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 20
|
||||
})
|
||||
.backgroundColor('#0D9FFB')
|
||||
.width('35%')
|
||||
.height('5%')
|
||||
.onClick(()=>{
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
import hilog from '@ohos.hilog';
|
||||
import TestRunner from '@ohos.application.testRunner';
|
||||
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
|
||||
var abilityDelegator = undefined
|
||||
var abilityDelegatorArguments = undefined
|
||||
|
||||
async function onAbilityCreateCallback() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
|
||||
}
|
||||
|
||||
async function addAbilityMonitorCallback(err: any) {
|
||||
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
|
||||
}
|
||||
|
||||
export default class OpenHarmonyTestRunner implements TestRunner {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
onPrepare() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
|
||||
}
|
||||
|
||||
async onRun() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
|
||||
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
|
||||
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
|
||||
var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
|
||||
let lMonitor = {
|
||||
abilityName: testAbilityName,
|
||||
onAbilityCreate: onAbilityCreateCallback,
|
||||
};
|
||||
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
|
||||
var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
|
||||
var debug = abilityDelegatorArguments.parameters['-D']
|
||||
if (debug == 'true')
|
||||
{
|
||||
cmd += ' -D'
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
|
||||
abilityDelegator.executeShellCommand(cmd,
|
||||
(err: any, d: any) => {
|
||||
hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
|
||||
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? '');
|
||||
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? '');
|
||||
})
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
|
||||
}
|
||||
}
|
||||
37
ohos/entry/src/ohosTest/module.json5
Normal file
37
ohos/entry/src/ohosTest/module.json5
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
{
|
||||
"module": {
|
||||
"name": "entry_test",
|
||||
"type": "feature",
|
||||
"description": "$string:module_test_desc",
|
||||
"mainElement": "TestAbility",
|
||||
"deviceTypes": [
|
||||
"phone"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:test_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "TestAbility",
|
||||
"srcEntry": "./ets/testability/TestAbility.ets",
|
||||
"description": "$string:TestAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:TestAbility_label",
|
||||
"exported": true,
|
||||
"startWindowIcon": "$media:icon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"skills": [
|
||||
{
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
],
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
16
ohos/entry/src/ohosTest/resources/base/element/string.json
Normal file
16
ohos/entry/src/ohosTest/resources/base/element/string.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
ohos/entry/src/ohosTest/resources/base/media/icon.png
Normal file
BIN
ohos/entry/src/ohosTest/resources/base/media/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
||||
6
ohos/hvigor/hvigor-config.json5
Normal file
6
ohos/hvigor/hvigor-config.json5
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
{
|
||||
"modelVersion": "5.1.0",
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
4
ohos/hvigorconfig.ts
Normal file
4
ohos/hvigorconfig.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import path from 'path'
|
||||
import { injectNativeModules } from 'flutter-hvigor-plugin';
|
||||
|
||||
injectNativeModules(__dirname, path.dirname(__dirname))
|
||||
8
ohos/hvigorfile.ts
Normal file
8
ohos/hvigorfile.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import path from 'path'
|
||||
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
import { flutterHvigorPlugin } from 'flutter-hvigor-plugin';
|
||||
|
||||
export default {
|
||||
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins:[flutterHvigorPlugin(path.dirname(__dirname))] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
13
ohos/oh-package.json5
Normal file
13
ohos/oh-package.json5
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"modelVersion": "5.1.0",
|
||||
"name": "flutter_application_2",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.6"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user