实现了首页

This commit is contained in:
7YHong 2021-12-28 12:58:20 +08:00
parent f45975f051
commit 76c07bd6bb
24 changed files with 6675 additions and 0 deletions

27
quickapp/.gitignore vendored Normal file
View File

@ -0,0 +1,27 @@
.DS_Store
node_modules
/dist
/build
/sign
# sign
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
.ide
.quickapp.preview.json

1
quickapp/.npmrc Normal file
View File

@ -0,0 +1 @@
registry="https://registry.npm.taobao.org"

6
quickapp/.prettierignore Normal file
View File

@ -0,0 +1,6 @@
package.json
manifest.json
README.md
# assets/js
src/assets/js/*.js

5
quickapp/README.md Normal file
View File

@ -0,0 +1,5 @@
# PushDeer-快应用 (开发中)
PushDeer 是一个开放源码的无 App 推送服务
这里是 PushDeer 的 `快应用` 端的源码

4399
quickapp/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

58
quickapp/package.json Normal file
View File

@ -0,0 +1,58 @@
{
"name": "pushdeer",
"version": "2.0.0",
"description": "PushDeer开源版可以自行架设的无APP推送服务",
"scripts": {
"start": "hap server --watch",
"server": "hap server",
"build": "hap build",
"release": "hap release",
"watch": "hap watch",
"debug": "hap debug",
"gen": "node ./scripts/gen/index.js",
"precommit-msg": "echo '🚧 start pre-commit checks ...' && exit 0",
"prettier": "node ./scripts/selfCloseInputTag.js && prettier --write \"src/**/*.{ux,js,json,less,scss,css,pcss,md,vue}\"",
"prettier-watcher": "onchange '**/*.md' \"src/**/**/*.{ux,js,json,less,scss,css,pcss,md,vue}\" -- prettier --write {{changed}}"
},
"dependencies": {
"apex-ui": "^1.9.2"
},
"devDependencies": {
"@babel/runtime": "^7.12.5",
"@types/quickapp": "npm:quickapp-interface@^1.0.0",
"colors": "^1.4.0",
"husky": "^7.0.1",
"less": "^4.1.1",
"less-loader": "^10.0.1",
"lint-staged": "^11.0.1",
"onchange": "^5.2.0",
"prettier": "^2.3.2",
"prettier-plugin-ux": "^0.3.0"
},
"prettier": {
"singleQuote": true,
"semi": false,
"printWidth": 80,
"proseWrap": "never",
"tabWidth": 2
},
"husky": {
"hooks": {
"pre-commit": "yarn run precommit-msg && lint-staged"
}
},
"lint-staged": {
"**/**.{ux,js,json,less,scss,css,pcss,md,vue}": [
"prettier --write",
"git add"
]
},
"keywords": [
"快应用",
"快应用示例",
"快应用模版"
],
"browserslist": [
"chrome 65"
]
}

View File

@ -0,0 +1,87 @@
/**
* @desc: gen script commandmake a new page generated by one click.
* @author: nicejade
*/
const fs = require('fs')
const path = require('path')
const colors = require('colors')
const newFolderName = process.argv[2]
String.prototype.firstUpperCase = function() {
return this.replace(/\b(\w)/g, $1 => {
return $1.toLowerCase()
})
}
const resolve = dir => {
return path.join(__dirname, '../..', dir)
}
const successExecPrint = msg => {
console.log(
colors.green(``) +
colors.cyan(`${msg} `) +
colors.green('task has been successfully executed.')
)
}
function createNewPage(newFolderPath) {
const mReg = new RegExp('@PAGE_CLASS_NAME', 'g')
const pageContent = fs.readFileSync(`${__dirname}/template.ux`, 'UTF-8')
const rootClassName = newFolderName
.firstUpperCase()
.replace(/([A-Z])/g, '-$1')
.toLowerCase()
const newContent = pageContent.replace(mReg, rootClassName)
fs.mkdirSync(newFolderPath, 0777)
fs.writeFile(`${newFolderPath}/index.ux`, newContent, error => {
if (error) throw `Something went wrong: ${error}`
})
successExecPrint('Create New Page')
}
function saveRouter2Manifest() {
const manifestPath = resolve('/src/manifest.json')
let manifestConf = fs.readFileSync(manifestPath, 'UTF-8')
manifestConf = JSON.parse(manifestConf)
const routerPages = manifestConf.router.pages
routerPages[`pages/${newFolderName}`] = {
component: 'index'
}
manifestConf = JSON.stringify(manifestConf, null, 2)
fs.writeFile(manifestPath, manifestConf, error => {
if (error) throw `Something went wrong[@saveRouter2Manifest]: ${error}`
})
successExecPrint('Save Router Into Manifest')
}
function main() {
if (!newFolderName) {
return console.warn(
`⚠️ Please enter the name of the page you want to create.`.underline.red
)
}
const folderNameReg = /^[A-Z][[A-Za-z0-9]+$/
if (!folderNameReg.test(newFolderName)) {
return console.warn(
`⚠️ Please enter the standard Folder name. Eg: XyzAbcde.`.underline.red
)
}
const newFolderPath = path.join(__dirname, `../../src/pages/${newFolderName}`)
const isExist = fs.existsSync(newFolderPath)
if (isExist) {
return console.warn(
`⚠️ ${newFolderName} already exists in the /src/pages/ directory.`
.underline.red
)
}
createNewPage(newFolderPath)
saveRouter2Manifest()
}
main()

View File

@ -0,0 +1,28 @@
<template>
<div class="wrapper">
<text class="title">{{ title }}</text>
</div>
</template>
<script>
export default {
private: {
title: '欢迎体验快应用开发'
},
onInit() {}
}
</script>
<style lang="less">
@import './../../assets/styles/style.less';
.wrapper {
.flex-box-mixins(column, center, center);
.title {
font-size: 8 * @size-factor;
text-align: center;
color: @black;
}
}
</style>

View File

@ -0,0 +1,36 @@
/**
* @file: selfCloseInputTag.js
* @desc: 遍历指定目录下 .ux 文件将其中 input 标签由 <input **></input> 转换为 <input ** />
* @date: 2019-01-23
*/
const fs = require('fs')
const path = require('path')
const quickappCodePath = './src/'
const main = codePath => {
const traversing = cpath => {
const files = fs.readdirSync(cpath)
files.forEach(fileName => {
const fPath = path.join(cpath, fileName)
const stats = fs.statSync(fPath)
stats.isDirectory() && traversing(fPath)
stats.isFile() && fPath.endsWith('.ux') && matchAndReplace(fPath)
})
}
traversing(codePath)
}
const matchAndReplace = path => {
const pageContent = fs.readFileSync(path, 'UTF-8')
const newContent = pageContent.replace(
/(<)([\s]*?)(input\b[^\/]*?)>[\s\S]*?<\/input>/gm,
'$1$3 />'
)
fs.writeFile(path, newContent, error => {
if (error) throw `Something went wrong: ${error}`
})
}
main(quickappCodePath)

17
quickapp/src/app.ux Normal file
View File

@ -0,0 +1,17 @@
<script>
/**
* 应用级别的配置,供所有页面公用
*/
const $utils = require('./helper/utils').default
const $apis = require('./helper/apis').default
/* @desc: 注入方法至全局 global,以便页面调用 */
const hook2global = global.__proto__ || global
hook2global.$utils = $utils
hook2global.$apis = $apis
export default {
onCreate() {}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,5 @@
.flex-box-mixins (@column, @justify, @align) {
flex-direction: @column;
justify-content: @justify;
align-items: @align;
}

View File

@ -0,0 +1,2 @@
@import './variables.less';
@import './mixins.less';

View File

@ -0,0 +1,9 @@
@brand: #09ba07;
@white: #ffffff;
@black: #000000;
@grey: #9393aa;
@red: #fa0101;
@green: #ffff00;
@size-factor: 5px;

View File

@ -0,0 +1,90 @@
/**
* 封装了一些网络请求方法方便通过 Promise 的形式请求接口
*/
import $fetch from '@system.fetch'
import $utils from './utils'
const TIMEOUT = 20000
Promise.prototype.finally = function(callback) {
const P = this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason =>
P.resolve(callback()).then(() => {
throw reason
})
)
}
/**
* 调用快应用 fetch 接口做网络请求
* @param params
*/
function fetchPromise(params) {
return new Promise((resolve, reject) => {
$fetch
.fetch({
url: params.url,
method: params.method,
data: params.data
})
.then(response => {
const result = response.data
const content = JSON.parse(result.data)
/* @desc: 可跟具体不同业务接口数据,返回你所需要的部分,使得使用尽可能便捷 */
content.success ? resolve(content.value) : resolve(content.message)
})
.catch((error, code) => {
console.log(`🐛 request fail, code = ${code}`)
reject(error)
})
.finally(() => {
console.log(`✔️ request @${params.url} has been completed.`)
resolve()
})
})
}
/**
* 处理网络请求timeout 是网络请求超时之后返回默认 20s 可自行修改
* @param params
*/
function requestHandle(params, timeout = TIMEOUT) {
try {
return Promise.race([
fetchPromise(params),
new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('网络状况不太好,再刷新一次?'))
}, timeout)
})
])
} catch (error) {
console.log(error)
}
}
export default {
post: function(url, params) {
return requestHandle({
method: 'post',
url: url,
data: params
})
},
get: function(url, params) {
return requestHandle({
method: 'get',
url: $utils.queryString(url, params)
})
},
put: function(url, params) {
return requestHandle({
method: 'put',
url: url,
data: params
})
}
// 如果method 您需要更多类型,可自行添加更多方法;
}

View File

@ -0,0 +1,20 @@
import $ajax from '../ajax'
/**
* @desc 在实际开发中您可以将 baseUrl 替换为您的请求地址前缀
*
* 已将 $apis 挂载在 global您可以通过如下方式进行调用
* $apis.example.getApi().then().catch().finally()
*
* 备注如果您不需要发起请求删除 apis 目录以及 app.ux 中引用即可
*/
const baseUrl = 'https://api.exampel.com/'
export default {
getApi(data) {
return $ajax.get(`${baseUrl}your-project-api`, data)
},
postOtherApi(data) {
return $ajax.post(`${baseUrl}your-project-api`, data)
}
}

View File

@ -0,0 +1,14 @@
/**
* 导出 apis 下目录的所有接口
*/
const files = require.context('.', true, /\.js/)
const modules = {}
files.keys().forEach(key => {
if (key === './index.js') {
return
}
modules[key.replace(/(^\.\/|\.js$)/g, '')] = files(key).default
})
export default modules

View File

@ -0,0 +1,29 @@
/**
* 您可以将常用的方法或系统 API统一封装暴露全局以便各页面组件调用而无需 require / import.
*/
const prompt = require('@system.prompt')
/**
* 拼接 url 和参数
*/
function queryString(url, query) {
let str = []
for (let key in query) {
str.push(key + '=' + query[key])
}
let paramStr = str.join('&')
return paramStr ? `${url}?${paramStr}` : url
}
function showToast(message = '', duration = 0) {
if (!message) return
prompt.showToast({
message: message,
duration
})
}
export default {
showToast,
queryString
}

View File

@ -0,0 +1,54 @@
{
"package": "com.pushdeer.app",
"name": "pushdeer",
"versionName": "1.0.0",
"versionCode": 1,
"minPlatformVersion": 1070,
"icon": "/assets/images/logo.png",
"features": [
{
"name": "system.prompt"
},
{
"name": "system.router"
},
{
"name": "system.shortcut"
},
{
"name": "system.fetch"
}
],
"permissions": [
{
"origin": "*"
}
],
"template/official": "demo-template",
"config": {
"logLevel": "debug"
},
"router": {
"entry": "pages",
"pages": {
"pages": {
"component": "index"
},
"pages/Home": {
"component": "index"
}
}
},
"display": {
"titleBarBackgroundColor": "#f2f2f2",
"titleBarTextColor": "#414141",
"pages": {
"pages/Demo": {
"titleBarText": "PushDeer"
},
"pages/DemoDetail": {
"titleBarText": "详情页"
}
}
}
}

View File

@ -0,0 +1,57 @@
<template>
<!-- template里只能有一个根节点 -->
<div class="wrapper">
<text class="title">{{ text }}</text>
<text class="desc"
>快应用是移动互联网新型应用生态与手机系统深度整合为用户提供更加场景化的体验。具备传统APP完整的应用体验但无需安装、即点即用。
</text>
<text class="desc"
>标准是由主流手机厂商组成的快应用联盟联合制定。其标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台,以平台化的生态模式对个人开发者和企业开发者全品类开放
</text>
<input
class="btn"
type="button"
value="欢迎使用"
onclick="onWelcomeBtnClick"
/>
</div>
</template>
<script>
export default {
private: {
text: '快应用是什么?',
},
onWelcomeBtnClick() {
$utils.showToast('快应用:复杂生活的简单答案,让生活更顺畅')
},
}
</script>
<style lang="less">
@import './../../assets/styles/style.less';
.wrapper {
.flex-box-mixins(column, center, center);
margin: 0 10 * @size-factor;
.title {
font-size: 8 * @size-factor;
text-align: center;
color: @black;
}
.desc {
margin-top: 10 * @size-factor;
color: @grey;
}
.btn {
width: 90 * @size-factor;
height: 16 * @size-factor;
border-radius: 8 * @size-factor;
background-color: @brand;
color: @white;
font-size: 30px;
margin-top: 16 * @size-factor;
}
}
</style>

View File

@ -0,0 +1,68 @@
<template>
<!-- template里只能有一个根节点 -->
<div class="container">
<div style="height: 50%">
<img class="logo" src="/assets/images/launch-logo.png" />
</div>
<div class="btn-group">
<input
class="btn-wx"
type="button"
title="mn"
value="Sign in with WeChat"
onclick="onSignWxBtnClick"
/>
</div>
</div>
</template>
<script>
import router from '@system.router'
export default {
// 页面级组件的数据模型影响传入数据的覆盖机制private内定义的属性不允许被覆盖
private: {
title: '欢迎体验快应用开发',
},
onSignWxBtnClick() {
router.push({
uri: '/pages/Home',
})
},
onInit() {
},
}
</script>
<style lang="less" scoped>
.container {
flex-direction: column;
height: 100%;
}
.logo {
margin: 0 auto;
}
.btn-group {
flex-direction: column;
width: 50%;
margin: 0 auto;
input {
margin: 16px 0;
padding: 24px;
border-width: 3px;
border-radius: 8px;
background-color: transparent;
font-size: 32px;
}
.btn-wx {
color: #296c05;
border-color: #296c05;
}
}
</style>

View File

@ -0,0 +1,3 @@
{
"rules": [{ "rule": "enable", "page": "*" }]
}

1660
quickapp/yarn.lock Normal file

File diff suppressed because it is too large Load Diff