hookehuyr

整理多余文件

Showing 194 changed files with 5122 additions and 0 deletions
# port
VITE_PORT = 8006
# 反向代理服务器地址
VITE_PROXY_TARGET = http://voice.onwall.cn
# API请求前缀
VITE_PROXY_PREFIX = /srv/
# 打包输出文件夹名称
VITE_OUTDIR = voice
# 是否开启调试
VITE_CONSOLE = 0
# appID相关
VITE_APPID=微信appID
# 资源公共路径
VITE_BASE = /
# 测试open-id
# VITE_OPENID = api-test-openid
# VITE_OPENID = o8BRf1gLDWieH3Y3JvbrI_4IjaME
VITE_OPENID = oJLZq5t9PIKLW9tm1oSUNAuPwssA
# VITE_OPENID = oJLZq5uT_6GwIh2tQWh1F9IoHZ3U
# B端账号
VITE_ID = 13761653761
# 验证码
VITE_PIN =
# 资源公共路径
VITE_BASE = /f/voice/
# 测试open-id
VITE_APP_OPENID =
# B端账号
VITE_APP_ID =
# 验证码
VITE_APP_PIN =
{
"globals": {
"EffectScope": true,
"computed": true,
"createApp": true,
"customRef": true,
"defineAsyncComponent": true,
"defineComponent": true,
"effectScope": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"inject": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onUnmounted": true,
"onUpdated": true,
"provide": true,
"reactive": true,
"readonly": true,
"ref": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"toRaw": true,
"toRef": true,
"toRefs": true,
"triggerRef": true,
"unref": true,
"useAttrs": true,
"useCssModule": true,
"useCssVars": true,
"useRoute": true,
"useRouter": true,
"useSlots": true,
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true
}
}
\ No newline at end of file
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-27 08:59:09
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-07-08 18:15:20
* @FilePath: /tswj/.eslintrc.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
module.exports = {
// parser: '@typescript-eslint/parser',
parser: 'vue-eslint-parser',
parserOptions: {
parser: 'babel-eslint',
// parser: '@typescript-eslint/parser',
},
extends: [
// add more generic rule sets here, such as:
// 'eslint:recommended',
'plugin:vue/vue3-recommended',
'./.eslintrc-auto-import.json'
// 'plugin:vue/recommended' // Use this if you are using Vue.js 2.x.
],
rules: {
// override/add rules settings here, such as:
// 'vue/no-unused-vars': 'error'
"vue/max-attributes-per-line": ["error", {
"singleline": {
"max": 20
},
"multiline": {
"max": 10
}
}],
"vue/singleline-html-element-content-newline": 0, // 在单行元素的内容之前和之后需要换行符
"vue/first-attribute-linebreak": 0, // 强制第一个属性需要换行
"vue/multi-word-component-names": 0, // 要求组件名称始终为多字
"vue/html-indent": 0, // 执行一致的缩进
"vue/html-closing-bracket-newline": 0, // 在标签的右括号之前要求或禁止换行
},
overrides: [
{
files: ['*.ts'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['plugin:@typescript-eslint/recommended'],
},
],
}
node_modules
.DS_Store
dist
dist-ssr
*.local
.history
doc
.vscode
src/views/test/*
src/store/test.js
cypress
src/test/mocha/test.js
cypress.json
src/test
.idea
{
"esversion": 11,
"asi": true
}
\ No newline at end of file
v18.13.0
export function createProxy(prefix, target) {
const ret = {};
ret[prefix] = {
target,
changeOrigin: true,
ws: true,
// rewrite: (path) => path.replace(/^\/api/, '')
// rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
}
return ret
}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}
No preview for this file type
<!DOCTYPE html>
<html lang='zh'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<title></title>
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.compat.css" /> -->
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEzFrlVSgeuOQT
sglIR5RxEASnH0XKKxg/rl6U0pe6NGHwnybhdO6ZHAWRIU4OVOVDCI3OnJ2/2c2o
eCT9L+fDGJew3BAMZvKKn1A/o5xM5YYJo8IKKeJbehjXajXdRJ5WkhAKwSH+rSJE
nADUF4S5sqbXVlvttc1QUVL9GprPq5OBptDfcs6AM+dN1XOn/LgFt0KJ1C80Ah1a
TLjLLFOGEJNLtTAUpLzJb5DKLro88QgPK8ek5afOKiOMULnFk3QJCZ1W98Xd75zq
5Fz/FLCmTgkZMGe+iLr44MewmwMu1H/cHtWVkfEZiFUcRa5xc6SbvMGENfu/3/L4
rLQ7ppMRAgMBAAECggEAaNnMD+WoA35Unh28DlN8xiRXpkbmIwmE2ODpKXduOVoR
WGcjCvoG6XJhkOpisQYQQ/+5tfwBnCbKCNlCM9cjLvHaV/NXZZQv4yVwVwevjdS3
7kjeaBXasQxDUfoXirU1e0BE5cXye8L4v/8x/c4t+9YwSAiN3/99zS4W/hz/oGaE
fCkjHOHQkQKw0invQz3kf86iyanLBS/rllJAtZKmRFqZKchWR68m+sDcbAP320tb
z2yi7og8QcP+kuqQWr2QVOCfD7zz5ihLDCnzipNU/7JmHIkUXqYI8NKGLSftN0LB
NSmOinsx/oM4gu7IAMsyZjpM4UkAHieJEtAHM4RIMQKBgQD13iV4QgupvQauwnl/
Kezse8zSjZS2YSUVZRsMDqw62sVa2BE4CV9NCWO3nPp5MDSDXahjDuoS640askM5
ynWQWbDmttomlVqPbXwHUfKqTLgUIvl7byIuyoJHAIlL/7xEOeHHa5oIy49aKTnw
vrJMTrBifNsdqWp2ht64hwNL3QKBgQDM6IklIbfXDEdji7LAaCzu24uttWAwLn69
d1q5fMVWfWBl3l8O3gvbJSxXTeLHNcjsOb1iQq+3CT/eV+g+5xv17EQH+32ASq9d
VBQ0tZC09BkMcDKPulC9JoGVsgLnIbjOy7GJKOhANqYh18FW9JAYvzZFWzNpsGAR
kXZIGt/axQKBgQDotvZCSEkfxPHhUeOL0FQXVep9VFLw+SwPfx5FoFG2d0Gbha1u
m7hfg0amEWgmctERkgGCmShG9jsdjKMCvTXfhnVhOqtrH6yS2y8tAoysUmddb+kx
wvPY1AbRS5monItHDH4+sgMe1gV+ck0MKIM8pLJg1grTnXpOa8O9ZtVg5QKBgDFM
4XJlom3DLons2p0gc28ks36f3Py6sxOy28k1E+WzVLYtwoE5O3EGiJyYyK9VaXos
ijxR/yTyvMMqM16vDDMnHVcuUwvC7F5wFEx6Qs7GzCAJ/qBGG5bm5Na3datWmbhn
mdd+WCLbAy2xU3swbFsH5m7Zeo07OmH/tY2zqZhhAoGBALxxnWJ4bgtZHcHREB0A
QP6ZSLWoUk0ggoPuwSVgHImW+/C1/38KjHgv4UmhS59MpNqX3BOUgP1lTKQ4ifut
N2/tFBdZXNdsbRNYp2UTGAHzUK6sUGyvY4g6mAZJWsIsVIzuLrZdrQywlglBpM4Q
v/Q0jcIl9880opSG/+dfRbpW
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEMTCCApmgAwIBAgIRAJqTbr7oXEP7a1vMS7zyApQwDQYJKoZIhvcNAQELBQAw
ZzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMR4wHAYDVQQLDBVodXlp
cnVpQEhZUi1NQUMubG9jYWwxJTAjBgNVBAMMHG1rY2VydCBodXlpcnVpQEhZUi1N
QUMubG9jYWwwHhcNMjMwNTE5MDcxMTE0WhcNMjUwODE5MDcxMTE0WjBVMScwJQYD
VQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxKjAoBgNVBAsMIWh1
eWlydWlASFlSLU1BQy5sb2NhbCAo6IOh5YWI55SfKTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMTMWuVVKB645BOyCUhHlHEQBKcfRcorGD+uXpTSl7o0
YfCfJuF07pkcBZEhTg5U5UMIjc6cnb/Zzah4JP0v58MYl7DcEAxm8oqfUD+jnEzl
hgmjwgop4lt6GNdqNd1EnlaSEArBIf6tIkScANQXhLmyptdWW+21zVBRUv0ams+r
k4Gm0N9yzoAz503Vc6f8uAW3QonULzQCHVpMuMssU4YQk0u1MBSkvMlvkMouujzx
CA8rx6Tlp84qI4xQucWTdAkJnVb3xd3vnOrkXP8UsKZOCRkwZ76Iuvjgx7CbAy7U
f9we1ZWR8RmIVRxFrnFzpJu8wYQ1+7/f8vistDumkxECAwEAAaNqMGgwDgYDVR0P
AQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFJbi3Ybj
xDBPnN8B3bayujege6IKMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAAAYcEwKgC
ejANBgkqhkiG9w0BAQsFAAOCAYEAi3Scjz10WV/nJnlKHGbQxBgM4FqOQMEMqNoQ
ojdRQqY7iTfV+6265TFaZ9pY27+ZKzL8Qyb6htqNYuRKACXqEohHHJBdDlGV9Kda
hxznoP9ZBYm4NoiSiIJIQmEVy5SH/qb208gZPXb8mQT/czPPmQAE0oTWrVUDRkJl
YGJmfcdVuN8JfLqW0HxUdP89gqH8nHv72+wZpcqc9i/yVwCfjhqgbinwU/rkZRqW
7SIBVlDJs7d+4EuDMQMMe21w4b3isXr+LVtrH6I1MtQ0hTd9bQiMvl6HQ6hDK9Yd
VRz2ubj5p2/qzCchxxfMMJjAea8YNlQCL593963PKzDPcaJnw8j9RtySpeIxiPPQ
4+oRkZgO6Bd9OrxOAmoLG8+bJJbwmWC0LxH2nvYmArFgzKDu5hqwGQnLP0/7GeIk
fNqWPJ84rj0V3lfVRKYWYwXNJbFTCQ3/ewN6mTChzBWgmRFUv6LjSfzq/X2l5tX0
vLXgvm2XxAtQoVRUAYsRRRrFwguT
-----END CERTIFICATE-----
使用mkcert在本地生成2个免费的https证书(此命令会生成两个文件: localhost+2.pem, localhost+2-key.pem)
mkcert localhost 127.0.0.1 ::1
https://blog.csdn.net/themagickeyjianan/article/details/106836904
https://blog.wangjunfeng.com/post/local_https/
https://juejin.cn/post/7141308011921801223?searchId=20230817153624B0F9ACBED49D8807E243#heading-7
This diff could not be displayed because it is too large.
{
"name": "my_record",
"description": "",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"start": "vite --host 0.0.0.0",
"build": "vite build",
"build-watch": "vite build --watch",
"build-ts": "vue-tsc --noEmit && vite build",
"serve": "vite preview",
"cypress:open": "cypress open"
},
"dependencies": {
"@vitejs/plugin-legacy": "^1.8.2",
"@vueuse/core": "^8.5.0",
"animate.css": "^4.1.1",
"dayjs": "^1.11.3",
"default-passive-events": "^2.0.0",
"global": "^4.4.0",
"html2canvas": "^1.4.1",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"mui-player": "^1.6.0",
"recorder-core": "^1.3.23122400",
"typescript": "^4.7.3",
"uuid": "^8.3.2",
"vant": "^4.8.1",
"vconsole": "^3.14.6",
"vite-plugin-dynamic-import": "^0.9.6",
"vite-plugin-mp": "^1.6.1",
"vue": "^3.2.36",
"weixin-js-sdk": "^1.6.5"
},
"devDependencies": {
"@types/jquery": "^3.5.14",
"@types/lodash": "^4.14.182",
"@types/moment": "^2.13.0",
"@typescript-eslint/parser": "^5.27.1",
"@vitejs/plugin-vue": "^2.3.3",
"@vue/compiler-sfc": "^3.2.36",
"axios": "^0.27.2",
"chai": "^4.3.6",
"cypress": "^9.7.0",
"eslint-plugin-vue": "^9.0.1",
"less": "^4.1.2",
"mocha": "^10.0.0",
"pinia": "^2.0.14",
"postcss-px-to-viewport": "^1.1.1",
"qs": "^6.10.3",
"tslint": "^6.1.3",
"unplugin-auto-import": "^0.8.8",
"unplugin-vue-components": "^0.26.0",
"unplugin-vue-define-options": "^0.6.1",
"vite": "^2.9.9",
"vite-plugin-style-import": "1.4.1",
"vue-router": "^4.0.15"
}
}
module.exports = {
printWidth: 100, // 代码行的宽度,通用建议每行最大长度建议为100/120,但最好不超过这两个数。
tabWidth: 2, // 指定每次缩进的空格数。
semi: true, // 是否在代码语句结尾添加分号。
vueIndentScriptAndStyle: true,
singleQuote: true, // 是否使用单引号,JSX单独设置。
trailingComma: 'all', // 在多行以逗号分割的句法中尽可能补充尾行逗号。
bracketSpacing: true, // 是否在对象属性与大括号之间填充空格。
bracketSameLine: false, // 开始标签的右尖括号是否跟随在最后一行属性末尾。
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto', // 设置换行风格,避免不同操作系统造成的大量代码diff。
singleAttributePerLine: false // 在Html,Vue,JSX中是否强制每条属性占用一行。
};
#!/usr/bin/env sh
# -----------------------------------------------
# Filename: publish.sh
# Revision: 1.0
# Date: 2022年5月20日
# Author: Hooke
# Description: **** 根据php项目相应特征书写项目发布流程
# -----------------------------------------------
# 当发生错误时中止脚本
set -e
# 本地Git服务器目录路径
path=/Users/huyirui/program/itomix/git/isp/f
# 编译输出文件夹
output=voice
# 打包
npm run build
# 移除Git服务器目录下项目文件夹
rm -r $path"/${output:?}/images"
rm -r $path"/${output:?}/index.html"
rm -r $path"/${output:?}/static"
# 把本地编译输出文件夹添加到服务器目录
mv "${output:?}/images" $path"/${output:?}"
mv "${output:?}/index.html" $path"/${output:?}"
mv "${output:?}/static" $path"/${output:?}"
# 提交到Git服务器
cd $path"/${output:?}"
git pull
git add -A
git commit -m '前端网页更新'
git push
# 更新SSH服务器上文件
# ssh -p 22 itomix@ipadbiz.cn 'cd /opt/voice/f/voice && git pull'``
export interface commentListType {
id: string;
avatar: string;
name: string;
kg_name: string;
comment_time: string;
note: string;
c_action: string;
c_name: string;
cover: string;
prod_id: string;
perf_id: string;
book_id: string;
perf_name: string;
book_name: string;
localism_type: string;
is_new: number;
}
<!--
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-26 23:52:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-01-02 13:59:58
* @FilePath: /tswj/src/App.vue
* @Description:
-->
<template>
<!-- 页面缓存 -->
<router-view v-slot="{ Component, route }">
<keep-alive :include="keepPages" :max="10">
<component :is="Component" :key="route.name" />
</keep-alive>
</router-view>
</template>
<script setup>
import { mainStore, useTitle } from '@/utils/generatePackage'
import { computed, watchEffect, onMounted } from 'vue';
import { useRoute } from 'vue-router'
import { setToastDefaultOptions } from 'vant';
// 会根据配置判断是否显示调试控件
// eslint-disable-next-line no-unused-vars
import vConsole from '@/utils/vconsole'
// 初始化WX环境
import wx from 'weixin-js-sdk'
import { wxJsAPI } from '@/api/wx/config'
import { apiList } from '@/api/wx/jsApiList.js'
// 使用 include + pinia 状态管理动态缓存页面
const store = mainStore()
const keepPages = computed(() => store.getKeepPages)
// TAG: 全局设置页面标题
const $route = useRoute();
watchEffect(
() => useTitle($route.meta.title)
)
// TAG: 全局配置Toast
// setToastDefaultOptions({
// duration: 2000,
// className: 'zIndex',
// wordBreak: 'all',
// });
onMounted(async () => {
const { data } = await wxJsAPI();
data.jsApiList = apiList;
wx.config(data);
wx.ready(() => {
wx.showAllNonBaseMenuItem();
});
wx.error((err) => {
console.warn(err);
});
})
</script>
<style lang="less">
@prefix: ~'@{namespace}-x';
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
body {
position: relative;
// --van-white: #fff;
// --van-blue: #1989fa;
// --van-button-primary-color: var(--van-white);
// --van-button-primary-background: var(--van-primary-color);
/* 全局修改主色调 */
// --van-blue: #F9D95C;
// background-color: #FAFAFA;
p {
margin: 0;
padding: 0;
}
}
.@{prefix} {
color: red;
}
.global-center {
position: relative;
top: 50%;
transform: translateY(-50%);
}
.zIndex {
z-index: 4500 !important;
}
.van-popup.van-toast {
z-index: 3003 !important;
background: rgba(0, 0, 0, 0.7) !important;
}
</style>
/*
* @Date: 2022-06-20 16:33:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 16:35:56
* @FilePath: /tswj/src/api/B/audit.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
const Api = {
CHECK_PROD: '/srv/?a=check_prod',
}
/**
* @description 审核作品
* @param {*} prod_id
* @param {*} status
* @param {*} check_note
* @returns {*} data
*/
export const checkProdAPI = (params) => fn(fetch.post(Api.CHECK_PROD, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-09 02:25:31
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-17 22:32:59
* @FilePath: /tswj/src/api/B/kg.js
* @Description: 幼儿园主页接口
*/
import { fn, fetch } from '@/api/fn';
const Api = {
KG_INFO: '/srv/?a=kg_info',
MY_KG: '/srv/?a=my_kg',
}
/**
* @description 幼儿园详情
* @returns {*} data
*/
export const kgInfoAPI = (params) => fn(fetch.get(Api.KG_INFO, params));
/**
* @description 我的幼儿园详情
* @returns {*} data
*/
export const myKgAPI = (params) => fn(fetch.get(Api.MY_KG, params));
/*
* @Date: 2022-06-20 12:56:47
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 15:41:41
* @FilePath: /tswj/src/api/B/localism.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
const Api = {
LOCALISM_LIST_MODI: '/srv/?a=localism_list4modi',
ADD_LOCALISM: '/srv/?a=add_localism',
MODIFY_PROD_LOCALISM: '/srv/?a=modify_prod_localism',
}
/**
* @description 幼儿园方言列表
* @returns {*} data
*/
export const localismListModiAPI = (params) => fn(fetch.get(Api.LOCALISM_LIST_MODI, params));
/**
* @description 新增方言
* @param {string} localism_name
* @returns {*} data
*/
export const addLocalismAPI = (params) => fn(fetch.post(Api.ADD_LOCALISM, params));
/**
* @description 更新作品方言
* @param {string} prod_id
* @param {string} localism_name
* @returns {*} data
*/
export const modifyProdLocalismAPI = (params) => fn(fetch.post(Api.MODIFY_PROD_LOCALISM, params));
/*
* @Date: 2022-06-17 15:03:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 09:59:50
* @FilePath: /tswj/src/api/B/login.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
const Api = {
B_LOGIN: '/srv/?a=b_login',
B_LOGOUT: '/srv/?a=b_logout',
}
/**
* @description 登录接口
* @param {*} phone 手机号
* @param {*} pin 验证码
*/
export const bLoginAPI = (params) => fn(fetch.post(Api.B_LOGIN, params));
/**
* @description 登出接口
*/
export const bLogoutAPI = (params) => fn(fetch.post(Api.B_LOGOUT, params));
/*
* @Date: 2022-05-26 19:50:27
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-18 00:15:08
* @FilePath: /tswj/src/api/C/book.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
const Api = {
ADD_SUBSCRIBE: '/srv/?a=add_subscribe',
BOOK_INFO: '/srv/?a=book_info',
}
/**
* @description: 订阅书籍操作
* @param {String} book_id 书籍 ID
* @returns
*/
export const addSubscribeAPI = (params) => fn(fetch.post(Api.ADD_SUBSCRIBE, params));
/**
* @description: 书籍详情
* @param {String} book_id 书籍 ID
* @param {String} localism_type 方言类型
* @param {*} limit
* @param {*} offset
* @returns
*/
export const bookInfoAPI = (params) => fn(fetch.get(Api.BOOK_INFO, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-01 16:00:48
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-07-01 16:40:05
* @FilePath: /tswj/src/api/C/donate.js
* @Description: 捐钱操作API
*/
import { fn, fetch } from '@/api/fn';
const Api = {
PREPARE_DONATE: '/srv/?a=prepare_donate',
ADD_DONATE: '/srv/?a=add_donate',
ONE_CERT: '/srv/?a=one_cert',
}
/**
* @description: 当前用户捐献所需信息
* @summary 适用于 访客进入操作,幼儿园节目操作,表演者节目操作
* @param {String} kg_id 幼儿园ID
* @param {String} perf_id 表演者ID
* @returns
*/
export const prepareDonateAPI = (params) => fn(fetch.get(Api.PREPARE_DONATE, params));
/**
* @description: 用户捐献
* @param {Number} qty 数量
* @param {String} donate_name 捐赠人名称
* @param {Number} kg_id 指定助力幼儿园id
* @param {Number} perf_id 指定助力儿童id
* @returns
*/
export const addDonateAPI = (params) => fn(fetch.post(Api.ADD_DONATE, params));
/**
* @description: 捐赠证书
* @param {String} donate_id 捐赠ID
* @returns
*/
export const oneCertAPI = (params) => fn(fetch.get(Api.ONE_CERT, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-18 21:12:23
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-09 09:21:54
* @FilePath: /tswj/src/api/C/kg.js
* @Description: 幼儿园相关接口
*/
import { fn, fetch } from '@/api/fn';
const Api = {
KG_LIST: '/srv/?a=kg_list',
KG_DONATE_LIST: '/srv/?a=donate_list',
KG_DONATE_RANK: '/srv/?a=donate_rank',
KG_BOOK_LIST: '/srv/?a=kg_book_list',
}
/**
* @description 幼儿园列表页
* @param {*} params 参数
* @returns {array} data
*/
export const kgListAPI = (params) => fn(fetch.get(Api.KG_LIST, params));
/**
* @description 幼儿园捐赠列表页
* @param {*} kg_id 幼儿园ID
* @param {*} limit 20
* @param {*} offset 0
* @returns {array} data
*/
export const kgDonateListAPI = (params) => fn(fetch.get(Api.KG_DONATE_LIST, params));
/**
* @description 幼儿园捐赠排行榜
* @param {*} kg_id 幼儿园ID
* @param {*} limit 20
* @param {*} offset 0
* @returns {array} data
*/
export const kgDonateRankAPI = (params) => fn(fetch.get(Api.KG_DONATE_RANK, params));
/**
* @description 幼儿园书籍列表
* @param {*} kg_id 幼儿园ID
* @returns {*} data
*/
export const kgBookListAPI = (params) => fn(fetch.get(Api.KG_BOOK_LIST, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-18 22:16:10
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-09-06 11:32:16
* @FilePath: /tswj/src/api/C/me.js
* @Description: 我的页面接口操作
*/
import { fn, fetch } from '@/api/fn';
const Api = {
CHANGE_PERFORMER: '/srv/?a=change_performer',
MY_INFO: '/srv/?a=my_info',
MY_PERFORMER: '/srv/?a=my_performer',
MY_LIKE: '/srv/?a=my_like',
MY_FAVOR: '/srv/?a=my_favor',
MY_COMMENT: '/srv/?a=my_comment',
MY_ATME: '/srv/?a=my_atme',
DEL_COMMENT: '/srv/?a=del_comment',
MY_SUBSCRIBE: '/srv/?a=my_subscribe',
MY_FOLLOW: '/srv/?a=my_follow',
MY_PROD: '/srv/?a=my_prod',
}
/**
* @description: 切换儿童角色
* @param {*} params
* @returns
*/
export const changePerformerAPI = (params) => fn(fetch.post(Api.CHANGE_PERFORMER, params));
/**
* @description: 获取儿童信息
* @param {object} params 参数
* @returns {*} 布尔值||查询值
*/
export const myInfoAPI = (params) => fn(fetch.get(Api.MY_INFO, params));
/**
* @description: 角色列表信息
* @param {*} params
* @returns
*/
export const myPerformerAPI = (params) => fn(fetch.get(Api.MY_PERFORMER, params));
/**
* @description: 点赞列表信息
* @param {*} params
* @returns
*/
export const myLikeAPI = (params) => fn(fetch.get(Api.MY_LIKE, params));
/**
* @description: 收藏列表信息
* @param {*} params
* @returns
*/
export const myFavorAPI = (params) => fn(fetch.get(Api.MY_FAVOR, params));
/**
* @description: 用户评论列表
* @param {string} limit
* @param {string} offset
* @returns
*/
export const myCommentAPI = (params) => fn(fetch.get(Api.MY_COMMENT, params));
/**
* @description: 删除用户评论
* @param {string} comment_id 评论ID
* @returns
*/
export const delCommentAPI = (params) => fn(fetch.post(Api.DEL_COMMENT, params));
/**
* @description: /@/我的列表
* @param {string} limit
* @param {string} offset
* @returns
*/
export const myAtmeAPI = (params) => fn(fetch.get(Api.MY_ATME, params));
/**
* @description: 我的订阅
* @returns
*/
export const mySubscribeAPI = (params) => fn(fetch.get(Api.MY_SUBSCRIBE, params));
/**
* @description: 我的关注
* @returns
*/
export const myFollowAPI = (params) => fn(fetch.get(Api.MY_FOLLOW, params));
/**
* @description: 我的作品
* @returns
*/
export const myProdAPI = (params) => fn(fetch.get(Api.MY_PROD, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-26 21:16:59
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-10 13:30:31
* @FilePath: /tswj/src/api/C/perf.js
* @Description: 用户相关API
*/
import { fn, fetch } from '@/api/fn';
const Api = {
PERF_INFO: '/srv/?a=perf_info',
ADD_FOLLOW: '/srv/?a=add_follow',
ADD_COMMENT: '/srv/?a=add_comment',
ADD_REPLY: '/srv/?a=add_reply',
MY_COMMENT_TIME: '/srv/?a=my_comment_time',
}
/**
* @description: 获取表演者信息
* @param {String} perf_id 表演者ID
* @returns
*/
export const perfInfoAPI = (params) => fn(fetch.post(Api.PERF_INFO, params));
/**
* @description: 关注用户操作
* @param {String} perf_id 表演者ID
* @returns
*/
export const addFollowAPI = (params) => fn(fetch.post(Api.ADD_FOLLOW, params));
/**
* @description: 用户新增评论操作
* @param {String} prod_id 作品ID
* @returns
*/
export const addCommentAPI = (params) => fn(fetch.post(Api.ADD_COMMENT, params));
/**
* @description: 用户新增回复操作
* @param {String} comment_id 评论ID
* @returns
*/
export const addReplyAPI = (params) => fn(fetch.post(Api.ADD_REPLY, params));
/**
* @description: 更新用户留言事件
* @summary 处理留言已读未读问题
* @param {String} optr_type 操作类型 my_comment | atme_comment
* @returns
*/
export const myCommentTimeAPI = (params) => fn(fetch.post(Api.MY_COMMENT_TIME, params));
import { fn, fetch } from '@/api/fn';
const Api = {
PROD_ACTION: '/srv/?a=prod_action',
PROD_INFO: '/srv/?a=prod_info',
}
/**
* @description: 操作作品动作
* @param {String} type 动作类型:like, favor, play
* @param {String} prod_id 作品 ID
* @returns
*/
export const prodActionAPI = (params) => fn(fetch.post(Api.PROD_ACTION, params));
/**
* @description: 查询作品详情
* @param {String} type 动作类型:like, favor, play
* @param {String} prod_id 作品 ID
* @returns
*/
export const prodInfoAPI = (params) => fn(fetch.get(Api.PROD_INFO, params));
/*
* @Date: 2022-06-17 14:54:29
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-18 22:18:46
* @FilePath: /tswj/src/api/common.js
* @Description: 通用接口
*/
import { fn, fetch, uploadFn } from '@/api/fn';
const Api = {
SMS: '/srv/?a=sms',
TOKEN: '/srv/?a=upload',
SAVE_FILE: '/srv/?a=upload&t=save_file',
}
/**
* @description: 发送验证码
* @param {*} phone 手机号码
* @returns
*/
export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
/**
* @description: 获取七牛token
* @param {*} filename 文件名
* @param {*} file 图片base64
* @returns
*/
export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));
/**
* @description: 上传七牛
* @param {*}
* @returns
*/
export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config));
/**
* @description: 保存图片
* @param {*} format
* @param {*} hash
* @param {*} height
* @param {*} width
* @param {*} filekey
* @returns
*/
export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params));
/*
* @Date: 2022-05-18 22:56:08
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-01-02 16:46:57
* @FilePath: /tswj/src/api/fn.js
* @Description: 文件描述
*/
import axios from '@/utils/axios';
// import { Toast } from 'vant';
import { showToast } from 'vant';
import qs from 'Qs'
/**
* 网络请求功能函数
* @param {*} api 请求axios接口
* @returns 请求成功后,获取数据
*/
export const fn = (api) => {
return api
.then(res => {
if (res.data.code === 1) {
return res.data || true;
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
// Toast({
// icon: 'close',
// message: res.data.msg
// });
showToast(res.data.msg);
return false;
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
return false;
})
.finally(() => { // 最终执行
})
}
/**
* 七牛返回格式
* @param {*} api
* @returns
*/
export const uploadFn = (api) => {
return api
.then(res => {
if (res.statusText === 'OK') {
return res.data || true;
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
// Toast({
// icon: 'close',
// message: res.data.msg
// });
showToast(res.data.msg);
return false;
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
return false;
})
}
/**
* 统一 GET/POST 不同传参形式
*/
export const fetch = {
get: function (api, params) {
return axios.get(api, { params })
},
post: function (api, params) {
return axios.post(api, params)
},
stringifyPost: function (api, params) {
return axios.post(api, qs.stringify(params))
},
basePost: function (url, data, config) {
return axios.post(url, data, config)
}
}
/*
* @Date: 2023-12-31 11:20:51
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-01-02 16:48:10
* @FilePath: /tswj/src/api/new_year_2024.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
const Api = {
GET_AUDIO: '/srv/?a=meet_spring&t=get_audio',
SAVE_EVENT: '/srv/?a=meet_spring&t=save_event',
GET_BOOK: '/srv/?a=meet_spring&t=get_book',
ADD_DONATE: '/srv/?a=meet_spring&t=add_donate',
CERT_LIST: '/srv/?a=meet_spring&t=cert_list',
SHARE_WISH_LIST: '/srv/?a=meet_spring&t=share_wish_list',
WISH_PRIZE: '/srv/?a=meet_spring&t=win_prize',
DEAL_PRIZE: '/srv/?a=meet_spring&t=deal_prize',
PRIZE_LIST: '/srv/?a=meet_spring&t=prize_list',
}
/**
* @description: 随机获取一个音频素材
* @returns
*/
export const getAudioAPI = (params) => fn(fetch.post(Api.GET_AUDIO, params));
/**
* @description: 埋点
* @returns
*/
export const saveEventAPI = (params) => fn(fetch.post(Api.SAVE_EVENT, params));
/**
* @description: 随机获取4本书
* @returns
*/
export const getBookAPI = (params) => fn(fetch.get(Api.GET_BOOK, params));
/**
* @description: 生成捐助记录
* @returns
*/
export const addDonateAPI = (params) => fn(fetch.post(Api.ADD_DONATE, params));
/**
* @description: 证书列表
* @returns
*/
export const certListAPI = (params) => fn(fetch.get(Api.CERT_LIST, params));
/**
* @description: 分享祝福语列表
* @returns
*/
export const shareWishListAPI = (params) => fn(fetch.get(Api.SHARE_WISH_LIST, params));
/**
* @description: 抽奖
* @returns
*/
export const wishPrizeAPI = (params) => fn(fetch.post(Api.WISH_PRIZE, params));
/**
* @description: 处置奖品
* @returns
*/
export const dealPrizeAPI = (params) => fn(fetch.post(Api.DEAL_PRIZE, params));
/**
* @description: 中奖列表
* @returns
*/
export const prizeListAPI = (params) => fn(fetch.get(Api.PRIZE_LIST, params));
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-09 13:32:44
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-14 14:47:01
* @FilePath: /tswj/src/api/wx/config.js
* @Description:
*/
import { fn, fetch } from '@/api/fn';
const Api = {
WX_JSAPI: '/srv/?a=wx_share',
}
/**
* @description 获取微信CONFIG配置文件
* @param {*} url
* @returns {*} cfg
*/
export const wxJsAPI = (params) => fn(fetch.get(Api.WX_JSAPI, params));
/*
* @Date: 2022-06-13 14:18:57
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 14:27:21
* @FilePath: /tswj/src/api/wx/jsApiList.js
* @Description: 文件描述
*/
export const apiList = [
"updateAppMessageShareData",
"updateTimelineShareData",
"onMenuShareTimeline",
"onMenuShareAppMessage",
"onMenuShareQQ",
"onMenuShareWeibo",
"onMenuShareQZone",
"startRecord",
"stopRecord",
"onVoiceRecordEnd",
"playVoice",
"pauseVoice",
"stopVoice",
"onVoicePlayEnd",
"uploadVoice",
"downloadVoice",
"chooseImage",
"previewImage",
"uploadImage",
"downloadImage",
"translateVoice",
"getNetworkType",
"openLocation",
"getLocation",
"hideOptionMenu",
"showOptionMenu",
"hideMenuItems",
"showMenuItems",
"hideAllNonBaseMenuItem",
"showAllNonBaseMenuItem",
"closeWindow",
"scanQRCode",
"chooseWXPay",
"openProductSpecificView",
"addCard",
"chooseCard",
"openCard"
]
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-09 13:32:44
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-09 13:42:06
* @FilePath: /tswj/src/api/wx/config.js
* @Description:
*/
import { fn, fetch } from '@/api/fn';
const Api = {
WX_PAY: 'c/bill_paymentForBill.do',
}
/**
* @description 微信支付接口
* @param {*}
* @returns {*}
*/
export const wxPayAPI = (params) => fn(fetch.get(Api.WX_PAY, params));
.modify-top {
z-index: 36;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 10px;
background-image: url('http://gyzs.onwall.cn/top-xian%402x.png');
background-size: contain;
}
.content-bg {
/**
* background-color and background-image 共存,不能使用渐变色
* 图片铺平当时精度提高看看效果
* 直接用渐变色
* 不使用渐变色背景
*/
height: 100%;
min-height: 100vh;
// background-image: url('@images/bg-yellow-duan@2x.png');
background-image: url('http://gyzs.onwall.cn/bg-yellow-duan%402x.png');
// background-size: cover;
// background: linear-gradient(360deg, #FDD347 0%, #FFED6D 100%) ;
}
@namespace: 'tswj';
/* ============ 颜色 ============ */
// 主色调
@base-color: #11D2B1;
// 文字颜色
@base-font-color: #FFFFFF;
// 定义一个映射
#colors() {
base-color: @base-color;
base-font-color: @base-font-color;
}
// 混合
.width100 {
width: 100%;
}
// Generated by 'unplugin-auto-import'
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
import axios from 'axios';
import { Toast } from 'vant';
export default {
// 初始化设置
init: {
mounted () {
document.title = this.$route.meta.title;
}
},
likeFn: {
methods: {
/**
* 用户相关操作
* @param {String} type 动作类型:like, favor, play
* @param {String} id 作品 ID
*/
handleAction (type, id) { // 用户操作
axios.post('/srv/?a=prod_action', {
action_type: type,
prod_id: id
})
.then(res => {
if (res.data.code === 1) {
if (res.data.msg === `${type}-add-OK`) { // 动作操作成功
this.getProductDetail(type, id);
if (type === 'favor') {
Toast('收藏成功');
}
if (type === 'like') {
Toast('点赞成功');
}
} else { // 取消操作
this.getProductDetail(type, id);
if (type !== 'play') {
Toast('取消成功');
}
}
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
});
},
getProductDetail (type, id) { // 查询更新作品详情
axios.get('/srv/?a=prod_info', {
params: {
prod_id: id
}
})
.then(res => {
if (res.data.code === 1) {
this.detail[`is_${type}`] = res.data.data[`is_${type}`];
this.detail[`${type}_num`] = res.data.data[`${type}_num`];
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
});
}
}
}
};
/**
* 判断多行省略文本
* @param {*} id 目标dom标签
* @returns
*/
const hasEllipsis = (id) => {
let oDiv = document.getElementById(id);
let flag = false
if (oDiv.scrollHeight > oDiv.clientHeight) {
flag = true
}
return flag
}
export default {
hasEllipsis
}
\ No newline at end of file
import { ref } from 'vue'
import { useBrowserLocation, useEventListener, useTitle, useUrlSearchParams, useWindowScroll, logicAnd } from '@vueuse/core'
export const fn = () => {
// const location = useBrowserLocation()
// console.warn(location.value);
// useEventListener(window, 'scroll', (evt) => {
// const { x, y } = useWindowScroll()
// // console.warn(x.value);
// console.warn(y.value);
// })
// useTitle('New Title')
const a = ref(true)
const b = ref(true)
const flag = a.value && b.value
console.warn(flag);
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-17 12:13:13
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-12 22:50:29
* @FilePath: /tswj/src/composables/index.js
* @Description:
*/
import { onMounted, onUnmounted } from 'vue'
import { useVideoList } from '@/composables/useVideoList.js'
import { useDefaultPerf } from '@/composables/useDefaultPerf.js'
import { useBookList, useAsyncBookList } from '@/composables/useBookList.js'
import { useShortcutBar } from '@/composables/useShortcutBar.js'
import { useScrollTop } from '@/composables/useScrollTop.js'
import { useMessageList } from '@/composables/useMessageList.ts'
export {
useVideoList,
useDefaultPerf,
useBookList,
useAsyncBookList,
useShortcutBar,
useScrollTop,
useMessageList,
}
/**
* 添加和清除 DOM 事件监听器
* @param {*} target
* @param {*} event
* @param {*} callback
*/
export function useEventListener(target, event, callback) {
onMounted(() => target?.addEventListener(event, callback))
onUnmounted(() => target?.removeEventListener(event, callback))
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-07 17:46:54
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-12 22:55:58
* @FilePath: /tswj/src/composables/useBookList.js
* @Description:
*/
import { ref } from 'vue'
import axios from '@/utils/axios';
import { Toast } from 'vant';
import { useRoute } from 'vue-router';
import { kgBookListAPI } from '@/api/C/kg'
export const useBookList = () => {
const $route = useRoute();
const emptyStatus = ref(false);
// tslint:disable-next-line: variable-name
const kg_id = $route.query.kg_id ? $route.query.kg_id : '';
const kgInfo = ref({
id: '',
logo: '',
name: '',
multi_name: '',
book_list: []
});
if (kg_id) { // 从学校列表进入
axios.get('/srv/?a=kg_book_list', {
params: {
kg_id
}
})
.then(res => {
if (res.data.code === 1) {
kgInfo.value = res.data.data;
kgInfo.value.book_list.forEach(item => {
item.show = true; // 默认显示所有,给搜索功能留的hook
});
// 有空格分割name
if (kgInfo.value.name.indexOf(' ') > -1) {
kgInfo.value.multi_name = kgInfo.value.name.split(' ');
}
if (!kgInfo.value.book_list.length) {
emptyStatus.value = true;
}
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
})
} else { // 从访客进入
axios.get('/srv/?a=book_list')
.then(res => {
if (res.data.code === 1) {
res.data.data.forEach(item => {
item.show = true; // 默认显示所有,给搜索功能留的hook
});
kgInfo.value = {
book_list: res.data.data
}
if (!kgInfo.value.book_list.length) {
emptyStatus.value = true;
}
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
})
}
return {
kg_id,
kgInfo,
emptyStatus
}
}
// !!废弃方法
// 前端使用方式过于复杂
export const useAsyncBookList = async () => {
const $route = useRoute();
const emptyStatus = ref(false);
// tslint:disable-next-line: variable-name
const kg_id = $route.query.kg_id ? $route.query.kg_id : '';
const kgInfo = ref({
id: '',
logo: '',
name: '',
multi_name: [],
book_list: []
});
const { data } = await kgBookListAPI({ kg_id });
if (data) kgInfo.value = data;
kgInfo.value.book_list.forEach(item => {
item.show = true; // 默认显示所有,给搜索功能留的hook
});
// 有空格分割name
if (kgInfo.value.name.indexOf(' ') > -1) {
kgInfo.value.multi_name = kgInfo.value.name.split(' ');
}
if (!kgInfo.value.book_list.length) {
emptyStatus.value = true;
}
return {
kg_id,
kgInfo,
emptyStatus
}
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-18 14:31:26
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-05-30 10:18:19
* @FilePath: /tswj/src/composables/useDefaultPerf.js
* @Description:
*/
import { ref } from 'vue'
import axios from '@/utils/axios';
import { Toast } from 'vant';
/**
* @description: 获取默认儿童信息
* @param {*} bookId
* @param {*} params
* @param {*} avatar
* @param {*} name
* @param {*} price
* @param {*} user_id
* @param {*} perf_id
* @param {*} perf_name
* @param {*} can_upload
* @param {*} can_upload
* @param {*} can_upload
* @param {*} message
* @return {*}
*/
export const useDefaultPerf = (bookId) => {
// 金数据准备数据
const userInfo = ref({})
axios.get('/srv/?a=default_perf', {
params: {
book_id: bookId
}
})
.then(res => {
if (res.data.code === 1) {
userInfo.value = {
book_id: res.data.data.book_id,
avatar: res.data.data.book_cover,
name: res.data.data.book_name,
price: res.data.data.book_price,
user_id: res.data.data.user_id,
perf_id: res.data.data.perf_id,
perf_name: res.data.data.perf_name,
can_upload: res.data.data.can_upload, // can_upload :1=可上传,-1=用户没有实名,-2=用户没有儿童表演者
// can_upload: -1, // can_upload :1=可上传,-1=用户没有实名,-2=用户没有儿童表演者
}
} else {
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
});
return {
userInfo
}
}
/*
* @Date: 2022-06-22 00:07:42
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-30 13:45:54
* @FilePath: /tswj/src/composables/useLogin.js
* @Description: 文件描述
*/
import { bLoginAPI } from '@/api/B/login'
import { useRouter } from 'vue-router'
import { wxInfo } from '@/utils/tools';
import { ref } from 'vue'
import { useCountDown } from '@vant/use';
import { smsAPI } from '@/api/common'
import { Toast } from 'vant'
export const useLogin = () => {
const phone = ref('');
const code = ref('')
const refForm = ref(null);
const validateForm = () => {
const valid = refForm.value.validate();
valid
.then(() => {
refForm.value.submit();
})
.catch(error => {
console.error(error);
Toast({
message: '请检查后再次提交',
icon: 'cross',
});
})
}
/**
* 判断微信环境看是否弹出控件框
* 桌面微信直接输入
* 其他环境弹出输入框
*/
let use_widget = ref(true);
use_widget.value = !!(wxInfo().isiOS || wxInfo().isAndroid);
/**
* 手机号码校验
* 函数返回 true 表示校验通过,false 表示不通过
* @param {*} val
*/
const sms_disabled = ref(true);
const phoneValidator = (val) => {
let flag = false;
// 简单判断手机号位数
if (/1\d{10}/.test(val) && phone.value.length === 11) {
sms_disabled.value = false;
flag = true;
} else {
sms_disabled.value = true;
flag = false;
}
return flag
};
/**
* 手机号数字弹框
*/
const keyboard_show = ref(false);
const refPhone = ref(null)
const showKeyboard = () => { // 弹出数字弹框
keyboard_show.value = true;
};
const keyboardBlur = () => { // 数字键盘失焦回调
keyboard_show.value = false;
refPhone.value.validate();
};
// 设置发送短信倒计时
// TAG: vant 自带倒计时函数
const limitSeconds = ref(60000); // 配置倒计时秒数
const countDown = useCountDown({ // 配置倒计时
time: limitSeconds.value,
onFinish: () => {
countDown.reset();
}
});
const sendCode = async () => { // 发送验证码
countDown.start();
// 验证码接口
const { code } = await smsAPI({ phone: phone.value });
if (code) {
Toast.success('发送成功');
}
};
// 过滤输入的数字 只能四位
const smsFormatter = (value) => value.substring(0, 4);
/**
* 用户登录
* @param {*} phone
* @param {*} pin
*/
const $router = useRouter();
const onSubmit = async (values) => {
const { code } = await bLoginAPI({ phone: values.phone, pin: values.code })
if (code) {
$router.push({
path: '/business/index'
});
}
};
return {
phone,
code,
onSubmit,
use_widget,
sms_disabled,
phoneValidator,
keyboardBlur,
keyboard_show,
showKeyboard,
refPhone,
refForm,
validateForm,
smsFormatter,
limitSeconds,
countDown,
sendCode,
}
}
/*
* @Date: 2022-06-12 22:51:21
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 01:01:33
* @FilePath: /tswj/src/composables/useMessageList.ts
* @Description: 测试处理列表查询功能中的重复代码问题
* 感觉复用意义不大,这么写反而很麻烦
*/
import { Ref, ref } from 'vue'
import { myCommentAPI } from '@/api/C/me'
import _ from 'lodash'
import { commentListType } from '@/@types/message/interface';
import {
loading,
finished,
limit,
offset,
finishedTextStatus,
emptyStatus,
} from '@/composables/variable';
// scrollList的类型是个麻烦,其他地方调用时类型不一定一样
function fn(data: [], scrollList: Ref<commentListType[]>) {
// function fn(data: [], scrollList: any) {
// 数据全部加载完成
if (!data.length) {
// 加载状态结束
finished.value = true;
}
scrollList.value = [...scrollList.value, ...data];
offset.value = scrollList.value.length;
loading.value = false;
// 隐藏loading标识,空列表图标
if (!scrollList.value.length) {
finishedTextStatus.value = false;
emptyStatus.value = true;
} else {
emptyStatus.value = false;
}
return {
scrollList,
finished,
loading,
finishedTextStatus,
emptyStatus,
};
}
export const useMessageList = () => {
// 我的留言接口联调
const scrollList = ref<commentListType[]>([]);
let obj = {
scrollList,
finished,
loading,
finishedTextStatus,
emptyStatus,
};
const onLoad = async () => {
const { data } = await myCommentAPI({ limit: limit.value, offset: offset.value });
data.forEach((item: { target_name: string | null | undefined; c_action: string; c_name: string; }) => {
let arr = _.split(item.target_name, '@'); // 分割评论的动作和姓名
item.c_action = arr[0]; // 评论动作
item.c_name = arr[1]; // 评论姓名
});
// fn把重复代码抽离
obj = fn(data, scrollList);
}
return {
onLoad,
scrollList: obj.scrollList,
loading: obj.loading,
finished: obj.finished,
finishedTextStatus: obj.finishedTextStatus,
emptyStatus: obj.emptyStatus,
};
}
import { $, _, storeToRefs, mainStore } from '@/utils/generatePackage'
/**
* 页面滚动恢复
* @returns
*/
export const useScrollTop = () => {
const store = mainStore();
const resetScrollTop = (key) => {
// 嵌套滚动,执行两个,先滚外面再滚里面
_.times(2, () => {
$("html,body").animate({ "scrollTop": String(storeToRefs(store)[key].value) + 'px' });
});
}
return {
resetScrollTop,
store
}
}
/*
* @Date: 2022-06-13 17:42:32
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-18 21:14:42
* @FilePath: /tswj/src/composables/useShare.js
* @Description: 文件描述
*/
import wx from 'weixin-js-sdk';
// import { Toast } from 'vant';
/**
* @description: 微信分享功能
* @param {*} title 标题
* @param {*} desc 描述
* @param {*} imgUrl 图标
* @return {*}
*/
export const sharePage = ({title = '童声无界', desc = '共读一本书,传递一份爱。', imgUrl = 'http://voice.onwall.cn/f/voice/images/weixin_logo.jpg'}) => {
const shareData = {
title, // 分享标题
desc, // 分享描述
link: location.origin + location.pathname + location.hash, // 分享链接,该链接域名或路径必须与当前页面对应的公众号 JS 安全域名一致
imgUrl, // 分享图标
success: function () {
// console.warn('设置成功');
}
}
// 分享好友(微信好友或qq好友)
wx.updateAppMessageShareData(shareData);
// 分享到朋友圈或qq空间
wx.updateTimelineShareData(shareData);
// 分享到腾讯微博
wx.onMenuShareWeibo(shareData);
// // 获取“分享给朋友”按钮点击状态及自定义分享内容接口(即将废弃)
// wx.onMenuShareAppMessage(shareData);
// // 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口(即将废弃)
// wx.onMenuShareTimeline(shareData);
// // 获取“分享到QQ”按钮点击状态及自定义分享内容接口(即将废弃)
// wx.onMenuShareQQ(shareData);
}
import { useRoute } from 'vue-router';
import { ref } from 'vue';
import { Cookies } from '@/utils/generatePackage'
export const useShortcutBar = (item) => {
const $route = useRoute();
const path = $route.path;
const isClient = Cookies.get('userType') === 'client' ? true : false; // 判断C端入口位置,访客/客户
// const case1 = ['home', 'me', 'rank'];
// const case2 = ['home'];
// const case3 = ['me'];
const shortcutItem = ref([]);
// 配置快捷跳转条
if (item) {
shortcutItem.value = item;
} else {
if (path === '/client/chooseBook') { // 爱心捐书页面
if (isClient) {
shortcutItem.value = ['home', 'me', 'rank']
} else {
shortcutItem.value = ['me']
}
}
if (path === '/client/donateCertificate') {
shortcutItem.value = ['home']
}
if (path === '/business/index') {
shortcutItem.value = ['me']
}
}
return {
shortcutItem
}
}
import { ref } from 'vue'
import axios from '@/utils/axios';
import _ from 'lodash'
import { Toast } from 'vant';
export const useUnwatchList = () => {
// 绑定页面数据
const prod_list = ref([]);
const limit = ref(10)
const offset = ref(0)
// 处理书籍下作品列表
const loading = ref(false);
const finished = ref(false);
// 因为不能让空图标提前出来的写法
const finishedTextStatus = ref(false);
const emptyStatus = ref(false);
/**
* 向下滚动查询数据
*/
const onLoad = () => {
// 异步更新数据
axios.get('/srv/?a=my_unplay', {
params: {
limit: limit.value,
offset: offset.value
}
})
.then(res => {
if (res.data.code === 1) {
prod_list.value = _.concat(prod_list.value, res.data.data.prod);
prod_list.value = _.uniqBy(prod_list.value, 'id');
_.each(prod_list.value, (item) => {
item.type = 'read-only' // 特殊标识,判断入口 为keepAlive使用
})
offset.value = prod_list.value.length;
loading.value = false;
// 数据全部加载完成
if (!res.data.data.prod.length) {
// 加载状态结束
finished.value = true;
}
// 空数据提示
if (!prod_list.value.length) {
finishedTextStatus.value = false;
emptyStatus.value = true;
}
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
})
};
return {
onLoad,
prod_list,
finished,
loading,
finishedTextStatus,
emptyStatus,
}
}
/*
* @Date: 2022-05-10 12:15:14
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-29 23:36:29
* @FilePath: /tswj/src/composables/useUpload.js
* @Description: 图片上传模块
*/
import { v4 as uuidv4 } from 'uuid';
import { ref, reactive } from 'vue'
import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common'
export const useUpload = () => {
let lock_btn = ref(false); // 保存按钮锁
let fileList = ref([]);
let upload_image = reactive({ src: '' });
const afterRead = async (res) => {
lock_btn.value = true; // 上传开始, 不能保存
let affix = uuidv4();
// 此时可以自行将文件上传至服务器
let dataURL = res.content;
let base64url = dataURL.slice(dataURL.indexOf(',') + 1); // 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA.......
// 获取七牛token
const { token, key, code } = await qiniuTokenAPI({ filename: `${affix}_${res.file.name}`, file: base64url });
if (code) {
const config = {
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': 'UpToken ' + token, // UpToken后必须有一个 ' '(空格)
}
}
// 上传七牛服务器
const { filekey, hash, image_info } = await qiniuUploadAPI('http://upload.qiniup.com/putb64/-1/key/' + key, base64url, config)
if (filekey) {
// 保存图片
const { data } = await saveFileAPI({ filekey, hash, format: image_info.format, height: image_info.height, width: image_info.width });
upload_image.src = data.src;
lock_btn.value = false; // 头像上传完成, 打开锁
}
}
};
const beforeDelete = () => { // 删除图片回调
upload_image.src = '';
return true;
}
return {
lock_btn,
fileList,
upload_image,
afterRead,
beforeDelete
}
}
import { ref } from 'vue'
import axios from '@/utils/axios';
import { Toast } from 'vant';
export const idCard = () => {
/**
* 检查用户是否已实名认证 (实名认证后可以上传作品,留言)
*/
const can_use = ref(false)
axios.get('/srv/?a=can_upload')
.then(res => {
if (res.data.code === 1) {
can_use.value = res.data.data.can_upload ? true : false;
} else {
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
})
return {
can_use
}
}
/*
* @Date: 2022-05-05 18:07:16
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-10-01 21:13:07
* @FilePath: /tswj/src/composables/useVideoList.js
* @Description: 文件描述
*/
import { ref } from 'vue'
import axios from '@/utils/axios';
import _ from 'lodash'
import { Toast } from 'vant';
import { useRoute } from 'vue-router'
import { bookInfoAPI } from '@/api/C/book'
import { flowFn } from '@/hooks/useFlowFn'
export const useVideoList = () => {
const $route = useRoute();
// 切换视频语言
const checkMandarin = ref(true); // 普通话选项卡
const checkLocalism = ref(false); // 方言选项卡
const chooseLanguage = ref({ text: '普通话', val: '普通话' }); // 默认选中普通话
/**
* 切换视频语言回调
* @param {*} type
*/
const toggleLanguage = (type) => {
if (type === 'mandarin') {
checkMandarin.value = true;
checkLocalism.value = false;
} else {
checkMandarin.value = false;
checkLocalism.value = true;
}
// 修改默认语言绑定数据
if (checkLocalism.value) {
// tslint:disable-next-line:no-string-literal
chooseLanguage.value = { text: columns.value[0]['text'], val: columns.value[0]['val'] }
} else {
chooseLanguage.value = { text: '普通话', val: '普通话' };
}
// 切换语言需要更新列表数据
onReload()
}
// 方言选择项
let columns = ref([
{ text: '所有方言', val: '所有方言' },
])
//
axios.get('/srv/?a=localism_list&book_id=' + $route.query.id)
.then(res => {
if (res.data.code === 1) {
let arr = [];
_.each(res.data.data, item => {
arr.push({
text: item,
val: item
})
});
columns.value = _.concat(columns.value, arr);
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
})
const showPicker = ref(false);
/**
* 选择方言确认后回调
* @param {*} param
*/
const onConfirm = ({ selectedOptions }) => {
showPicker.value = false;
chooseLanguage.value = {
text: selectedOptions[0].text,
val: selectedOptions[0].val
}
onReload()
};
// 绑定页面数据
const bookInfo = ref('');
// tslint:disable-next-line: variable-name
const prod_list = ref([]);
const limit = ref(10)
const offset = ref(0)
// 处理书籍下作品列表
const loading = ref(false);
const finished = ref(false);
// 因为不能让空图标提前出来的写法
const finishedTextStatus = ref(false);
const emptyStatus = ref(false);
/**
* 向下滚动查询数据
*/
const onLoad = async () => {
// 异步更新数据
const { data, code } = await bookInfoAPI({ book_id: $route.query.id, kg_id: $route.query.kg_id ? $route.query.kg_id : 0, localism_type: chooseLanguage.value.text, limit: limit.value, offset: offset.value })
if (code === 1) {
bookInfo.value = data;
flowFn(data.prod_list, prod_list, offset, loading, finished, finishedTextStatus, emptyStatus);
}
};
/**
* 重载刷新程序
*/
const onReload = () => {
offset.value = 0
prod_list.value = []
loading.value = true;
finished.value = false;
onLoad()
}
return {
toggleLanguage,
onLoad,
columns,
prod_list,
finished,
loading,
bookInfo,
showPicker,
checkLocalism,
checkMandarin,
onConfirm,
chooseLanguage,
finishedTextStatus,
emptyStatus,
}
}
/*
* @Date: 2022-06-12 23:54:24
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 00:50:29
* @FilePath: /tswj/src/composables/variable.js
* @Description: 文件描述
*/
import { ref } from 'vue';
export const loading = ref(false);
export const finished = ref(false);
export const limit = ref(5);
export const offset = ref(0)
export const finishedTextStatus = ref(false);
export const emptyStatus = ref(false);
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-25 18:34:17
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-30 16:55:15
* @FilePath: /tswj/src/constant.js
* @Description:
*/
// 金数据表单 - 家长端(废弃)
export const JSJ_FORM_C = 'https://jsjs.onwall.cn/f/NAGn1D';
// 金数据表单 - 家长端(普通话/方言)
export const JSJ_FORM_MANDARIN = 'https://jsjs.onwall.cn/f/NAGn1D';
export const JSJ_FORM_LOCALISM = 'https://jsjs.onwall.cn/f/HFdZIx';
// 金数据表单 - 老师端
export const JSJ_FORM_B = 'https://jsj.onwall.cn/f/g7D0MT';
// 颜色变量
export const styleColor = {
baseColor: '#11D2B1',
baseFontColor: '#FFFFFF'
}
/**
* 客户端类型
* @param CLIENT 家长端
* @param BUSINESS 老师端
*/
export const USER_ROLE = {
CLIENT: 'C',
BUSINESS: 'B',
}
/**
* 用户身份
* @param CHILDREN 儿童
* @param VISIT 访客
* @param KINDERGARTEN 幼儿园
*/
export const USER_TYPE = {
CHILDREN: 'C',
VISIT: 'V',
KINDERGARTEN: 'K',
}
// 默认视频封面
export const DEFAULT_COVER = 'http://gyzs.onwall.cn/tswj_vidieo_cover.jpg'
/**
* 用户操作状态
* @param PASS 正常
* @param NON_VERIFIED 未实名认证
* @param NON_DEFAULT_CHILD 没有默认儿童
*/
export const USER_STATUS = {
PASS: 1,
NON_VERIFIED: -1,
NON_DEFAULT_CHILD: -2
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-14 23:28:39
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-07 22:49:56
* @FilePath: /tswj/src/env.d.ts
* @Description:
*/
interface ImportMetaEnv extends Readonly<Record<string, string>> {
readonly VITE_OPENID: string;
readonly VITE_ID: string;
readonly VITE_PIN: string;
readonly VITE_APPID: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
/**
* 依赖注入命名集合
*/
export const myInjectionKey = Symbol()
export const fooInjectionKey = Symbol()
import { provide, inject } from "vue";
// const key = Symbol();
/**
* 创建全局变量
* @param {*} context
* @param {*} key
*/
export function createContext(context, key) {
provide(key, context)
}
/**
* 使用全局变量
* @param {*} key
* @returns
*/
export function useContext(key) {
return inject(key)
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-28 22:31:25
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-05-30 10:18:09
* @FilePath: /tswj/src/hooks/useDebounce.js
* @Description:
*/
import _ from 'lodash';
/**
* 封装lodash防抖
* @param {*} fn 执行函数
* @param {*} timestamp 执行间隔
* @param {*} options 函数配置 - 在延迟开始前调用,在延迟结束后不调用
* @returns 返回新的 debounced(防抖动)函数。
*/
export const useDebounce = (fn, timestamp = 500, options = { leading: true, trailing: false }) => {
return _.debounce(fn, timestamp, options);
}
/**
* @description 封装简化滚动查询列表执行流程
* @param {*} data 接口返回列表数据
* @param {*} list 自定义列表
* @param {*} offset
* @param {*} loading
* @param {*} finished
* @param {*} finishedTextStatus
* @param {*} emptyStatus
*/
import _ from 'lodash'
export const flowFn = (data, list, offset, loading, finished, finishedTextStatus, emptyStatus) => {
list.value = _.concat(list.value, data);
list.value = _.uniqBy(list.value, 'id');
offset.value = list.value.length;
loading.value = false;
// 数据全部加载完成
if (!data.length) {
// 加载状态结束
finished.value = true;
}
// 空数据提示
if (!list.value.length) {
finishedTextStatus.value = false;
}
emptyStatus.value = Object.is(list.value.length, 0);
}
import { useRouter } from 'vue-router';
/**
* 封装路由跳转方便行内调用
* @returns
*/
export function useGo () {
let router = useRouter()
function go (path, query) {
router.push({
path: path,
query: query
})
}
return go
}
export function useReplace () {
let router = useRouter()
function replace (path, query) {
router.replace({
path: path,
query: query
})
}
return replace
}
import { mainStore } from '@/utils/generatePackage.js'
// 删除 keep-alive 缓存
export const store = mainStore();
export const killPages = () => {
store.changeKeepPages();
}
export const addPages = () => {
store.keepThisPage();
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-31 12:06:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-12-31 17:32:10
* @FilePath: /tswj/src/main.js
* @Description:
*/
import { createApp } from 'vue';
import { Button, Image as VanImage, Col, Row, Icon, Form, Field, CellGroup, ConfigProvider, Toast, Uploader, Empty, Tab, Tabs, Overlay, NumberKeyboard, Lazyload, List, PullRefresh, Popup, Picker, Sticky, Stepper, Tag, Swipe, SwipeItem, Dialog, ActionSheet, Loading, Checkbox, Search, Notify } from 'vant';
import router from './router';
import App from './App.vue';
// import axios from './utils/axios';
import axios from '@/utils/axios';
// import 'default-passive-events'; // 解决Chrome控制台non-passive event listener输出问题
import { createPinia } from 'pinia';
import 'vant/lib/index.css';
const pinia = createPinia();
const app = createApp(App);
app.config.globalProperties.$http = axios; // 关键语句
app.use(pinia).use(router).use(Button).use(VanImage).use(Col).use(Row).use(Icon).use(Form).use(Field).use(CellGroup).use(Toast).use(Uploader).use(Empty).use(Tab).use(Tabs).use(Overlay).use(NumberKeyboard).use(Lazyload).use(List).use(PullRefresh).use(Popup).use(Picker).use(Sticky).use(Stepper).use(Tag).use(Swipe).use(SwipeItem).use(Dialog).use(ActionSheet).use(Loading).use(Checkbox).use(Search).use(ConfigProvider).use(Notify);
app.mount('#app');
const routes = [{
path: '/image',
redirect: '',
name: 'html转图片',
component: 'html2canvas',
keepAlive: '',
meta: {
title: 'html转图片',
name: ''
},
children: [{
path: 'children',
redirect: '',
name: 'html转图片',
component: 'children-test',
keepAlive: '',
meta: {
title: 'html转图片',
name: ''
}
}]
}]
// const routes = []
export default routes
const data = [
{
"case_id": "424589807164071936",
"code": "N06",
"title": "复旦管理学奖励基金会",
"detail": "我国自古就有优秀的管理思想和实践,但中国现代管理科学则是在改革开放之后才逐步发展起来的。为进一步推动我国现代管理科学发展,原中共中央政治局常委、国务院副总理李岚清同志于2005年发起成立了复旦管理学奖励基金会,这也是中国人自己设立的管理学界第一个奖励基金会。\r\n“要真正解决好中国的管理问题,最终还是要依靠中国人自己。”这句话道出了“管理”必须根植于一个国家的社会组织和民族文化。管理科学,是兴国之道,也是一个国家软实力的重要组成部分。\r\n十六年来,基金会各项管理逐步完善,2020年首次参加社会组织等级评估即被授予“5A级社会组织”荣誉称号;FTI透明指数排名连获最优等级。基金会的评奖工作,及其开展的一系列公益项目,获得了来自各界人士的一致认可;同时借助媒体之力,不断拓宽公众对中国管理学的认识边界,受益人数不断增加。如今,基金会已逐渐发展成为中国管理学界最具影响力、最具公信力的基金会。\r\n作为一个“奖励性”的基金会,我们希望打造中国管理学界的“诺贝尔奖”。基金会目前设立了“复旦管理学杰出贡献奖”“复旦管理学终身成就奖”“复旦企业管理杰出贡献奖”三大奖项,已成为我国管理学界享有崇高声誉、具有广泛影响力的重要奖项。截至2020年,已评选出57位获奖人,他们中不乏成思危、苏东水等矢志推动中国特色的管理学及其研究走向世界的杰出专家学者,亦有张瑞敏、任正非等对中国管理学不断实践、探索的优秀民族企业家。\r\n评奖之外,基金会还积极开展了丰富多样的公益活动。自2013年起,面向我国高等学府,面向青年师生,面向中西部地区举办了“校园公益”系列讲座活动,辐射师生5000余人。\r\n联合我国管理学一级学会,举办了一系列具有国际影响力的管理学学术盛会。其中,“中国管理学年会”是中国管理学领域规模最大、层次最高的综合性学术会议。另外,基金会通过支持“中国管理学青年论坛”,为有潜力的优秀青年架起了跨学科、跨层次的学习交流平台,旨在培养中国管理学的中青年力量。\r\n为加强学术界和实业界的合作,基金会充分发挥“桥梁·引领·赋能”作用,做到将“管理学带出去”,“管理领进来”,邀请获奖人、专家学者与企业家共话“管理”。\r\n基金会还与复旦大学东方管理研究院、第一财经合作开展了“中国杰出企业家管理思想访谈录”项目,已通过42集电视专题片、6部《改变世界》、14本研究丛书等形式对外发布,另有10多个优秀案例走进了高校课堂,收益人数达10亿多人。\r\n基金会积极响应习近平总书记“把论文写在祖国大地上”的号召,与《管理学报》合作,举办专题学术研讨会,开辟“中国企业家管理思想”专栏;与知名企业合作开展“海尔生态雨林计划”等专项研究。\r\n2020年新冠疫情的突发,对全国各地的公共卫生治理都是前所未有的考验。为总结出应对疫情的科学、高效的经验,提供疫情应对经验给相关部门,基金会资助了“新冠疫情防控防治的中国特色管理理论与方法”系列专著及案例研究。于基金会而言,这件事意义非常。\r\n作为一个扎根于中国管理学领域发展的公益组织,基金会在各级领导的亲切关怀下不断发展。获奖人所提出管理思想、管理理论和实践的创新、各项公益活动等,对于上海乃至全国各地的社会治理、公共管理与企业管理都发挥了重要的作用。在每年的颁奖典礼上,历任上海市领导均受邀出席并致辞。当今世界正面临百年未有的大变局,发展中国特色的管理学、并让中国特色管理学发挥更大的影响力,这比任何时候都更加迫切。在未来的公益发展事业中,基金会将继续助力中国特色管理学的探索和创新,为增强上海自主创新能力,提高城市国际竞争力,做出新的重大的贡献!",
"cover": {
"name": "N06.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N06.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N06.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N06.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3406,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "复旦管理学奖励基金会"
},
"voted": false,
"liked": false
},
{
"case_id": "419178326515888128",
"code": "N14",
"title": "上海市普陀区长寿社会组织联合会",
"detail": "近年来,各类社区社会组织数量增长,规模扩大,社会组织日趋成为服务社区发展,提升社区治理水平的重要力量。所以以服务中心传统的点对点形式来去服务社会组织,已经不符合形势的发展,亟待搭建新的平台。在这种情势下,2016年长寿社会组织联合会孕育而生。长寿社会组织联合会是全市首家街道层面社会组织联合会。联合会以党建为引领,创新构建社区、社会组织、社会组织联合会的联动机制,这种全新模式不仅为社区与社会组织之间搭建了交流对接平台,也为促进社会组织自律自治、资源共享、健康发展创造了良好的条件。\n联合会运行以来,正式会员近百家。目前,长寿社会组织联合会成员中已有区党代表、区人大代表、区政协委员,充分激发社会组织领军人物的参与度,发挥社会组织自我管理、自我服务的能效。\n创新党建引领社会组织参与社区治理是我们的工作特色之一。2016年我们同步成立联合会党总支,党总支通过“价值引领、服务凝聚、同心共治”凝聚党员力量,提升基层组织活力。目前,党总支下设20个党组织、6个联合支部,14个独立支部。联合会自成立以来开展了一系列凝聚力建设活动,包括开展情景党课、建立学习教育体验站等等,我们还努力将公益理念引入党建活动,例如开展垃圾分类主题党日活动。通过这些活动和服务,不仅会员们的凝聚力日益增强,更是聚拢到了一批原先游离在边缘的社会组织。\n搭建公益服务平台也是我们最大的工作特色。我们通过公益秀、公益项目菜单、公益集市等形式将社会服务和项目精准化地投放到我们两新组织、楼宇和居民区,政府购买社会组织服务项目的数量及社区参与面都有了一个较大幅度的提升。\n在新媒体时代,为了更加方便项目对接,社联会依托微信公众号平台,于18年9月正式上线了长寿公e家网站。公e家的推出填补了20万以下政府采购服务对接渠道的空白。居民区科室可以进行社区需求发布,社会组织发布服务内容,这样以来加快了信息传递速率,实现了项目精准对接。例如,我们会在学生的暑假开展暑期班公益项目,让公益项目走进社区、走进百姓生活中。项目结项后,我们会举办成果展,把项目的成果进行公示,并在公E家上给承接方打分,能够让购买方一目了然地了解社会组织的服务能力。通过这样一个平台,我们让长寿的社会组织能真正了解到社区的需求,因地制宜地研发适合长寿、服务长寿的公益项目。尤其在疫情的冲击下,公E家的优势更加得到了肯定。2016年以来我们通过线上线下的渠道共举办了115个公益项目、300余场活动,有效实现社会组织与居民需求的“无缝对接”。\n我们在实践中摸索,完善中创新。展望未来,长寿社会组织联合会也将不断探索,下一步的计划是“请进来、走出去”,长寿社会组织联合会将联合其他街镇乃至其他区县的社会组织共同协作,打破社会组织属地化壁垒,提升他们视野和竞争力,因地制宜的研发出服务社区的公益项目,让公益的力量势如破竹,为打造精彩长寿、善美普陀和公益上海添砖加瓦。",
"cover": {
"name": "N14.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N14.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N14.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N14.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "APPLY",
"public_vote": 3346,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市普陀区长寿社会组织联合会"
},
"voted": false
},
{
"case_id": "419527762110595072",
"code": "N04",
"title": "上海震旦教育发展基金会",
"detail": "上海震旦教育发展基金会成立于2015年,秉持弘扬公益精神,积极回报社会的办会宗旨,努力汇集各方力量、传递正能量。\r\n基金会主要以四项特色工作为主:\r\n(一)携手各方力量,关爱特殊人群\r\n震旦教育基金会已成功主办、协办多项全国性、市级助残公益活动。关爱自闭症特殊群体活动,主题鲜明、内容丰富、参与者众、受益面广。\r\n(二)共襄慈善良业,回报社区民众\r\n震旦教育基金会为社区建设作贡献。为黄浦社区加装电梯工程中做配套绿化改建项目,为居民提供了优美的绿化环境。\r\n基金会每年中国传统节日前向街道、镇、村老人、残疾人送去温暖与爱心。\r\n2020年疫情期间,震旦教育基金会为黄浦区各大医院、派出所等总共58家单位,送去价值28万余元的哈根达斯蛋糕,向日夜坚守在疫情防控第一线的工作人员送去慰问与祝福,为抗击疫情助力加油!\r\n(三)引领环保时尚,共倡整洁家园\r\n震旦教育基金会联合公益机构举办了多场大型环保艺术展,在浦东科技馆的“艺起减塑”历时90天,共接待观众逾13万人次,使参与者对环保、减塑、有了感性的认识,也认识到环保是我们全人类的职责与使命。\r\n(四)共同奉献爱心,基金奖励优秀\r\n震旦师生积极为抗疫捐款,把参与慈善公益事业作为每个人的社会责任与使命。在疫情之中,基金会表彰震旦职业学院17名驰援武汉的毕业生,给予每人2万元的奖励,鼓励和表彰他们无私无畏,挺身而出把人民生命安全放在首位的大无畏精神。\r\n震旦教育基金会近年来开展了50多项公益项目活动,受益人数16万余人次。震旦教育基金会将不忘初心,凝心聚力,坚毅前行,吸纳更多热心于慈善事业的有识之士参与,做更多造福于社会的公益活动。",
"cover": {
"name": "N04.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N04.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N04.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N04.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "REFUSE",
"public_vote": 4125,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海震旦教育发展基金会"
},
"voted": false
},
{
"case_id": "420369007372419072",
"code": "N18",
"title": "上海青创社会服务中心",
"detail": "上海青创社会服务中心,AAAA级社会组织,是一家从事社会创新治理、公共空间营造与运维、公益活动策划以及媒体宣传于一体的枢纽型社会组织。机构在党建引领下茁壮成长,在上海城市更新、社会治理工作中发挥着积极重要的作用。\n党建引领社会组织发展\n上海青创坚持“党建引领促发展”的理念,目前团队规模超过70人,服务在上海创新治理的前沿,年服务人次超过30万。机构党支部拥有中共党员15名,这些党员既是业务骨干,也是治理先锋。在建党百年之际,上海青创成立了普陀区首家建在社会组织上的党群服务站。党建引领树立了青创人正确的价值观,为社会组织的发展保驾护航。机构理事长也先后荣获上海市五四青年奖章个人、上海市青年社区治理达人、普陀区优秀共产党员等荣誉。\n党建引领公益志愿服务\n通过“党建”带动“公益”的模式,青创公益在党支部的带领下,组建了多个青年志愿团队,参与到各项公益志愿服务当中。定期举办五福生日会为老系列服务;作为区文明单位,在创城行动中参与美化楼宇环境;积极响应“人民城市人民建,人民城市为人民”的理念,成立了苏州河护河队,助力苏州河环境治理工作;疫情期间组织员工在一线抗疫、慰问、捐款捐物,今年以来机构组织了一批又一批的员工和志愿者,参与疫苗接种的宣传和动员工作中;在党建引领之下,每年都有青年员工志愿加入民兵队伍,成为祖国国防力量的后备军。\n党建引领社会创新治理\n通过项目孵化团队,通过社区挖掘骨干,上海青创每年为超过100个社区提供赋能,培育社区项目负责人,强化自治共治,更好地推动社区治理体系和能力的现代化。通过空间培育志愿队伍,在机构参与运营的多个公共空间上面,不仅对驻点服务人员进行赋能提升,还把居民也动员起来,成为空间的小主人,进一步服务百姓,提升空间活力。机构理事长作为一名区政协委员,每年都会对上海社会治理工作积极地建言资政,为社会组织的发展而发声。\n坚持党建引领,才能促进社会组织健康有序的发展。在庆祝中国共产党成立100周年大会上,习近平总书记强调“新时代的中国青年,要以实现中华民族伟大复兴为己任,增强做中国人的志气、骨气、底气”。上海青创社会服务中心通过公益之申这个平台,以青年社会组织的身份表态:将不忘公益初心,在党建引领下,为上海创新社会治理工作添一份力。",
"cover": {
"name": "N18.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N18.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N18.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N18.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 5079,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海青创社会服务中心"
},
"voted": false
},
{
"case_id": "420305782152998912",
"code": "N02",
"title": "上海静安区心灵导航心理咨询服务中心",
"detail": "上海静安区心灵导航心理咨询服务中心成立于2011年8月,作为一家开展专业心理服务的非营利性社会组织,始终以“热衷公益、不求回报,把爱心奉献社会,把专业与关怀传递给更多、更广的社会大众”作为服务宗旨,共同的公益理念聚集了200余名心理咨询师志愿者,在心灵导航党支部的带领下,关注社区心理健康,提供专业心理服务。\n二、专业服务关注社区心理健康\n走进社区、学校,楼宇,通过心理咨询、上门走访、心理辅导活动等形式在社区普及心理学知识,增强人们心理健康意识。设计并实施了“星星港”失独家庭心理疏导、“贫困青少年心理健康项目”、“安徽贫困青少年心理暑期夏令营”、“信访人员心理疏导”、“特殊人员心理疏导”等心理服务工作。服务人群涵盖了老人、青少年、白领、困境等群体,累计开展项目82个,服务58000人次。\n三、热心公益回馈社会\n疫情伊始,心灵导航第一时间以党支部为核心,党员心理咨询师为骨干力量,组建“心理服务志愿团队”,创建热线和微信通道,向社会免费开通,录制《新冠疫情心理微课程》,通过各种渠道宣传播放,为市民和一线防疫工作者提供及时必要的心理援助。热线服务除涵盖上海地区之外,还处理了来自武汉金银潭医院医护人员的热线求助,同时为新疆喀什地区和驻疆武警部队提供远程心理指导。热线累计服务156人次,目前热线已作为一项常态化工作。\n四、文化援疆心理援疆\n心灵导航积极参与“心理援疆”,大力支援边疆的心理健康体系建设,自2018年起已连续三年为新疆巴楚县和驻疆武警部队开展心理健康建设服务,成立了“心灵导航巴楚工作站”以及“驻疆部队心理援建服务中心”,运用远程线上授课、专家团队赴疆现场教学、组织心理骨干赴沪深造等形式,为新疆巴楚教育系统、公安系统、社区一线工作人员、驻疆武警部队培养了大量的心理服务骨干,并通过线上形式为当地有心理困扰的家庭和武警战士提供心理咨询服务,防止了严重事故的发生,受助者来电、来信表示感谢,武警三支队连续三年零事故。心理援疆服务取得良好成效,累计服务9000人次,得到驻疆武警部队和巴楚县委的高度评价和肯定。\n五、媒体报道报道\n1、中央电视台曾对心灵导航为失独家庭开展的心理服务进行过专题报道。\n2、学习强国平台和静安报对心灵导航疫情期间的工作进行了宣传报道。\n3、人民网、上海电视台对心理援疆进行了连续报导。\n六、获得荣誉\n于2020年被评为上海市文明单位,复评为4A级社会组织。",
"cover": {
"name": "N02.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N02.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N02.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N02.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 4446,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海静安区心灵导航心理咨询服务中心"
},
"voted": false
},
{
"case_id": "419897909908398080",
"code": "N13",
"title": "上海市奉贤区民营经济协会",
"detail": "我们奉贤区民营经济协会的前身是奉贤县(区)个体劳动者协会和私营企业协会,成立于上世纪八十年代末。今年1月,为顺应形势发展需要,区民营经济协会的业务主管单位由奉贤区市场监督管理局变更为奉贤区工商联(总商会),开创了全市先河。多年来,协会认真贯彻落实习近平总书记关于加强社会组织建设的一系列重要指示精神,紧紧围绕推进“两个健康”(民营经济健康发展和民营经济人士健康成长),强化“三个服务”(服务会员、服务经济、服务社会)坚持“建设四会”(政治建会、团结立会、服务兴会、改革强会)这一工作理念和职责任务,扎实开展各项工作,促进社会组织高质量发展。目前,协会会员达到6000多名,其中理事会员150余人。协会先后二次获得全国个私协会系统先进单位和5A级社团组织、上海市个私协会系统三八红旗集体、奉贤区十佳公益机构、“热心慈善无私奉献”先进单位等称号;还收获服务单位赠送的三十多面锦旗和几十封感谢信。\n在引领广大会员参与公益事业方面我们的主要做法是:\n---充分发挥党员先锋模范引领作用。积极组织党员、会员开展访贫问暖活动;组织并推动会员开展公益服务项目,积极参加青海、务川、精准扶贫、关心下一代等项目对接捐助等公益活动,共有500余人次弱势群体受益。立足会员需求,我会成立了志愿者协调小组、法律顾问小组,发挥老同志、法律工作者协调优势,帮助协调解决近百家会员企业在生产经营投资中面临的困难问题,维护其合法权益,有效发挥我会的“稳定器”作用。\n---充分发挥民营经济人士主体作用。我们于2015年7月在会员中积极组建“爱心”、“小皮匠”、“善之乐”、“医疗志愿”等四支百人志愿服务队,采用分散服务和相对集中服务模式,积极组织开展3.5学雷锋、4•15爱心活动、志愿者嘉年华、公益伙伴日和“三下乡大篷车”等活动,“益”起行动,传递爱的正能量。“4•15”爱心行动日活动是全市个私协会系统影响深远的一项“品牌”活动,已经持续开展了20多年。“小皮匠”志愿服务队从2010年成立时的几个人发展到目前的40多人,志愿服务群众达40万余人次,近五年累计志愿服务时长15120个小时,人均服务时长400小时。服务项目有理发、磨剪刀、修鞋、修表、配钥匙、义诊和各种咨询服务,深得社会各界的好评。\n---引导民营企业积极履行社会责任。去年年初,面对突如其来的新冠疫情,协会第一时间向会员企业发出《倡议书》,动员各会员企业积极响应党和政府号召,自觉履行社会责任,以捐款捐物的方式共同参与抗击疫情,据不完全统计,共有68家会员企业捐款捐物总计863万元;组织企业家参与“携手慈善,与爱同行”、“弘扬公益贤风共建美丽贤城”奉贤区9.5中华慈善日系列活动,捐赠善款达上千万元。\n积极引导和组织民营经济人士参与公益事业、履行社会责任是我们社会组织的重要职责。“新时代呼唤新作为,新征程谱写新篇章”。我们将坚定理想信念、永葆初心使命,以更强大的内生动力和昂扬的精神状态,在营造共建共治共享的社会治理格局中发挥更大的作用,为“温暖这座城”做出新的更大的贡献!",
"cover": {
"name": "N13.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N13.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N13.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N13.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 343,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市奉贤区民营经济协会"
},
"voted": false
},
{
"case_id": "429021582644748288",
"code": "N03",
"title": "上海大慈公益基金会",
"detail": "上海大慈公益基金会是由上海龙华古寺发起,于2015年1月18日成立的佛教界第一家非公募基金会。基金会以“大慈念一切,慧光照十方”为基本理念;以慈善回报社会,以慈爱构建和谐社会为使命。六年来共募集善款9220.9万元,使用善款5132.1万元,受益群体277118人。受助的对象有老人和儿童、本地困境家庭、国家级贫困地区、革命老区、少数民族地区,以及上海对口援助地区。\r\n基金会在文化传承等方面也有新的亮点,16个慈善项目不断升级,逐步形成大慈品牌,被中国社会组织评为4A级社会组织、并获上海市科普公益贡献奖、中国红十字会奉献奖、2020年度公益之申“十佳公益项目”等。理事长照诚法师多次获得“上海慈善之星”的称号。\r\n一、“明旸法师助学帮困基金”,通过连续十年总计1000万元的捐赠用于帮助上海在校的孤儿、身患重大疾病等困难家庭学生完成学业。五年来投入资金500万元、受助学生2700人。经第三方评估满意度为100%。\r\n此项目同时也带动了其他爱心企业的积极参与,光明乳业在我们资助的困境学生中每人每年再增加1000元的牛奶卡直到项目结束为止。2019年有一家爱心组织捐赠100万元来认领此项目,我们很高兴的看到基金会爱的种子在持续的发芽。\r\n二、“生命护航——儿童意外伤害”项目,秉承“救孩子,救家庭”的理念,切实有效的帮助遭受意外伤害的患儿家庭,应对突如其来的变故。截止到2020年共救助患儿195人,使用资金278.7万元。2018年我们将项目前移,把宣传教育与救治相结合。举办“儿童无伤害日”,切实守护儿童健康的梦想。\r\n三、2017年大慈基金会与上海市慈善基金会合作举办了“蓝天下的至爱--点亮心愿”慈善义拍。三年来共拍得善款2246.5万元,用于“先心病”手术等医疗项目。\r\n四、为了让革命老区上海对口支援地区的青少年享受到优质科学资源参与科普体验,建立“大慈流动科技馆”项目,四年来共投入资金178万元,共有13000多名孩子受益。\r\n五、利用大数据的优势,推动远程支教项目。对云南泸西县小学推送,让孩子们“走进”上海课堂感受优质教育。\r\n六、“大慈儿童普惠”项目,改善身处困境的儿童生活,该项目执行以来共有5424名孩子受助。\r\n七、2017年开始分别为河南固始等革命老区、云南对口支援地区培训优秀中青教师、校长共183名。\r\n八、“老教授健康关爱”专项基金项目,五年来共资助资金100万元。\r\n九、2018年、2019年在月饼的推广会上共募得资金245万元,全部用于本市残疾儿童等学校。\r\n十、新冠肺炎抗疫期间,捐赠物资1788.04万元,捐赠现金543万元。理事长照诚法师手书“福”字共计1892幅,同时又为1649名上海援鄂医务人员特别发行个性化邮票并定制了“抗疫英雄卡”。\r\n十一、基金会每季度都会开展“一路有你”微慈善项目。\r\n多年来,基金会在项目的运行中突出了三性,广泛性、多样性、特色性,并向专业、规范、制度化迈进。\r\n基金会将继续要以“为政府分忧,为百姓解难”为根本,做好政府想做百姓所需的项目,在人道救助领域倾力奉献。",
"cover": {
"name": "N03.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N03.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N03.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N03.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3981,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海大慈公益基金会"
},
"voted": false
},
{
"case_id": "424325105943162880",
"code": "N15",
"title": "上海喜雅爱心社区服务中心",
"detail": "喜雅爱心成立于12年,是5A级社会组织,曾获上海市先进社会组织等殊荣。中心共有48名员工,100多名志愿者,有独立的党支部,7名党员。在党建引领下我们积极开展各类公益活动,为服务社区居民贡献自己的力量。\n\n在我们的身边,有这样一群特殊的邻居——“阳光宝宝”,因为智力发育不完善,永远成为了我们关注的阳光宝宝,她们需要被照顾。当我第一次走进长宁区新泾镇“阳光之家”的时候,被这25名在校全日制“阳光宝宝”深深感动,他们乖巧可爱,懂礼貌知感恩,渴望朋友,渴望走出家庭,走出教室,走向社会。他们的年龄在26-47岁之间,他们的父母50-80岁,有的父母早已无力照顾自己的孩子。提升“阳光宝宝”独立生活的能力,让他们学着融入社会,这一生存问题刻不容缓。\n\n在上海市慈善基金会第二届“蓝天至爱计划”的资助下,“阳光宝宝成长计划”应运而生!我们得到了新泾镇人民政府的大力支持。作为项目总设计师,我发挥亲子艺术教育的专业特长,组织团队为“阳光宝宝”量身定制创作课程,结合非遗艺术传承,用宝宝们自己的作品开发“阳光宝宝”文创产品。通过就业指导,培养他们成为新泾镇慈善超市的收银员、公益集市的导购员。正如大家一开篇看到的宣传片,阳光宝宝们正在自信自强地成长!\n\n“垃圾分一分·环境美十分”喜雅爱心积极参与社区治理,助力长宁做好垃圾分类特长生。2018年我们领先全市提出了“垃圾分类达人秀”活动,推荐长宁区垃圾分类形象大使,进单位进学校进社区进商圈,喜雅爱心开展垃圾分类宣讲活动逾2000场。我们开创垃圾分类美学,设计垃圾分类视觉体系,创作垃圾分类普法宣传片,亲身演绎“环保时装秀”,创建长宁区特色工作“八大首创”,设计互动游戏“魔方转转转”,至今为止我们在课堂上累计创作了8000只创意分类垃圾桶。让垃圾分类变得简单有趣,让环保活跃在长宁的大街小巷。我们的足迹从长宁走向上海,为建设美丽上海添上有力的一笔!\n\n更多的,喜雅爱心积极拓展对外服务项目,其中政府购买服务项目涉及长宁区民政局、区绿化市容局、区妇联等8个区政府单位,服务范围覆盖全长宁。为老助餐、上门维修等服务内容20余种,爱心暑托班、春雨润心田等服务项目共计百余个。服务对象从老至幼覆盖全年龄段,从普通家庭到弱势群体,服务十万余人次。把与社区居民有关的事,都当做自己的“头等大事”。",
"cover": {
"name": "N15.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N15.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N15.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N15.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3563,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海喜雅爱心社区服务中心"
},
"voted": false
},
{
"case_id": "419533650678550528",
"code": "N16",
"title": "上海市宁波商会",
"detail": "上海市宁波商会不是公益基金会,而是代表了商会组织,代表了民营企业的力量。下面从三个方面来阐述:\n第一、党建引领,锻造甬商红色品牌。中共上海市宁波商会委员会成立于2019年,是上海首家异地地市级商会党委,杨浦区首家“两新”组织党委,以“商会会员企业、楼宇企业、党建联席单位”为工作载体,党建联席单位31家,指导联系会员企业近1000家,覆盖4000余名党员,先后开展两新组织党建论坛、践行红色之旅、红五月滨江跑、优秀党建案例分享等具有甬商特色的品牌活动47场,形成了以党建促会建,以党建促会员企业发展的党建工作模式,是新形势下社团组织基层党建工作的创新与实践。\n第二、甬抗疫情,彰显责任与担当。面对突如其来的疫情,商会第一时间做出响应,发布《致全体会员抗击疫情倡议书》和《致全体党员抗击疫情倡议书》,商会会员企业及个人积极响应号召,以实际行动为抗击疫情捐资捐物,投身各项疫情防控工作。据不完全统计,商会企业累计捐助善款及物资近6000万元,商会党委及委员企业累计捐助善款及物资550余万元。期间,我们为瑞金医院援鄂医疗队送去了冲锋衣,为宁波家乡一线工作人员送去了防护服,为华山医院医护人员送去了暖心礼包,杉杉华清医院、大众出行服务、小汤山医院改扩建工程、雷神山医院信息化工程、分众电梯公益广告等等,甬商积极参与各项抗击疫情前线建设和后勤保障工作事例不胜枚举,全体甬商上下一心共同为打赢此次疫情阻击战贡献了力量。\n第三、脱贫攻坚,助力社会事业发展。\n商会始终将家国情怀与企业发展紧密结合,号召全体会员企业践行社会责任。我们致力公益的脚步从未停歇,我们捐赠宁波恩美儿童福利院,关爱折翼天使,我们捐赠上海交通大学医学院附属新华医院,营造儿童公益空间,我们捐赠上海甬协公益基金会,助力贫困优秀大学生读书,我们支持上海公益伙伴日,引领公益之光。商会企业中有代表性的比如分众传媒美丽中国乡村支教、龙元慈善基金会、全筑关爱脑瘫儿童、一兆韦德“老兵回家”等等公益项目,据不完全统计,商会会员企业每年捐助公益项目金额近亿元。\n同时,商会企业在助力脱贫攻坚的道路上,留下了深刻的足迹。例如致达集团,2016年起联合6家企业共同向云南省彝良县捐赠4500万元,修建道路、农民新村和希望小学,目前已经让4000户居民喜迁新居、数百名小学生有了崭新明亮的课堂,使村民逐步摆脱贫困,迈向幸福生活。例如宁波银行上海分行作为第三届进博会“消费扶贫生活馆”的唯一金融支持单位参与其中,为扶贫攻坚和公共卫生安全贡献自己的力量。\n家国有需要,甬商有担当!上海甬商始终坚守初心,爱国敬业,在奉献社会中创造价值,在高质量发展浪潮中勇于担当。",
"cover": {
"name": "N16.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N16.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N16.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N16.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 342,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市宁波商会"
},
"voted": false
},
{
"case_id": "419561056730619904",
"code": "N20",
"title": "上海乐爱社工师事务所",
"detail": "2012年乐爱在上海市民政局注册成立,多年来致力于提供助残社会工作、社区工作等专业服务,是一家5A级社会组织。业务重点服务浦东新区,杨浦区、徐汇区、宝山区,辐射上海市16个区以及无锡惠山区,总计服务60余个街镇,累计服务人次超过61万人次。多年来获得多项市级、区级奖项。\r\n阳光家园服务\r\n乐爱社工运用“助人自助”的理念为残障学员提供康复服务。包括生活自理、劳动技能、教育培训、康复训练以及社会参与等,提升学员个人能力,为其家庭提供支持,促进亲子关系融洽缓解家庭照护压力。搭建其参与融入社会的平台。2012年至今乐爱累计服务“三阳机构”学员共计17余万人次,为多个“阳光家园”获得了荣誉。如金杨街道“阳光心园”被市残联誉为“上海市残疾人之家”,徐家汇、殷行街道的“阳光心园”获得了“上海市示范型阳光心园”等。\r\n多年助残经验的基础上,形成专业助残服务模式并制定浦东新区阳光之家星级评定标准,在区级助残服务方面,2017年乐爱受浦东新区残联委托对浦东36家“阳光之家”进行培训和督导。\r\n研发行业标准\r\n2019年乐爱与上海市残联合作共同研发制定了《上海市“阳光之家”星级评定标准》,为16个区开展星级评定指标解读的培训,为整个上海市“阳光之家”的服务管理能级提升做出了贡献。\r\n\r\n社区精神障碍服务\r\n社区精神障碍患者由于病情造成生活技能减退,个人及其家庭承受了长期的照护和精神压力。社区对精障人士的排斥及偏见使他们难以融入社会。自2014年开始,乐爱运用“社区康复模式”在殷行街道、徐家汇街道、杨浦区精神卫生中心开展了社区精障患者服务管理平台项目,打造了“康复离院、回归家庭、适应社区、融入社会”完整服务模式。2021年,乐爱开展的社区精神障碍康复工作获得了市民政局的认可,作为第一批试点单位在杨浦区开展试点工作。\r\n该项目在2015年获得《杨浦区十佳优秀案例》,2018年作为社区治理经典案例,收录在上海政法委出版的《综治研究》一书中,2020年,机构也通过此项目被评为“上海市平安示范单位”。\r\n社区治理项目\r\n乐爱发挥专业优势运用“社区工作模式”不断探索社区治理途径,2018年开始承接宝山区区级层面的“活力楼组”建设项目,以“增能赋权”专业理念,探索社区问题解决的新途径。\r\n截止到2021年,乐爱在宝山区12个街镇2个园区,打造了4000余个“活力楼组”。项目获得了中共上海市委组织部、中共上海市委政法委、中共上海市社会工作委员会颁发的“中国(上海)社会治理创新实践优秀案例奖”。",
"cover": {
"name": "N20.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N20.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N20.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N20.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 762,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海乐爱社工师事务所"
},
"voted": false
},
{
"case_id": "421773466363342848",
"code": "N12",
"title": "上海市白玉兰开心家园家庭服务社",
"detail": "“白玉兰”自2013年成立以来,在市妇联悉心培育指导下,在全国三八红旗手赵红娣社长带领下,弘扬公益精神,创新公益实践,用爱心铸就公益服务品牌。\n“白玉兰”坚持将发展公益作为立业之基。在服务对象上,以公益为民的情怀,聚焦困境中的妇女、儿童和家庭,持续深化调解、心理辅导及危机干预等服务;在团队建设上,以公益精神滋养培育了一支200人的志愿服务总队;在公益实践中,以人文关怀精耕细作项目;“白玉兰”在上海这片公益沃土中蓬勃生长。先后获全国维权先进集体、市三八红旗集体、优秀女性社会组织,巾帼文明岗等荣誉称号,获评上海市规范化建设五A社会组织。白玉兰志愿者团队公益服务事迹三次受到上海电视台新闻坊专访和宣传。多次在中国社会组织、上海社会组织等杂志刊登服务事迹。\n为提升服务妇女儿童身心健康专业水平,白玉兰志愿服务总队分设“心理疏导、危机干预、讲师团辅、督导培训、项目执行”五支团队,实行精细化服务。2018--2019连续二年在全市开展“幸福从心出发”百场公益讲座;与市妇联携手打造“12338”心理咨询热线,线上线下同步开展心理援助和危机干预服务,年平均服务3万多人次。为了打造“开心家园”品牌,在做强本部旗舰的基础上,深入各区指导因地制宜建立开心家园心理咨询工作站、社区心理服务点,并在部分区成立“6+1”开心家园示范点,将信访接待、法律援助、人民调解、心理疏导“四位一体”功能落实到基层妇女之家,形成同城效应。\n为了更广惠及民生,积极申报开展各类公益项目,受益人群涵盖失独家庭、妇科癌症患者、单亲困难母亲、困境儿童等,服务范围遍及市内11个区,受益人群达5万多人次。通过心理疏导、团体辅导和主题活动等多种关护形式,引领舒展心胸,直面困境,塑造健康人生。\n“白玉兰”着力打造“知心妈妈”服务品牌。五轮近10年,每年承接政府疑难信访件100多起,面对坚冰,发挥第三方优势,爱心陪伴、认知引导,在政府和上访者之间架起沟通的桥梁,化解率达50%以上,挽救了众多深陷泥潭的家庭。不少对象送来了感谢信、锦旗等,以示感谢。提炼创立的“五步法”,成为化解信访矛盾的行动指南。市信访办和市妇联两次授予“白玉兰知心妈妈项目服务贡献奖”。\n白玉兰主动承担社会责任。2015年元旦外滩踩踏事件,2019年3.25江苏响水化工厂爆炸事件,5.16长宁区建筑工地倒塌等重大灾害事故,白玉兰总会在第一时间请缨并参与救援,使身心遭受重创的家属及时得到抚慰和帮助。为助力抗疫,开设了15场公益微课,8个微信群,为包括社区群众、居委干部、居家学生、消防官兵、城管队员等提供心理调适,更义无反顾与医护人员一起,奔赴长宁区临空留验点开展专业疏导,让700多个回沪人员在第一时间感受到祖国的温暖和伟大。\n白玉兰以专业与爱,让生命如花绽放!",
"cover": {
"name": "N12.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N12.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N12.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N12.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3685,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市白玉兰开心家园家庭服务社"
},
"voted": false
},
{
"case_id": "423887740208525312",
"code": "N10",
"title": "上海仁德基金会",
"detail": "上海仁德基金会是2011年12月9日在上海市民政局注册成立的公募基金会。2016年11月,仁德成为上海市首批获得“慈善组织登记证书”和“慈善组织公开募捐资格证书”的五家公募基金会之一。2017年12月通过5A级社会组织评审,成为5A级公募基金会。2019年,上海仁德基金会成立了联合党支部,在党建的引领下,仁德团队立足上海、辐射全国,开展公益活动。\n一、高效透明坚守公益初心\n仁德基金会自成立以来募得善款总计3.64亿,支出善款总计约3.04亿。2017年到2020年每年投入的公益项目资金分别是6248万、8035万、5091万和7992万。仁德高效透明的工作,让一些品牌项目获得政府、社会和企业等相关部门的认可和肯定;得到了新闻媒体的积极宣传和捐赠人的大力支持,项目影响力大、辐射范围广。如“亲亲禾苗,营养一餐”项目持续开展困难学生帮扶工作,自2015年8月实施以来,累计筹款3000多万,已为4.7万名偏远贫困地区的中小学生和特殊学校学生送去营养餐,项目入选国务院扶贫办“2019年全国社会组织扶贫50佳案例”;“春柳-留守女童关爱项目”自2017年实施以来,关注留守女童生理和心理健康,荣获中国慈善项目大赛百强项目荣誉。仁德也连续6年在中国基金会透明指数FTI的(FoundationTransparencyIndex)评比中获得满分100分。在事业不断发展的过程中,仁德也非常注重自身的规范化建设,通过完善内部治理结构、开展建章立制工作、实施员工绩效考核,学习和掌握相关法律法规等活动,在思想上提高员工的意识,在实践中提高员工的技能,在考核中约束员工的行为,从而保障仁德的公益事业公开、透明,符合法律法规的要求,帮扶到真正有需要的人。\n二、高效对接,积极抗疫防疫\n在2020年抗疫工作中仁德团队行动迅速,从1月29日至3月10日的42天内,为了将爱心捐款及时转换成抗疫前线急缺的物资,团队成员们24小时连轴转,通过全国的合作伙伴网络采购物资、联系物流,确保在最短的时间内将物资送到医院和医护人员手中。同时,每一笔抗疫善款的支出都在第二天通过微信公众号向捐赠人和社会公众公示。仁德在抗疫工作中奖励和慰问了1200名上海援鄂医护人员和上海公卫中心医护人员;为上海东方医院等15家医院和5家武汉的医院捐赠了抗疫物资;为疫情期间奋战在养老一线的养老院、养老助餐点和养老护理员捐赠了防疫物资和关爱津贴。仁德还是第一家完成海外捐赠物资免税手续的基金会。\n三、响应政策,助力脱贫攻坚\n2019年-2020年期间仁德员工们不怕苦不怕累,克服高原反应,深入到“三州三区”、云南、贵州的对口支援地区实地调研,充分了解当地老百姓的需求。在此基础上,仁德在“三州三区”、云南和贵州的对口支援地区开展了59个项目,捐赠扶贫资金达1030.8万元,受益人数达9万人次。这些项目以关怀对口支援地区的弱势群体和有需要的群体为己任,积极开展帮扶老、弱、病、残、孤等群体的公益活动。\n四、踊跃参与,增色社区服务仁德从2018年开始与杨浦区12家基金会牵手,支持和辅导社区基金会开展互联网筹款;为全市15家社区基金会参与99公益日筹款提供专业的技术支持和周到的服务。今后,仁德将结合十四五规划和2035年远景纲要的要求,结合上海市公益事业的规划,继续做好品牌项目,让仁爱之心和贤德之举的种子结出更加丰硕的果实。",
"cover": {
"name": "N10.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N10.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N10.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N10.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 2607,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海仁德基金会"
},
"voted": false
},
{
"case_id": "425393918906314752",
"code": "N09",
"title": "上海财经大学教育发展基金会",
"detail": "上海财经大学教育发展基金会是2008年在上海市民政局登记注册的慈善组织,我们以围绕公益、服务上财、服务社会为核心,助力学校建设成具有鲜明财经特色的世界一流大学,在吸引更多的社会力量参与高等财经教育发展的同时,支持抗疫、乡村振兴、长三角发展等工作,践行服务国家战略实施和社会公益发展。\r\n十三年来,上财基金会资产的总规模和公益性支出不段攀升,通过“理念协同、机制协同、项目协同、队伍协同”深化多元化筹资机制,发挥上财专业优势,投资收益表现亮眼。截至2021年6月,基金会净资产为2.62亿元,年均实施项目约为150项,受益人数2万余人。基金会遵守公开透明、专业规范的原则,2017年获评5A级社会组织,并成为上海首家高校公益基地;中基透明指数持续5年保持满分,2020年获上海唯一满分高校基金会。持续打造公益品牌,传播公益文化,连续三年分别以“公益校庆”、“咖啡绿植”、“元阳帮扶”获评公益之申十佳公益校园和公益项目。\r\n1、红色经典,强化党建内涵\r\n在建党100周年之际,基金会携手校友企业设立党建育人基金,通过引入《永不消逝的电波》等一批上海创作的红色经典艺术剧作,打造沉浸式党课,引导党员、师生在感悟经典中赓续红色基因、厚植爱国情怀、汲取精神力量;鼓励支持教职工开展党建课题研究,把党建当学问做,推进党史教育入脑入心。\r\n2、立德树人,关爱学子成长\r\n围绕学校育人的根本任务,基金会累计设立100余项丰富的奖助学金,如山佳奖学金奖励进步最大的学生,让获奖的同学感受到努力被认可的喜悦;设立首个民族专项—石榴籽基金,筑牢中华民族共同意识,贴近、关心和助力民族学生成长成才;设立“心动力”基金,加强学生心理健康教育的内涵建设。\r\n3、千村调查,助力乡村振兴\r\n中国农村是大学生熟悉社会、了解国情的最好课堂,基金会助力打造持续13年的实践项目“千村调查”,支持学生走千村、访万户、读中国、传递爱,将青春写在祖国的大地上,通过田野调查获取数据资料、形成决策咨询报告,为国家相关部门决策提供参考。\r\n基金会设立元阳帮扶基金,携手广大师生、校友、企业和基金会投入和引进400余万资金,从教育、党建入手,助力云南元阳县精准脱贫。我们也将持续为推进乡村振兴贡献上财力量。\r\n4、文化传承,发挥公益育人\r\n基金会聚焦公益育人,指导成立学生公益社团—思源社,启动“六个一”公益传播计划,以“一站公益基地、一堂公益课、一本公益护照、一个公益项目、一次志愿服务、一起做公益”为抓手,“走出去、请进来”携手沪上优秀公益机构,向师生播撒公益种子。\r\n百年芳华,初心如磐。鉴往知来,砥砺前行!上财基金会将持续打造一流,期待更多人和我们一起用公益点亮希望,让城市和社会更温暖。",
"cover": {
"name": "N09.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N09.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N09.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N09.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 1564,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海财经大学教育发展基金会"
},
"voted": false
},
{
"case_id": "425366695058976768",
"code": "N19",
"title": "上海复星公益基金会",
"detail": "复星自成立以来,秉承“修身、齐家、立业、助天下”的理念,深入践行企业社会责任,坚持服务社会、人民和国家。上海复星公益基金会成立于2012年11月,是以复星为主要捐赠人的公益行为体。\n上海复星公益基金会为“中国社会组织评估等级·5A级社会组织”,主要业务包括:健康福祉、教育、文化艺术及青年创业、就业等。每年捐助公益项目30余个,辐射全球多个国家和地区。\n\n抗疫:2020年1月24日除夕当晚,复星紧急成立“全球抗疫指挥部”,启动全球调配医疗物资的抗疫行动,复星基金会设立抗疫专项基金积极投身抗疫。\n此后,复星逐步建立了覆盖日本、印度、英国、德国、巴西、以色列、韩国、波兰等23个国家的物资调配网络,筹措了近300万件各类医疗物资,驰援了包括湖北武汉在内的国内28个省市区抗疫一线。\n2020年3月,在国内疫情持续好转,国外疫情却又呈现爆发态势的情况下,复星又立即启动全球人道主义驰援计划,向全球40多个国家开展捐赠行动。\n复星基金会始终在抗疫前线。自2021年4月底启动驰援印度人道主义行动,五一假期期间,复星印度区域抗疫指挥部休假不休兵,在总指挥部、制氧机生产厂、机场及物流中心、印度前线,复星在每一个环节安排专人把关,争分夺秒加紧生产运输,将印度紧缺的制氧机、呼吸机、口罩等防护设备以最快速度运往当地。\n\n乡村医生:2017年12月,在国家卫生健康委扶贫办的指导下,复星瞄准精准扶贫的薄弱环节——贫困人口的基本医疗保障需求,联合中国光彩事业基金会、中国人口福利基金会等,发起“健康暖心——乡村医生健康扶贫”项目(以下简称“乡村医生项目”)。三年来,复星调动全球资源助力基层医疗体系建立,项目覆盖全国15个省、市、自治区的70个国家级贫困县(包括13个“三区三州”深度贫困县),共帮扶12545个行政村卫生室,守护22192名乡村医生,惠及300万户基层家庭。\n乡村医生健康扶贫项目以帮扶乡村医生为切入口,围绕守护、赋能与激励村医三个核心内容,推进以“五个一”工程为抓手的全方位立体式帮扶计划,派出员工志愿者驻点接力扶贫,帮助贫困地区培养并留住合格的乡村医生,有效提升基层医疗卫生服务水平,最终助力国家脱贫攻坚任务圆满完成。\n2021是中国乡村振兴的元年,在《中共中央国务院关于全面推进乡村振兴加快农业农村现代化的意见》的指引下,复星将继续深化帮扶内容,巩固脱贫成果,以实现基层农村的健康振兴。乡村医生项目将进一步拓展帮扶区域和内容,提升村医的技术能力和工作环境,从而为广大村民提供更好、更可持续的医疗服务,助力“健康中国梦”早日实现。\n\n其他项目:\n-太极抗帕:经过六年多的坚持,至2021年3月,复星基金会“太极抗帕”公益项目已惠及近400位帕金森患者,这项公益还将持续进行。\n-青少年:2013年5月30日,伴随着复星与保德信在中国建立合资公司——复星保德信人寿,上海复星公益基金会与保德信金融集团联手将拥有18年历史的保德信青少年社区志愿奖引入中国,以推动中国青少年公益与国际接轨。青社奖来到中国已经走过了八个年头,至今已有超过4500名中学生申请。在过去的六届里,共表彰了数百位12-18岁在志愿服务或公益活动中做出杰出贡献的中学生志愿者。",
"cover": {
"name": "N19.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N19.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N19.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N19.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 1235,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海复星公益基金会"
},
"voted": false
},
{
"case_id": "427919603789049856",
"code": "N07",
"title": "上海市慈善教育培训中心",
"detail": "上海市慈善教育培训中心成立于1995年,现有员工15人,是一家5A级社会组织。中心成立26年来,始终坚持“知识扶贫、技能助强、促进发展”的宗旨,努力为各类社会群体开展公益慈善教育服务。近5年来,中心每年开展的公益慈善项目超过30个,年投入项目资金近1000万元,每年直接惠及人数超过5万人,从多方面体现了上海对弱势群体的人间大爱和城市温暖,起到公益示范引领作用。先后被评为上海市第七届“慈善之星”和静安区“文明单位”。\r\n1、“大众创业、万众创新”特色明显。中心连续16年在全市90余所高校、中职校举办了免费创业教育培训班,举办上海市青年创业夏令营,累计投入资金540余万元,共惠及大中专学生13000余人,其中有9人获得全国创业大赛一等奖和全球创业精神大奖。有数百名学生实施了自主创业,成为活跃在上海和帮助家乡脱贫的成功创业者。\r\n2、“共享阳光、助力脱贫”。中心从2015年起连续实施“共享阳光”公益行动,累计投入资金1500余万元,帮助1000多名外来务工者获得大、中专学历证书,有1500多人通过参加免费职业技能培训提升了职业能力,在上海稳定就业,助力脱贫,提高了生活水平。\r\n3、“金融普惠教育,推进社会和谐”。中心从2016年起对社区老年人、外来务工者、在校大学生、社区青少年等人群免费开展了金融知识和防范金融风险教育及少儿财商教育,累计投入资金690.9万元,惠及人员近10万人。\r\n4、“创意艺术教育,助力青少年发展”。中心从2013年开始启动“牵手艺术彩虹·献给未来地球”青少年创意艺术教育培训项目,8年来投入资金1400余万元,吸引了12万人次的青少年参加,探索了自闭症青少年通过创意教育提升工业设计能力的途径和方法,建立了教育、产业、商业和媒体深度融合的新模式,一些优秀设计作品被应用于文具等产品,一批自闭症青少年提高了社会交往能力,有的建立了个人工作室,有的实现就业。\r\n5、“科普教育,提升素质”。中心从2017年开始对青少年免费开展无人机科普教育,并组织开展了有200万人次青少年参加的全国航空·无人机科普培训和大赛,将青少年科普教育与国防教育、公益教育相结合,开创了特殊青少年科普教育的新途径。\r\n6、“抗疫情、送温暖”。新冠疫情期间,中心积极做好防疫、抗疫物资捐赠工作。组织艺术家以各种艺术表演形式进行抗疫宣传,举办“共克时艰抗疫情,线上义演赞英雄”慈善专场演出,用抖音、美篇等方法合成一个个微视频作品,其网上展播量超过80万人次,鼓舞了全国人民抗疫必胜的斗志。为湖北“共享阳光”学员及时送上一份慰问金,表达了对英雄的武汉和湖北人民为战胜新冠疫情作出重大贡献的感谢。\r\n7、“示范引领,体现责任”。中心注重公益慈善的诚信建设,26年中没有发生诚信和质量问题,近五年来,带动3万人次志愿者参与公益项目,有100多家企业和机构合作开展公益项目。中心还为本市和外地社会组织开展能力建设培训,仅中心原副主任徐本亮一人就为全国4000多家社会组织开展了培训和咨询。",
"cover": {
"name": "N07.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N07.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N07.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N07.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 1076,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市慈善教育培训中心"
},
"voted": false
},
{
"case_id": "429036392128294912",
"code": "N17",
"title": "上海秋海堂文化艺术中心",
"detail": "秋海堂文化艺术中心(以下简称秋海堂)创办于2014年,缘起并蒙恩于海上艺术大家——书画泰斗陈佩秋、著名书法家刘小晴先生。创办者是两位书画大家的共同入室弟子徐宏斌。\r\n2018年3月31日,陈佩秋先生曾亲自为秋海堂陈佩秋大师工作室揭牌。2018年12月8日刘小晴书法工作室在秋海堂正式揭牌;2017年起著名画家陈翔(现上海中国画院院长)在秋海堂开设陈翔中国画公益讲堂。\r\n依托名家大师工作室,秋海堂致力于书画艺术的传承、传播。守正创新,紧贴时代,举办高水平的艺术活动;推动书法文化进校园,注重美育、德育相结合;发起秋海堂刘小晴艺术基金,坚持投身公益和扶贫事业,持续帮扶徐汇区对口支持的云南省红河州,为脱贫攻坚事业作出突出贡献。正因为连续几年文化扶贫的行为和贡献,秋海堂文化艺术中心创办人,徐宏斌老师,于2021年2月份被评为全国脱贫攻坚先进个人的荣誉。而且在全国三千多先进个人当中,他也是唯一的书法工作者。这也是对秋海堂多年来文化扶贫的最大肯定。\r\n秋海堂文化艺术中心是在徐汇区民政局注册、接受徐汇区文旅局指导的优秀公益组织,先后被评为或授予:徐汇区美术馆美育共同体成员单位(徐汇区文旅局),徐汇区市民修身基地(徐汇区文明办),徐汇区新的阶层人士工作示范点(徐汇区委统战部)、徐汇区特殊对象未成年子女教育关爱基地(徐汇区司法局)、徐汇区政协书画院创作基地(徐汇区政协)。2021年入选上海百佳社会组织排行榜。\r\n秋海堂植根徐汇,已先后设立虹梅街道、天平街道、凌云街道等大师工作室社区基地,并先后与高安路第一小学、上海市中国中学,世界外国语中学等合作共建。开展“百场公益讲座”活动,先后走进多家学校和社区,两年时间已经进行了70多场书法公益讲座,影响到数千名青少年。秋海堂曾被《人民日报》作为上海艺术馆品牌典型进行专题报道。",
"cover": {
"name": "N17.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N17.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N17.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N17.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3179,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海秋海堂文化艺术中心"
},
"voted": false
},
{
"case_id": "426455554140151808",
"code": "N08",
"title": "上海市基金同业公会",
"detail": "上海市基金同业公会成立于2010年11月18日,是由上海基金行业相关业务单位发起并自愿组成的行业性的非营利性社会团体法人,是中国第一家基金行业自律组织。目前,公会共有会员单位181家,包括上海地区66家公募基金机构,37家资产管理机构,24家私募基金机构,32家基金销售机构,22家异地基金管理公司在沪分支机构。其中,公募基金会员管理资产规模8.67万亿元,占全国37.84%。\n公会成立以来,始终以公益为立会之本,坚持以服务为基础、自律为核心,充分发挥公会的桥梁纽带作用,在投资者教育、自律管理、会员服务、国际交流、社会责任上成功打响了中国基金业第一家同业公会的品牌,为建设上海国际金融中心和国际资管中心作出积极的贡献。\n\n-探索公益投教新模式,强化投资者保护工作\n公会自成立以来,累计举办投资者保护教育宣传活动百余场,向投资者发放实物投教产品达40万件;首创网上基金学院、公募基金集体接待日,通过网络打破了地域界限,让全国各地投资者与上海基金公司实现零距离互动交流;策划筹建上海地区首个由自律组织和地方政府共建的投资者教育基地:上海基金业—陆家嘴金融城投资者教育基地,提供投资者看得见、摸得到的多元公益投教;与第一财经携手打造业内首个投资者教育电视栏目《基金时间》,每周三晚在第一财经电视、抖音等平台播出,帮助投资者更好地认识基金,树立科学的投资理念,受到业内业外高度认可和广泛赞誉,成为上海基金业的投教新名片。\n\n-发挥行业核心优势、服务国家发展战略,进一步推进金融行业对外开放\n2020年4月1日起,我国正式取消对证券公司、公募基金管理公司的外资持股比例限制。在此背景下,3月31日,在我国正式取消对证券公司、公募基金管理公司的外资持股比例限制的前夕,由公会牵头编写的《海外资管机构赴上海投资指南》中英文双版正式发布,收到海外资管的高度评价,这是国内同类行业协会为服务海外资管机构推出指南性文件的首次尝试,同时也开创了城市编写指南吸引海外资管投资的先河。\n\n-行业强大合力应对疫情,彰显社会组织公益属性\n2020年1月,湖北武汉爆发新冠疫情,公会第一时间向行业发出《致敬白衣天使项目倡议书》,设立全国首个由行业自律组织发起的专项基金:上海基金业致敬白衣天使专项基金。专项基金共筹集了4748.1736万元,直接拨付抗疫医务工作者2676万元,受益医务人员及家属共计4349名;支持市卫健委“防控新冠疫情纪念铜章”、市基层卫生抗疫表彰活动、《逆行者》—上海援鄂医务人员群像雕塑等公益项目;致力推动上海市医疗卫生系统人才培育,支持上海市“杰出青年医学人才”以及“十佳家庭医生”项目。专项基金荣获上海慈善最高奖项第十一届“中华慈善奖上海市提名奖”。此外,上海基金业捐款捐物超过一亿,在全市社团组织中位居前列,充分展现上海基金业责任与担当。",
"cover": {
"name": "N08.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N08.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N08.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N08.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 2273,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市基金同业公会"
},
"voted": false
},
{
"case_id": "422875798316593152",
"code": "N05",
"title": "上海市浦东新区旅游业协会",
"detail": "上海市浦东新区旅游协会成立于1995年,是浦东新区旅游行业企事业单位自愿组成的跨部门、跨所有制的非营利行业性社会团体。\n协会成立至今,先后获得市级、区级各项荣誉称号,2016年,被上海市社团管理局评为“5A级社会组织”。现有会员单位超过350余家,下设宾馆、旅行社、景点、旅游投资发展4个专业委员会,行业覆盖率90%以上。\n在新区民政局与新区文体旅游局指导与支持下,协会以探索公益创新模式为目的,积极践行公益事业之路。今天,我将从三个方面着手,为各位评委老师讲述我们的公益事业:\n一、紧握服务企业根本,打造特色公益品牌\n多年来,协会紧紧围绕以公益促发展,以服务促提升,不断迭代升级特色公益品牌,结合浦东旅游实际情况,积极开展各类公益活动,为推动上海建设“公益之城”添砖加瓦。\n协会以服务会员为工作核心,以极力支持社会公益活动为根本,秉持着“为会员排忧解难、为行业保驾护航”的服务理念,始终按照“服务、代表、协调、自律”为工作宗旨,不断积极探索公益模式,先后树立了5·19中国旅游日浦东新区主题活动、对口援建、新区旅游业纠纷调解公益平台、浦东旅游志愿者队伍等协会特色公益品牌项目。\n二、发挥行业资源优势,践行公益旅游之路\n为深入贯彻落实习近平总书记关于对口支援工作一系列重要指示精神,根据翁祖亮书记关于浦东与莎车、大理2020年度扶贫协作工作指示,协会先后组织开展新区旅游企业赴新疆莎车县、云南大理市进行旅游援建工作,就客源输送、文旅融合发展、旅游产品定制、旅游资源整合、运营效率提升、人才培养、民宿产业探索等多方面给予扶持,以实际旅游产业提升与经济效益拉动来促进沪疆、沪滇之间文化旅游援助行动。\n同时,协会积极围绕打造浦东公益旅游新项目,在5•19中国旅游日策划开展浦东新区主题公益活动,活动通过旅游企业集体宣传浦东旅游资源,讲好浦东旅游故事,同时串联滨江“世界会客厅”及网红打卡点,将7色丝带化身爱和正能量进行传播与分享,营造多样化沉浸式旅游休闲体验,体现“彩色让世界更美好”精神。\n另外依托强大的会员体系及组织优势,协会积极探索建立以浦东新区旅游企业为志愿者的旅游志愿服务队伍。进一步引导新区旅游从业人员做文明旅游的倡导者、推动者、实践者,推动规范长效的旅游志愿服务机制,提升浦东新区旅游质量满意度。\n三、助力企业复工复产,拓展延伸公益新思路\n随着疫情防控进入常态化,国内游在不断恢复中,内循环成为旅游复苏的主战场。协会抓牢重点工作,整合内需,创新打造了“惠游浦东”品牌,推出了“惠游浦东”旅游联票和“惠游浦东”文旅巡展等活动,进一步刺激文旅消费潜力,助力畅通新区文旅企业后疫情时代内循环通路。\n今后,协会在各项公益活动、志愿服务活动中将拿出120分的热情和150分的努力,以非营利性作为基础,积极探索公益新模式,为推动公益之城建设垒土筑基。",
"cover": {
"name": "N05.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N05.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N05.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N05.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 2276,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市浦东新区旅游业协会"
},
"voted": false
},
{
"case_id": "426458849424449536",
"code": "N01",
"title": "上海霞满云间公益发展中心",
"detail": "简介:\r\n上海霞满云间公益发展中心是一家专注机构养老、社区养老、居家养老、智慧养老业务的社区服务综合体。\r\n愿景——做上海最专业的上门居家养老服务机构\r\n使命——使用科学技术和爱的力量,为改善提升服务对象的生活生命质量而不懈努力\r\n理念——以生命服务生命以生命影响生命\r\n价值观——守法、尊重、安全、专业、快乐\r\n运营能力:\r\n霞满云间以专业为基础,将机构养老、社区养老和居家养老深入融合。机构自2012年成立以来,人员团队不断壮大,人员流失率1%,政府采购项目承接规模逐年递增,年度收入增长率约41.17%。霞满云间下辖机构养老四家,社区综合为老&日间养老6家,居家养老涉及松江7个街镇,实施分区域分层次阶梯式管理,为老年朋友提供标准化、专业化、人性化养老护理服务。\r\n公益理念:\r\n饮水思源、回报社会,是企业应尽的社会责任,霞满云间自2012年成立至今,主动承担社会责任,上海霞满云间公益发展中心是上海市民政局5382号公益基地,下辖5家公益基地,由专人负责管理,定期在“公益上海”平台发布公益消息,募集社会各方力量,倡导传播公益精神,救助弱势群体,努力营造社会和谐共享氛围。霞满云间积极开展公益项目,有认知症友好社区建设、失能老人助浴、爱心护理床、老伙伴互助等等,截至2020年底,机构共计承接公益项目100多个,服务老人达10万余,受益人次100万余人次,为提高社区老人生活生命质量做出了应有贡献。\r\n公信力、影响力:\r\n机构与日本、台湾、马来西亚等专业服务机构常年合作,与上海智障志愿者团队结成合作伙伴关系;经常接受市、区民政、区残联、街镇相关部门的指导和培训。\r\n并于2015年荣获上海市4A级社会组织;\r\n2015年、2018年和2019年荣获上海市肢残人协会颁发的优秀集体奖;\r\n2016年荣获优秀社会组织;\r\n2017年荣获慈善基金会颁发的慈善社会组织荣誉证书;\r\n2018年被评为2016-2017年度先进慈善义工集体;\r\n2019年荣获方松街道颁发的方松最美团队荣誉证书;\r\n“为长期卧床老人上门助浴”案例在2019年松江区养老服务行业评选表彰活动中荣获“十佳养老服务案例”称号;\r\n2020年度上海市承接政府购买服务社会组织,荣获《聚焦热点》栏目品牌机构展播(播出平台:上海电视台纪实人文频道),同年荣获慈善基金会颁发的“慈善捐赠爱满云间”奖杯。服务中频频收到服务对象送来的感谢信、锦旗等。\r\n2021年承接机构养老方松街道敬老院20年度上海市养老机构服务质量监测排名区排名第二,市排名前五。\r\n可持续发展:\r\n上海霞满云间公益发展中心以公益为纽带,促进“企社”、“社社”的合作。以慈善为导向,将社会各方面的人士共同联合起来,更进一步去激发社会的爱心,把我们的养老事业、养老服务做得更好。\r\n养老事业是非常富有意义的,我们将不遗余力地按照我们党“人民城市人民建,人民城市为人民”这个理念,共同去贴近养老事业的发展,让我们老年人的感受度、满意度、温暖度获得一个很大的提升。",
"cover": {
"name": "N01.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N01.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N01.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N01.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 4352,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海霞满云间公益发展中心"
},
"voted": false
},
{
"case_id": "422530524956082176",
"code": "N11",
"title": "上海市阳光社区青少年事务中心",
"detail": "上海市阳光社区青少年事务中心成立于2004年2月,是一家致力于青少年成长发展的社会服务机构。主要承接政府委托的6-25周岁社区青少年教育、管理和服务事务,400余名专职青少年事务社会工作者分布在13个区167个街镇,运用专业方法开展就业创业、社区融入、亲职教育、生命健康、助困增能、志愿服务、外展服务、未成年人司法等八大类服务。\n一、秉持专业理念,践行助人自助宗旨\n(一)关爱困境青少年,陪伴健康成长\n主要对城区困境青少年、金山(准)孤儿、崇明区留守儿童提供服务,建立“一人一档”,以个案辅导、家长沙龙、自护课堂、志愿服务等形式开展专业服务,引导困境青少年群体“爱自己、爱家庭、爱社区”,以全方位、多维度的陪伴式服务提升青少年的自我认同感和社会融入感。\n(二)关注未就业就学青少年,引导回归社会\n面对16至25周岁的未就业就学青少年群体,从优势视角出发,以就业促业、学历技能提升为抓手,协助与家庭、社区建立联结。2004年至今协助近五万名青少年成功就业。\n(三)聚焦特定青少年,促进社会融入\n一是面向刑事案件中需要帮扶、救助的未成年人开展教育引导和正向激励,累计服务、帮教违法涉罪未成年人1万余名;二是已介入近千个涉未成年人家事案件,提供庭前调解、心理疏导、家事调查、回访观护、担任探望监督人等服务,维护未成年人合法权益。\n二、构建保护体系,探索社会治理模式\n(一)参与地方标准建设,推动行业发展\n机构作为主要起草单位参与研制全国首个聚焦未成年人司法领域的《未成年人司法社会工作服务规范》这一上海地方标准。该标准的建立促进了全国未成年人司法社会工作的专业发展。\n(二)建立合作应急平台,集合专业力量\n机构建立“跨专业多部门合作应急平台”,联合高校、精卫中心、青少年热线、基金会、律师、媒体等力量形成青少年保护合作联盟,共同为青少年搭建权益保护“港湾”。\n(三)设立阳光研究院,加强分析预判\n每年面向高校发布青少年重点、热点问题的研究项目指南,联同市阳光中心的资深青少年事务社会工作者开展协同式研究。定期将现状、问题及针对性的对策建议形成调研报告、专报,助力相关职能部门对青少年问题的研判。\n成立十七年来,上海市阳光中心坚持以职业化、专业化为导向,加强社工队伍建设,汇聚了一批具有社会工作专业知识、勇于创新、敢于开拓、无私奉献的社工人才,在保护青少年权益的道路上不断前行!",
"cover": {
"name": "N11.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N11.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N11.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N11.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 923,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市阳光社区青少年事务中心"
},
"voted": false
}
]
export default data
\ No newline at end of file
const data = [
{
"case_id": "4245898071640719361",
"code": "N06",
"title": "复旦管理学奖励基金会",
"detail": "我国自古就有优秀的管理思想和实践,但中国现代管理科学则是在改革开放之后才逐步发展起来的。为进一步推动我国现代管理科学发展,原中共中央政治局常委、国务院副总理李岚清同志于2005年发起成立了复旦管理学奖励基金会,这也是中国人自己设立的管理学界第一个奖励基金会。\r\n“要真正解决好中国的管理问题,最终还是要依靠中国人自己。”这句话道出了“管理”必须根植于一个国家的社会组织和民族文化。管理科学,是兴国之道,也是一个国家软实力的重要组成部分。\r\n十六年来,基金会各项管理逐步完善,2020年首次参加社会组织等级评估即被授予“5A级社会组织”荣誉称号;FTI透明指数排名连获最优等级。基金会的评奖工作,及其开展的一系列公益项目,获得了来自各界人士的一致认可;同时借助媒体之力,不断拓宽公众对中国管理学的认识边界,受益人数不断增加。如今,基金会已逐渐发展成为中国管理学界最具影响力、最具公信力的基金会。\r\n作为一个“奖励性”的基金会,我们希望打造中国管理学界的“诺贝尔奖”。基金会目前设立了“复旦管理学杰出贡献奖”“复旦管理学终身成就奖”“复旦企业管理杰出贡献奖”三大奖项,已成为我国管理学界享有崇高声誉、具有广泛影响力的重要奖项。截至2020年,已评选出57位获奖人,他们中不乏成思危、苏东水等矢志推动中国特色的管理学及其研究走向世界的杰出专家学者,亦有张瑞敏、任正非等对中国管理学不断实践、探索的优秀民族企业家。\r\n评奖之外,基金会还积极开展了丰富多样的公益活动。自2013年起,面向我国高等学府,面向青年师生,面向中西部地区举办了“校园公益”系列讲座活动,辐射师生5000余人。\r\n联合我国管理学一级学会,举办了一系列具有国际影响力的管理学学术盛会。其中,“中国管理学年会”是中国管理学领域规模最大、层次最高的综合性学术会议。另外,基金会通过支持“中国管理学青年论坛”,为有潜力的优秀青年架起了跨学科、跨层次的学习交流平台,旨在培养中国管理学的中青年力量。\r\n为加强学术界和实业界的合作,基金会充分发挥“桥梁·引领·赋能”作用,做到将“管理学带出去”,“管理领进来”,邀请获奖人、专家学者与企业家共话“管理”。\r\n基金会还与复旦大学东方管理研究院、第一财经合作开展了“中国杰出企业家管理思想访谈录”项目,已通过42集电视专题片、6部《改变世界》、14本研究丛书等形式对外发布,另有10多个优秀案例走进了高校课堂,收益人数达10亿多人。\r\n基金会积极响应习近平总书记“把论文写在祖国大地上”的号召,与《管理学报》合作,举办专题学术研讨会,开辟“中国企业家管理思想”专栏;与知名企业合作开展“海尔生态雨林计划”等专项研究。\r\n2020年新冠疫情的突发,对全国各地的公共卫生治理都是前所未有的考验。为总结出应对疫情的科学、高效的经验,提供疫情应对经验给相关部门,基金会资助了“新冠疫情防控防治的中国特色管理理论与方法”系列专著及案例研究。于基金会而言,这件事意义非常。\r\n作为一个扎根于中国管理学领域发展的公益组织,基金会在各级领导的亲切关怀下不断发展。获奖人所提出管理思想、管理理论和实践的创新、各项公益活动等,对于上海乃至全国各地的社会治理、公共管理与企业管理都发挥了重要的作用。在每年的颁奖典礼上,历任上海市领导均受邀出席并致辞。当今世界正面临百年未有的大变局,发展中国特色的管理学、并让中国特色管理学发挥更大的影响力,这比任何时候都更加迫切。在未来的公益发展事业中,基金会将继续助力中国特色管理学的探索和创新,为增强上海自主创新能力,提高城市国际竞争力,做出新的重大的贡献!",
"cover": {
"name": "N06.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N06.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N06.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N06.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "ENABLE",
"public_vote": 3406,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "复旦管理学奖励基金会"
},
"voted": false,
"liked": false
},
{
"case_id": "419178326515888128",
"code": "N14",
"title": "上海市普陀区长寿社会组织联合会",
"detail": "近年来,各类社区社会组织数量增长,规模扩大,社会组织日趋成为服务社区发展,提升社区治理水平的重要力量。所以以服务中心传统的点对点形式来去服务社会组织,已经不符合形势的发展,亟待搭建新的平台。在这种情势下,2016年长寿社会组织联合会孕育而生。长寿社会组织联合会是全市首家街道层面社会组织联合会。联合会以党建为引领,创新构建社区、社会组织、社会组织联合会的联动机制,这种全新模式不仅为社区与社会组织之间搭建了交流对接平台,也为促进社会组织自律自治、资源共享、健康发展创造了良好的条件。\n联合会运行以来,正式会员近百家。目前,长寿社会组织联合会成员中已有区党代表、区人大代表、区政协委员,充分激发社会组织领军人物的参与度,发挥社会组织自我管理、自我服务的能效。\n创新党建引领社会组织参与社区治理是我们的工作特色之一。2016年我们同步成立联合会党总支,党总支通过“价值引领、服务凝聚、同心共治”凝聚党员力量,提升基层组织活力。目前,党总支下设20个党组织、6个联合支部,14个独立支部。联合会自成立以来开展了一系列凝聚力建设活动,包括开展情景党课、建立学习教育体验站等等,我们还努力将公益理念引入党建活动,例如开展垃圾分类主题党日活动。通过这些活动和服务,不仅会员们的凝聚力日益增强,更是聚拢到了一批原先游离在边缘的社会组织。\n搭建公益服务平台也是我们最大的工作特色。我们通过公益秀、公益项目菜单、公益集市等形式将社会服务和项目精准化地投放到我们两新组织、楼宇和居民区,政府购买社会组织服务项目的数量及社区参与面都有了一个较大幅度的提升。\n在新媒体时代,为了更加方便项目对接,社联会依托微信公众号平台,于18年9月正式上线了长寿公e家网站。公e家的推出填补了20万以下政府采购服务对接渠道的空白。居民区科室可以进行社区需求发布,社会组织发布服务内容,这样以来加快了信息传递速率,实现了项目精准对接。例如,我们会在学生的暑假开展暑期班公益项目,让公益项目走进社区、走进百姓生活中。项目结项后,我们会举办成果展,把项目的成果进行公示,并在公E家上给承接方打分,能够让购买方一目了然地了解社会组织的服务能力。通过这样一个平台,我们让长寿的社会组织能真正了解到社区的需求,因地制宜地研发适合长寿、服务长寿的公益项目。尤其在疫情的冲击下,公E家的优势更加得到了肯定。2016年以来我们通过线上线下的渠道共举办了115个公益项目、300余场活动,有效实现社会组织与居民需求的“无缝对接”。\n我们在实践中摸索,完善中创新。展望未来,长寿社会组织联合会也将不断探索,下一步的计划是“请进来、走出去”,长寿社会组织联合会将联合其他街镇乃至其他区县的社会组织共同协作,打破社会组织属地化壁垒,提升他们视野和竞争力,因地制宜的研发出服务社区的公益项目,让公益的力量势如破竹,为打造精彩长寿、善美普陀和公益上海添砖加瓦。",
"cover": {
"name": "N14.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N14.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N14.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N14.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "APPLY",
"public_vote": 3346,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海市普陀区长寿社会组织联合会"
},
"voted": false
},
{
"case_id": "419527762110595072",
"code": "N04",
"title": "上海震旦教育发展基金会",
"detail": "上海震旦教育发展基金会成立于2015年,秉持弘扬公益精神,积极回报社会的办会宗旨,努力汇集各方力量、传递正能量。\r\n基金会主要以四项特色工作为主:\r\n(一)携手各方力量,关爱特殊人群\r\n震旦教育基金会已成功主办、协办多项全国性、市级助残公益活动。关爱自闭症特殊群体活动,主题鲜明、内容丰富、参与者众、受益面广。\r\n(二)共襄慈善良业,回报社区民众\r\n震旦教育基金会为社区建设作贡献。为黄浦社区加装电梯工程中做配套绿化改建项目,为居民提供了优美的绿化环境。\r\n基金会每年中国传统节日前向街道、镇、村老人、残疾人送去温暖与爱心。\r\n2020年疫情期间,震旦教育基金会为黄浦区各大医院、派出所等总共58家单位,送去价值28万余元的哈根达斯蛋糕,向日夜坚守在疫情防控第一线的工作人员送去慰问与祝福,为抗击疫情助力加油!\r\n(三)引领环保时尚,共倡整洁家园\r\n震旦教育基金会联合公益机构举办了多场大型环保艺术展,在浦东科技馆的“艺起减塑”历时90天,共接待观众逾13万人次,使参与者对环保、减塑、有了感性的认识,也认识到环保是我们全人类的职责与使命。\r\n(四)共同奉献爱心,基金奖励优秀\r\n震旦师生积极为抗疫捐款,把参与慈善公益事业作为每个人的社会责任与使命。在疫情之中,基金会表彰震旦职业学院17名驰援武汉的毕业生,给予每人2万元的奖励,鼓励和表彰他们无私无畏,挺身而出把人民生命安全放在首位的大无畏精神。\r\n震旦教育基金会近年来开展了50多项公益项目活动,受益人数16万余人次。震旦教育基金会将不忘初心,凝心聚力,坚毅前行,吸纳更多热心于慈善事业的有识之士参与,做更多造福于社会的公益活动。",
"cover": {
"name": "N04.jpg",
"url": "http://gyzs.onwall.cn/2021gyzs/N04.jpg",
"uid": 1564543218846,
"status": "success"
},
"video": {
"name": "N04.mp4",
"url": "http://gyzs.onwall.cn/2021gyzs/N04.mp4",
"uid": 1564543218846,
"status": "success"
},
"status": "REFUSE",
"public_vote": 4125,
"score": 0,
"award": null,
"optr_date": "2021-12-31T15:50:00.547Z",
"corp": {
"name": "上海震旦教育发展基金会"
},
"voted": false
},
]
export default data
\ No newline at end of file
<template>
<router-view></router-view>
</template>
<script>
export default {
data () {
return {
}
},
mounted () {
},
methods: {
}
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App1</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
import { createApp } from 'vue';
import App from './App.vue';
// import store, { key } from './store/index';
import router from './router';
createApp(App).use(router).mount('#app');
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory('/index.html'),
routes: [
{
path: '/',
name: 'mono2',
component: () => import('./views/index.vue'),
},
],
});
export default router;
<template>
<div class="">456</div>
</template>
<script>
export default {
data () {
return {
}
},
mounted () {
},
methods: {
}
}
</script>
<style lang="less" scoped>
</style>
<template>
<router-view></router-view>
</template>
<script>
export default {
data () {
return {
}
},
mounted () {
},
methods: {
}
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App1</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
import { createApp } from 'vue';
import App from './App.vue';
// import store, { key } from './store/index';
import router from './router';
createApp(App).use(router).mount('#app');
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory('/index.html'),
routes: [
{
path: '/',
name: 'mono2',
component: () => import('./views/index.vue'),
},
],
});
export default router;
<template>
<div class="">123</div>
</template>
<script>
export default {
data () {
return {
}
},
mounted () {
},
methods: {
}
}
</script>
<style lang="less" scoped>
</style>
export default [{
path: '/about',
component: () => import('@/views/about.vue'),
meta: {
title: 'about'
}
}, {
path: '/record',
component: () => import('@/views/record.vue'),
meta: {
title: 'record'
}
}];
/*
* @Date: 2022-05-26 13:57:28
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-29 21:36:59
* @FilePath: /tswj/src/router.js
* @Description: 文件描述
*/
import { createRouter, createWebHashHistory } from 'vue-router';
import RootRoute from './route.js';
import asyncRoutesArr from "./mock/routes"
import generateRoutes from './utils/generateRoute'
// TAG: 路由配置表
/**
* 把项目独有的路由配置到相应的路径,默认路由文件只放公用部分
* 但是 vue 文件内容还是要事先准备好
*/
const modules = import.meta.globEager('@/router/routes/modules/**/*.js'); // Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块
const routeModuleList = [];
Object.keys(modules).forEach((key) => {
const mod = modules[key].default || {};
const modList = Array.isArray(mod) ? [...mod] : [mod];
routeModuleList.push(...modList);
});
// 创建路由实例并传递 `routes` 配置
const router = createRouter({
history: createWebHashHistory('/index.html'),
routes: [...RootRoute, ...routeModuleList]
});
// TAG: 动态生成路由
/**
* generateRoute 负责把后台返回数据拼接成项目需要的路由结构,动态添加到路由表里面
*/
router.beforeEach((to, from, next) => {
// 使用404为中转页面,避免动态路由没有渲染出来,控制台报警告问题
if (to.path == '/404' && to.redirectedFrom != undefined) {
// 模拟异步操作
setTimeout(() => {
if (!asyncRoutesArr.length) return; // 没有动态路由避免报错
const arr = generateRoutes(asyncRoutesArr); // 在路由守卫处生成,避免有子路由时刷新白屏问题。
arr.forEach(item => {
router.addRoute(item) // 新增路由
})
// 重写被404覆盖路由信息
next({ ...to.redirectedFrom, replace: true });
}, 1000);
} else {
next()
}
})
router.afterEach(() => {
// console.warn(to);
// console.warn(wx);
// share(to)
})
export default router;
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-07 18:03:50
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-08 19:35:53
* @FilePath: /tswj/src/router/methods/goToVideoDetail.ts
* @Description:
*/
// import { useRouter } from 'vue-router';
import $router from '@/router';
/**
* 路由跳转视频详情页
* @param prod_id 作品ID
* @param perf_id 表演者ID
* @param book_id 书籍ID
* @param type 特殊标识,判断入口 为keepAlive使用
*/
const fn = ({
prod_id,
perf_id,
book_id,
type,
}: {
prod_id: string;
perf_id: string;
book_id: string;
type?: string;
}): void => {
$router.push({
path: '/client/videoDetail',
query: {
prod_id,
perf_id,
book_id,
type,
},
});
};
export default fn;
const index = [{
path: '/auth',
name: '授权跳转页',
component: () => import('@/views/auth.vue'),
meta: {
title: '微信授权'
},
children: []
}]
export default index;
/*
* @Date: 2022-06-15 17:09:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-29 20:09:00
* @FilePath: /tswj/src/router/routes/modules/test/index.js
* @Description: 文件描述
*/
const index = [{
path: '/html2canvas',
name: 'html2canvas',
component: () => import('@/views/html2canvas.vue'),
redirect: '',
meta: {
icon: '',
title: 'DOM转image',
},
children: [],
}, {
path: '/test-slot',
name: 'test-slot',
component: () => import('@/views/test/test-slot.vue'),
redirect: '',
meta: {
icon: '',
title: '测试slot插槽',
},
children: [],
}, { // 配置404为动态路由中转页面
path: '/:pathMatch(.*)*',
redirect: '/404'
}, {
path: '/404',
name: '404',
component: () => import('@/views/test/404.vue'),
meta: {
icon: '',
title: '404',
},
children: [],
}];
export default index;
export default {
defaultPageSize: 10,
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-26 10:08:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-02 22:50:53
* @FilePath: /tswj/src/settings/designSetting.js
* @Description:
*/
import { ref } from 'vue';
import { styleColor } from '@/constant.js';
export const styleObject1 = ref({
backgroundColor: styleColor.baseFontColor,
color: styleColor.baseColor,
borderColor: styleColor.baseColor
})
export const styleObject2 = ref({
backgroundColor: styleColor.baseColor,
color: styleColor.baseFontColor,
borderColor: styleColor.baseColor
})
export const styleObject3 = ref({
// backgroundColor: '#6D97D2',
backgroundColor: '#F4675A',
color: styleColor.baseFontColor,
// borderColor: '#6D97D2'
borderColor: '#F4675A'
})
export const styleObject4 = ref({
backgroundColor: styleColor.baseFontColor,
color: '#713610',
borderColor: '#713610'
})
export const styleObject5 = ref({
backgroundColor: styleColor.baseFontColor,
color: '#FDD347',
borderColor: '#FDD347'
})
export const styleObject6 = ref({
backgroundColor: styleColor.baseFontColor,
color: '#777777',
borderColor: '#777777'
})
export const styleObject7 = ref({
backgroundColor: styleColor.baseFontColor,
color: '#0B3A72',
borderColor: '#0B3A72'
})
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-07 22:46:46
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-08 05:34:56
* @FilePath: /tswj/src/shims-vue.d.ts
* @Description:
*/
declare module '*.vue' {
import type { DefineComponent } from 'vue';
const component: DefineComponent;
export default component;
}
/*
* @Date: 2022-04-18 15:59:42
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 11:30:40
* @FilePath: /tswj/src/store/index.js
* @Description: 文件描述
*/
import { defineStore } from 'pinia';
// import { testStore } from './test'; // 另一个store
import _ from 'lodash';
import { useRouter } from 'vue-router'
export const mainStore = defineStore('main', {
state: () => {
return {
msg: 'Hello world',
count: 0,
auth: false,
comment_num: 0,
video_detail: {},
scrollTop: 0,
scrollTopCollection: 0,
scrollTopLike: 0,
scrollTopPerson: 0,
keepPages: ['default'], // 很坑爹,空值全部都缓存
};
},
getters: {
getKeepPages () {
return this.keepPages
},
// getTestStoreList () {
// return testStore().list // 返回另一个store的值
// }
},
actions: {
changeState (state) {
this.auth = state;
},
changeCommentNum (num) {
this.comment_num = num;
},
changeVideoDetail (v) {
this.video_detail = v;
},
changeScrollTop (v) {
this.scrollTop = v;
},
changeScrollTopCollection (v) {
this.scrollTopCollection = v;
},
changeScrollTopLike (v) {
this.scrollTopLike = v;
},
changeScrollTopPerson (v) {
this.scrollTopPerson = v;
},
changeKeepPages () { // 清空所有缓存,用一个不存在的值覆盖
this.keepPages = ['default'];
},
keepThisPage () { // 新增缓存页
const $router = useRouter();
const page = $router.currentRoute.value.meta.name;
this.keepPages.push(page);
},
removeThisPage () { // 删除缓存页
const $router = useRouter();
const page = $router.currentRoute.value.meta.name;
_.remove(this.keepPages, item => item === page)
}
},
});
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-25 18:34:17
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-22 01:35:44
* @FilePath: /tswj/src/theme-vars.js
* @Description: 修改vant默认表单样式
*/
import { styleColor } from '@/constant.js';
export const loginTheme = {
buttonPrimaryBackground: styleColor.baseColor,
buttonPrimaryBorderColor: styleColor.baseColor,
buttonPrimaryColor: styleColor.baseFontColor,
CellVerticalPadding: '14px'
};
/*
* @Date: 2022-06-20 01:22:50
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 01:23:18
* @FilePath: /tswj/src/composables/useMonitorKeyboard.js
* @Description: 文件描述
*/
/**
* @class 监听虚拟键盘
* @classdesc 监听虚拟键盘弹出隐藏
* @public onEnd 结束监听虚拟键盘
* @public onShow 传递一个回调 监听虚拟键盘弹出
* @public onHidden 传递一个回调 监听虚拟键盘隐藏
*/
class MonitorKeyboard {
constructor() {
this.type = this.IsIA();
this.originalHeight = window.innerHeight;
}
/**
* @function IsIA 获取设备类型
* @param 1 Android 2 iOS
*/
IsIA = () => {
const userAgent = typeof window === 'object' ? window.navigator.userAgent : '';
if (/android/i.test(userAgent)) {
return 1;
} else if (/iPhone|iPod|iPad/i.test(userAgent)) {
return 2;
}
}
// Android系统
onResize = () => {
//键盘弹起与隐藏都会引起窗口的高度发生变化
const resizeHeight = window.innerHeight;
if (this.originalHeight - resizeHeight > 50) {
this.show('Android系统: 软键盘弹出');
} else {
this.hidden('Android系统: 软键盘收起');
}
}
// iOS获取焦点
onFocusin = () => {
this.show('iOS系统:软键盘弹出');
}
// iOS失去焦点
onFocusout = () => {
this.hidden('iOS系统:软键盘收起');
}
/**
* @function onStart 开始监听虚拟键盘
*/
onStart = () => {
if (this.type == 1) {
// 获取窗口的高度
window.addEventListener('resize', this.onResize);
}
if (this.type == 2) {
// iOS系统
window.addEventListener('focusin', this.onFocusin);
window.addEventListener('focusout', this.onFocusout);
}
}
/**
* @function onEnd 结束监听虚拟键盘
*/
onEnd = () => {
if (this.type == 1) {
//获取窗口的高度
window.removeEventListener('resize', this.onResize);
}
if (this.type == 2) {
window.removeEventListener('focusin', this.onFocusin);
window.removeEventListener('focusout', this.onFocusout);
}
}
/**
* @function onShow 传递一个回调函数
* @param 虚拟键盘弹出时触发
*/
onShow = (fn) => {
this.show = fn;
}
/**
* @function onHidden 传递一个回调函数
* @param 虚拟键盘隐藏时触发
*/
onHidden = (fn) => {
this.hidden = fn;
}
}
export default MonitorKeyboard
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-28 10:17:40
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-01-02 18:02:31
* @FilePath: /tswj/src/utils/axios.js
* @Description:
*/
import axios from 'axios';
import router from '@/router';
import qs from 'Qs'
import { strExist } from '@/utils/tools'
// import { parseQueryString } from '@/utils/tools'
axios.defaults.params = {
f: 'voice',
};
/**
* @description 请求拦截器
*/
axios.interceptors.request.use(
config => {
// const url_params = parseQueryString(location.href);
// GET请求默认打上时间戳,避免从缓存中拿数据。
const timestamp = config.method === 'get' ? (new Date()).valueOf() : '';
/**
* POST PHP需要修改数据格式
* 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错
*/
if (config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url)) {
if (qs.stringify(config.data)) {
config.data = qs.stringify(config.data)
}
}
// 绑定默认请求头
config.params = { ...config.params, timestamp }
return config;
},
error => {
// 请求错误处理
return Promise.reject(error);
});
/**
* @description 响应拦截器
*/
axios.interceptors.response.use(
response => {
// 默认显示错误提示
response.data.show = true;
// 判断微信授权状态,进入页面时未授权需要授权跳转
// C/B 授权拼接头特殊标识,openid_x
let prefixAPI = router?.currentRoute.value.href?.indexOf('business') > 0 ? 'b' : 'c';
if (response.data.code === 401) {
// 特殊标识-带此标识报错不显示
response.data.show = false;
/**
* 未授权跳转登录页
* 带着上一个页面的信息, 授权完成后 返回当前页面
*/
router.replace({ path: '/auth', query: { href: location.hash, prefixAPI } });
}
// 拦截B端未登录情况
if (['老师请先登录!', '老师不存在!'].includes(response.data.msg)) { router.replace({ path: '/business/login' }); }
return response;
},
error => {
return Promise.reject(error);
});
export default axios;
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-17 11:34:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 16:31:28
* @FilePath: /tswj/src/utils/generateIcons.js
* @Description: 图标集合
*/
import icon_video from '@images/video.png'
import icon_up from '@images/icon-guanbi@2x.png'
import icon_down from '@images/icon-zhankai@2x.png'
import icon_subscribed from '@images/icon-dingyue01@2x.png'
import icon_unsubscribe from '@images/icon-dingyue02@2x.png'
import no_image from '@images/que-shuju@2x.png'
import icon_avatar from '@images/que-touxiang@2x.png'
import icon_logo from '@images/que-logo@2x.png'
import icon_dianzan1 from '@images/icon-dianzan01@2x.png'
import icon_dianzan2 from '@images/icon-dianzan02@2x.png'
import icon_shoucang1 from '@images/icon-shoucang01@2x.png'
import icon_shoucang2 from '@images/icon-shoucang02@2x.png'
import icon_liuyan from '@images/icon-liuyan@2x.png'
import icon_book from '@images/shu@2x.png'
import icon_me from '@images/icon-my@2x.png'
import icon_home from '@images/icon-home@2x.png'
import icon_rank from '@images/icon-paihang@2x.png'
import icon_ranking1 from '@images/1@2x.png'
import icon_ranking2 from '@images/2@2x.png'
import icon_ranking3 from '@images/3@2x.png'
import icon_flower from '@images/xiaohua@2x.png'
import icon_refuse from '@images/icon-jujue@2x.png'
import icon_apply from '@images/icon-shenhe@2x.png'
import icon_enable from '@images/icon-tongguo@2x.png'
export {
icon_video,
icon_up,
icon_down,
icon_subscribed,
icon_unsubscribe,
no_image,
icon_avatar,
icon_logo,
icon_dianzan1,
icon_dianzan2,
icon_liuyan,
icon_shoucang1,
icon_shoucang2,
icon_book,
icon_me,
icon_home,
icon_rank,
icon_ranking1,
icon_ranking2,
icon_ranking3,
icon_flower,
icon_refuse,
icon_apply,
icon_enable,
}
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-17 11:17:58
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-07-01 14:55:12
* @FilePath: /tswj/src/utils/generateModules.js
* @Description:
*/
import MyButton from '@/components/MyButton/index.vue'
import VideoCard from '@/components/VideoCard/index.vue'
import NoticeOverlay from '@/components/NoticeOverlay/index.vue'
import NoticeOverlayModule from '@/components/NoticeOverlayModule/index.vue'
import DonateBook from '@/components/DonateBook/index.vue'
import ShortcutFixed from '@/components/ShortcutFixed/index.vue'
import BookCard from '@/components/BookCard/index.vue'
import VideoDetail from '@/components/VideoDetail/index.vue'
import DonateBar from '@/components/DonateBar/index.vue'
import DonateFlower from '@/components/DonateFlower/index.vue'
export {
MyButton,
VideoCard,
NoticeOverlay,
NoticeOverlayModule,
DonateBook,
ShortcutFixed,
BookCard,
VideoDetail,
DonateBar,
DonateFlower,
}
/*
* @Date: 2022-05-17 11:26:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-20 14:00:13
* @FilePath: /tswj/src/utils/generatePackage.js
* @Description: 文件描述
*/
import Cookies from 'js-cookie'
import $ from 'jquery'
import _ from 'lodash'
import axios from '@/utils/axios';
import { storeToRefs } from 'pinia'
import { mainStore } from '@/store'
import { Toast, Dialog } from 'vant';
import { wxInfo, hasEllipsis } from '@/utils/tools';
import { useTitle } from '@vueuse/core'
export {
Cookies,
$,
_,
axios,
storeToRefs,
mainStore,
Toast,
Dialog,
wxInfo,
hasEllipsis,
useTitle
}
/*
* @Date: 2022-05-16 17:21:45
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-29 17:00:15
* @FilePath: /tswj/src/utils/generateRoute.js
* @Description: 文件描述
*/
/**
* 根据后台返回的路径,生成页面的组件模版
* @param {*} component
* @returns 模版地址
*/
function loadView(component) {
return () => import(`../views/${component}.vue`)
}
/**
* 生成路由结构
* @param {*} routes
*/
const generateRoutes = (routes) => {
const arr = []
routes.forEach(route => {
const router = {}
const {
path,
redirect,
name,
component,
keepAlive,
meta,
children
} = route
router.path = path
redirect && (router.redirect = redirect)
name && (router.name = name)
router.component = loadView(component)
keepAlive && (router.keepAlive = keepAlive)
meta && (router.meta = meta)
router.children = !Array.isArray(children) || generateRoutes(children);
arr.push(router)
})
return arr
}
export default generateRoutes;
import wx from 'weixin-js-sdk'
import axios from '@/utils/axios';
const fn = (to) => {
// 路由名
let ruleName = location.href.split('#/')[1].split('?')[0];
const icon = 'https://cdn.lifeat.cn/webappgroup/betterLifelogo.png'
const shareInfoMap = {
'client/index': {
title: '童声无界',
desc: '引导页',
icon
},
'client/chooseSchool': {
title: '选择幼儿园',
desc: '引导页',
icon
},
default: {
title: to.name,
desc: window.location.href,
icon
},
}
let infoMap = shareInfoMap[ruleName] ? shareInfoMap[ruleName] : shareInfoMap['default'];
// console.warn(ruleName);
console.warn(infoMap);
console.warn(wx);
console.warn(axios);
}
export default fn
// 这个判断后加的为了减少请求次数,据后端说有次数限制,当需要分享的页面才去请求接口。
// if (shareInfoMap[ruleName]) {
// // request 是封装的请求
// request.post('/wxmp/sign/jsSdk', {
// url: location.href,
// }).then(res => {
// let { timestamp, nonceStr, signature, appId } = res;
// wx.config({
// debug: false,
// appId,
// timestamp,
// nonceStr,
// signature,
// jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData']
// });
// wx.error(function (errres) {
// console.info(errres)
// })
// wx.ready(() => { //需在用户可能点击分享按钮前就先调用
// console.info('ready')
// //分享朋友
// wx.updateAppMessageShareData({
// title: infoMap.title, // 分享标题
// desc: infoMap.desc, // 分享描述
// link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
// imgUrl: infoMap.icon, // 分享图标
// success: function () {
// console.info("成功")
// // 设置成功
// },
// fail: function (erres) {
// console.info('失败:', erres)
// }
// })
// //分享到 朋友圈
// wx.updateTimelineShareData({
// title: infoMap.title, // 分享标题
// link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
// imgUrl: infoMap.icon, // 分享图标
// success: function () {
// console.info("成功")
// // 设置成功
// },
// fail: function (erres) {
// console.info('失败:', erres)
// }
// })
// });
// }).catch(err => {
// console.info('err:', err)
// })
// }
\ No newline at end of file
/*
* @Date: 2022-04-18 15:59:42
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-30 13:54:32
* @FilePath: /tswj/src/utils/tools.js
* @Description: 文件描述
*/
import dayjs from 'dayjs';
// 格式化时间
const formatDate = (date) => {
return dayjs(date).format('YYYY-MM-DD HH:mm');
};
/**
* @description 判断浏览器属于平台
* @returns
*/
const wxInfo = () => {
let u = navigator.userAgent;
let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
let uAgent = navigator.userAgent.toLowerCase();
let isTable = (uAgent.match(/MicroMessenger/i) == 'micromessenger') ? true : false;
return {
isAndroid,
isiOS,
isTable
};
};
/**
* @description 判断多行省略文本
* @param {*} id 目标dom标签
* @returns
*/
const hasEllipsis = (id) => {
let oDiv = document.getElementById(id);
let flag = false;
if (oDiv.scrollHeight > oDiv.clientHeight) {
flag = true
}
return flag
}
/**
* @description 解析URL参数
* @param {*} url
* @returns
*/
const parseQueryString = url => {
var json = {};
var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : [];
arr.forEach(item => {
var tmp = item.split('=');
json[tmp[0]] = tmp[1];
});
return json;
}
/**
* 字符串包含字符数组中字符的状态
* @param {*} array 字符数组
* @param {*} str 字符串
* @returns 包含状态
*/
const strExist = (array, str) => {
const exist = array.filter(arr => {
if (str.indexOf(arr) >= 0) return str;
})
return exist.length > 0
}
export { formatDate, wxInfo, hasEllipsis, parseQueryString, strExist };
import VConsole from 'vconsole';
// const vConsole = new VConsole();
let vConsole = '';
// 或者使用配置参数来初始化,详情见文档
if (+import.meta.env.VITE_CONSOLE) {
vConsole = new VConsole({ theme: 'dark' });
}
export default vConsole
<template>
<div class="">
<iframe id="iframe" :src="src" style="height: 100vh" width="100%" frameborder="0"></iframe>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const $route = useRoute();
const src = ref($route.query.href)
</script>
<script>
import mixin from 'common/mixin';
export default {
mixins: [mixin.init],
data () {
return {
myIframe: null
}
},
mounted () {
},
methods: {
onLoad(frame) {
this.myIframe = frame.contentWindow
}
}
}
</script>
<style lang="less" scoped>
</style>
<template>
<div class="">router test</div>
</template>
<script setup>
</script>
<style lang="less" scoped>
</style>
<template>
<div />
</template>
<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
const $route = useRoute();
onMounted(() => {
// php需要先跳转链接获取openid
/**
* encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
* 该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
* 其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
*/
let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址
// TAG: 开发环境测试数据
const short_url = `/srv/?f=voice&a=openid_${$route.query.prefixAPI}&res=${raw_url}`;
location.href = import.meta.env.DEV
? `${short_url}&input_openid=${import.meta.env.VITE_OPENID}`
: `${short_url}`;
})
</script>
<!--
* @Date: 2022-06-29 15:57:45
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-29 22:04:25
* @FilePath: /tswj/src/views/children-test.vue
* @Description: 文件描述
-->
<template>
<div class="">test</div>
</template>
<script setup>
</script>
<style lang="less" scoped>
</style>
<template>
<div>
<!-- 生成图片后隐藏原始结构 -->
<div v-if="flag" ref="canvasRef" style="width: 200px; height: 200px;">
<img :src="logo_image" alt="">
</div>
<div v-if="imgUrl">
<img :src="imgUrl" alt="" crossOrigin="anonymous" style="width: 300px; height: 300px;">
</div>
<div>
<div @click="createImage">合成图片</div>
<div @click="btn">child</div>
</div>
<router-view />
</div>
</template>
<script setup>
import logo_image from '@images/logo@3x.png'
</script>
<script>
import mixin from 'common/mixin';
import html2canvas from "html2canvas";
export default {
mixins: [mixin.init],
data() {
return {
imgUrl: "",
flag: true
}
},
mounted() {
},
methods: {
createImage() {
this.$nextTick(() => {
// 获取要生成图片的 DOM 元素
let canvasDom = this.$refs.canvasRef;
const options = {
// backgroundColor: '#ffffff',
// canvas: canvas,
useCORS: true,//配置允许跨域
// scale:1,
// windowWidth: document.body.scrollWidth,
// windowHeight: document.body.scrollHeight,
// x: 0,
// y: window.pageYOffset,
// allowTaint: true,
// background: "#ffffff", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的
dpi: 300 // 处理模糊问题
};
// console.log("获取指定的宽高", width, height, canvas);
html2canvas(canvasDom, options)
.then(canvas => {
try {
// 生成图片地址
this.imgUrl = canvas.toDataURL("image/png");
// console.log("canvas.toDataURL('image/png')", this.imgUrl);
this.flag = false;
} catch (e) {
alert("图片跨域,保存失败");
}
})
.catch(error => {
console.error("绘制失败");
console.error(error);
});
});
},
btn () {
this.$router.push({
path: '/image/children',
query: {
abc: 1
}
})
}
}
}
</script>
<style lang="less" scoped>
.m-html2canvas {
display: flex;
}
.m-canvasRef {
width: 500px;
height: 500px;
/* border: 1px solid red; */
/* box-sizing: border-box; */
box-shadow: 10px 10px 5px #888888;
}
.m-imageList {
width: 500px;
height: calc(500px / 3);
}
img {
width: 100%;
height: 100%;
float: left;
}
.m-showImage {
margin-left: 50px;
background: red;
width: 500px;
height: 500px;
}
.m-btn {
margin-left: 50px;
}
</style>
<template>
<div />
</template>
<script setup>
</script>
<style lang="less" scoped>
</style>
<!--
* @Date: 2024-02-01 09:45:51
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-02-01 09:47:13
* @FilePath: /my-record/src/views/record.vue
* @Description: 文件描述
-->
<style>
body {
word-wrap: break-word;
background: #f5f5f5 center top no-repeat;
background-size: auto 680px;
}
pre {
white-space: pre-wrap;
}
a {
text-decoration: none;
color: #06c;
}
a:hover {
color: #f00;
}
.main {
max-width: 700px;
margin: 0 auto;
padding-bottom: 80px;
}
.mainBox {
margin-top: 12px;
padding: 12px;
border-radius: 6px;
background: #fff;
--border: 1px solid #0b1;
box-shadow: 2px 2px 3px #aaa;
}
.btns button {
display: inline-block;
cursor: pointer;
border: none;
border-radius: 3px;
background: #0b1;
color: #fff;
padding: 0 15px;
margin: 3px 20px 3px 0;
line-height: 36px;
height: 36px;
overflow: hidden;
vertical-align: middle;
}
.btns button:active {
background: #0a1;
}
.pd {
padding: 0 0 6px 0;
}
.lb {
display: inline-block;
vertical-align: middle;
background: #00940e;
color: #fff;
font-size: 14px;
padding: 2px 8px;
border-radius: 99px;
}
</style>
<template>
<div class="main">
<slot name="top"></slot>
<div class="mainBox">
<div class="pd">
类型:{{ type }}
<span style="margin: 0 20px">
比特率: <input type="text" v-model="bitRate" style="width: 60px" /> kbps
</span>
采样率: <input type="text" v-model="sampleRate" style="width: 60px" /> hz
</div>
<div class="btns">
<div>
<button @click="recOpen">打开录音,请求权限</button>
<button @click="recClose">关闭录音,释放资源</button>
</div>
<button @click="recStart">录制</button>
<button @click="recStop" style="margin-right: 80px">停止</button>
<span style="display: inline-block">
<button @click="recPause">暂停</button>
<button @click="recResume">继续</button>
</span>
<span style="display: inline-block">
<button @click="recPlayLast">播放</button>
<button @click="recUploadLast">上传</button>
<button @click="recDownLast">本地下载</button>
</span>
</div>
</div>
<div class="mainBox">
<div
style="
height: 100px;
width: 300px;
border: 1px solid #ccc;
box-sizing: border-box;
display: inline-block;
vertical-align: bottom;
"
class="ctrlProcessWave"
></div>
<div
style="
height: 40px;
width: 300px;
display: inline-block;
background: #999;
position: relative;
vertical-align: bottom;
"
>
<div
class="ctrlProcessX"
style="height: 40px; background: #0b1; position: absolute"
:style="{ width: powerLevel + '%' }"
></div>
<div
class="ctrlProcessT"
style="padding-left: 50px; line-height: 40px; position: relative"
>
{{ durationTxt + "/" + powerLevel }}
</div>
</div>
</div>
<div class="mainBox">
<!-- 放一个 <audio ></audio> 播放器,标签名字大写,阻止uniapp里面乱编译 -->
<AUDIO ref="LogAudioPlayer" style="width: 100%"></AUDIO>
<div class="mainLog">
<div v-for="obj in logs" :key="obj.idx">
<div
:style="{
color: obj.color == 1 ? 'red' : obj.color == 2 ? 'green' : obj.color,
}"
>
<!-- <template v-once> 在v-for里存在的bug,参考:https://v2ex.com/t/625317 -->
<span v-once>[{{ getTime() }}]</span><span v-html="obj.msg" />
<template v-if="obj.res">
{{ intp(obj.res.rec.set.bitRate, 3) }}kbps
{{ intp(obj.res.rec.set.sampleRate, 5) }}hz 编码{{
intp(obj.res.blob.size, 6)
}}b [{{ obj.res.rec.set.type }}]{{ obj.res.durationTxt }}ms
<button @click="recdown(obj.idx)">下载</button>
<button @click="recplay(obj.idx)">播放</button>
<span v-html="obj.playMsg"></span>
<span v-if="obj.down">
<span style="color: red">{{ obj.down }}</span>
没弹下载?试一下链接或复制文本<button @click="recdown64(obj.idx)">
生成Base64文本
</button>
<textarea v-if="obj.down64Val" v-model="obj.down64Val"></textarea>
</span>
</template>
</div>
</div>
</div>
</div>
<slot name="bottom"></slot>
</div>
</template>
<script>
//加载必须要的core,demo简化起见采用的直接加载类库,实际使用时应当采用异步按需加载
import Recorder from "recorder-core";
//需要使用到的音频格式编码引擎的js文件统统加载进来,这些引擎文件会比较大
import "recorder-core/src/engine/mp3";
import "recorder-core/src/engine/mp3-engine";
//可选的扩展
import "recorder-core/src/extensions/waveview";
export default {
data() {
return {
type: "mp3",
bitRate: 16,
sampleRate: 16000,
duration: 0,
durationTxt: "0",
powerLevel: 0,
logs: [],
};
},
created: function () {
this.Rec = Recorder;
},
methods: {
recOpen: function () {
var This = this;
var rec = (this.rec = Recorder({
type: This.type,
bitRate: +This.bitRate,
sampleRate: +This.sampleRate,
onProcess: function (buffers, powerLevel, duration, sampleRate) {
This.duration = duration;
This.durationTxt = This.formatMs(duration, 1);
This.powerLevel = powerLevel;
This.wave.input(buffers[buffers.length - 1], powerLevel, sampleRate);
},
}));
rec.open(
function () {
This.reclog(
"已打开:" + This.type + " " + This.sampleRate + "hz " + This.bitRate + "kbps",
2
);
This.wave = Recorder.WaveView({ elem: ".ctrlProcessWave" });
},
function (msg, isUserNotAllow) {
This.reclog((isUserNotAllow ? "UserNotAllow," : "") + "打开失败:" + msg, 1);
}
);
},
recClose: function () {
var rec = this.rec;
this.rec = null;
if (rec) {
rec.close();
this.reclog("已关闭");
} else {
this.reclog("未打开录音", 1);
}
},
recStart: function () {
if (!this.rec || !Recorder.IsOpen()) {
this.reclog("未打开录音", 1);
return;
}
this.rec.start();
var set = this.rec.set;
this.reclog(
"录制中:" + set.type + " " + set.sampleRate + "hz " + set.bitRate + "kbps"
);
},
recPause: function () {
if (this.rec && Recorder.IsOpen()) {
this.rec.pause();
} else {
this.reclog("未打开录音", 1);
}
},
recResume: function () {
if (this.rec && Recorder.IsOpen()) {
this.rec.resume();
} else {
this.reclog("未打开录音", 1);
}
},
recStop: function () {
if (!(this.rec && Recorder.IsOpen())) {
This.reclog("未打开录音", 1);
return;
}
var This = this;
var rec = This.rec;
rec.stop(
function (blob, duration) {
This.reclog("已录制:", "", {
blob: blob,
duration: duration,
durationTxt: This.formatMs(duration),
rec: rec,
});
},
function (s) {
This.reclog("录音失败:" + s, 1);
}
);
},
recPlayLast: function () {
if (!this.recLogLast) {
this.reclog("请先录音,然后停止后再播放", 1);
return;
}
this.recplay(this.recLogLast.idx);
},
recUploadLast: function () {
if (!this.recLogLast) {
this.reclog("请先录音,然后停止后再上传", 1);
return;
}
var This = this;
var blob = this.recLogLast.res.blob;
//本例子假设使用原始XMLHttpRequest请求方式,实际使用中自行调整为自己的请求方式
//录音结束时拿到了blob文件对象,可以用FileReader读取出内容,或者用FormData上传
var api = "https://xx.xx/test_request";
var onreadystatechange = function (title) {
return function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
This.reclog(title + "上传成功", 2);
} else {
This.reclog(
title +
"没有完成上传,演示上传地址无需关注上传结果,只要浏览器控制台内Network面板内看到的请求数据结构是预期的就ok了。",
"#d8c1a0"
);
console.error(title + "上传失败", xhr.status, xhr.responseText);
}
}
};
};
This.reclog("开始上传到" + api + ",请求稍后...", "#f60");
/***方式一:将blob文件转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传***/
var reader = new FileReader();
reader.onloadend = function () {
var postData = "";
postData += "mime=" + encodeURIComponent(blob.type); //告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
postData +=
"&upfile_b64=" +
encodeURIComponent((/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result) || [])[1]); //录音文件内容,后端进行base64解码成二进制
//...其他表单参数
var xhr = new XMLHttpRequest();
xhr.open("POST", api);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = onreadystatechange("上传方式一【Base64】");
xhr.send(postData);
};
reader.readAsDataURL(blob);
/***方式二:使用FormData用multipart/form-data表单上传文件***/
var form = new FormData();
form.append("upfile", blob, "recorder.mp3"); //和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3
//...其他表单参数
var xhr = new XMLHttpRequest();
xhr.open("POST", api);
xhr.onreadystatechange = onreadystatechange("上传方式二【FormData】");
xhr.send(form);
},
recDownLast: function () {
if (!this.recLogLast) {
this.reclog("请先录音,然后停止后再下载", 1);
return;
}
this.recdown(this.recLogLast.idx);
},
reclog: function (msg, color, res) {
var obj = {
idx: this.logs.length,
msg: msg,
color: color,
res: res,
playMsg: "",
down: 0,
down64Val: "",
};
if (res && res.blob) {
this.recLogLast = obj;
}
this.logs.splice(0, 0, obj);
},
recplay: function (idx) {
var This = this;
var o = this.logs[this.logs.length - idx - 1];
o.play = (o.play || 0) + 1;
var logmsg = function (msg) {
o.playMsg =
'<span style="color:green">' + o.play + "</span> " + This.getTime() + " " + msg;
};
logmsg("");
var audio = this.$refs.LogAudioPlayer;
audio.controls = true;
if (!(audio.ended || audio.paused)) {
audio.pause();
}
audio.onerror = function (e) {
logmsg(
'<span style="color:red">播放失败[' +
audio.error.code +
"]" +
audio.error.message +
"</span>"
);
};
audio.src = (window.URL || webkitURL).createObjectURL(o.res.blob);
audio.play();
},
recdown: function (idx) {
var This = this;
var o = this.logs[this.logs.length - idx - 1];
o.down = (o.down || 0) + 1;
o = o.res;
var name =
"rec-" +
o.duration +
"ms-" +
(o.rec.set.bitRate || "-") +
"kbps-" +
(o.rec.set.sampleRate || "-") +
"hz." +
(o.rec.set.type || (/\w+$/.exec(o.blob.type) || [])[0] || "unknown");
var downA = document.createElement("A");
downA.href = (window.URL || webkitURL).createObjectURL(o.blob);
downA.download = name;
downA.click();
},
recdown64: function (idx) {
var This = this;
var o = this.logs[this.logs.length - idx - 1];
var reader = new FileReader();
reader.onloadend = function () {
o.down64Val = reader.result;
};
reader.readAsDataURL(o.res.blob);
},
getTime: function () {
var now = new Date();
var t =
("0" + now.getHours()).substr(-2) +
":" +
("0" + now.getMinutes()).substr(-2) +
":" +
("0" + now.getSeconds()).substr(-2);
return t;
},
formatMs: function (ms, all) {
var ss = ms % 1000;
ms = (ms - ss) / 1000;
var s = ms % 60;
ms = (ms - s) / 60;
var m = ms % 60;
ms = (ms - m) / 60;
var h = ms;
var t =
(h ? h + ":" : "") +
(all || h + m ? ("0" + m).substr(-2) + ":" : "") +
(all || h + m + s ? ("0" + s).substr(-2) + "″" : "") +
("00" + ss).substr(-3);
return t;
},
intp: function (s, len) {
s = s == null ? "-" : s + "";
if (s.length >= len) return s;
return ("_______" + s).substr(-len);
},
},
};
</script>
{
"compilerOptions": {
/* 基本选项 */
"target": "esnext", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "CommonJS", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"lib": [ // 指定要包含在编译中的库文件
"esnext",
"dom",
"dom.iterable",
"scripthost"
],
"allowJs": true, // 允许编译 javascript 文件
// "checkJs": true, // 报告 javascript 文件中的错误
"jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
// "declaration": true, // 生成相应的 '.d.ts' 文件
// "sourceMap": true, // 生成相应的 '.map' 文件
// "outFile": "./", // 将输出文件合并为一个文件
"outDir": "./", // 指定输出目录
// "rootDir": "./", // 用来控制输出目录结构 --outDir.
"removeComments": true, // 删除编译后的所有的注释
// "noEmit": true, // 不生成输出文件
"importHelpers": true, // tslib 导入辅助工具函数
"isolatedModules": false, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似)
/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
// "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
// "strictNullChecks": true, // 启用严格的 null 检查
// "noImplicitThis": true, // this 表达式值为 any 类型的时候,生成一个错误
// "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch case 语句贯穿)
/* 模块解析选项 */
"moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"baseUrl": ".", // 用于解析非相对模块名称的基目录
"paths": { // 模块名到基于 baseUrl 的路径映射的列表
"@/*": [
"src/*"
]
},
// "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
// "typeRoots": [], // 包含类型声明的文件列表
"types": [ // 需要包含的类型声明文件名列表
// "webpack-env",
"vite/client",
"lodash",
"moment",
"node",
"jquery",
],
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
/* Source Map Options */
// "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
// "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
// "inlineSourceMap": true, // 生成单个 sourcemaps 文件,而不是将 sourcemaps 生成不同的文件
// "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap --sourceMap 属性
/* 其他选项 */
// "experimentalDecorators": true, // 启用装饰器
// "emitDecoratorMetadata": true, // 为装饰器提供元数据的支持
"esModuleInterop": true, // 可以在es6中导入commonjs
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
],
"vueCompilerOptions": {
"target": 2,
"experimentalSuppressInvalidJsxElementTypeErrors": true
}
}
{
"defaultSeverity": "warning",
"extends": [
"tslint:recommended"
],
"linterOptions": {
"exclude": [
"node_modules/**"
]
},
"rules": {
"quotemark": [
true,
"single"
],
"indent": [
true,
"spaces",
2
],
"interface-name": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-consecutive-blank-lines": false,
"no-console": true
}
}
/*
* @Date: 2022-06-13 10:39:44
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 10:41:43
* @FilePath: /tswj/typings/index.d.ts
* @Description: 文件描述
*/
export {};
// => 全局类型声明
declare global {
interface Window {
_hmt: any;
wx: any;
AlipayJSBridge: any;
}
namespace GD {
interface BaseResponse<T = any> {
code: number;
data: T;
msg: string;
page: {
pageNo: number;
pageSize: number;
pages: number;
total: number;
};
}
}
}
// const response = GD.BaseResponse<{name: string}>
import vue from '@vitejs/plugin-vue';
import dynamicImport from 'vite-plugin-dynamic-import';
// import legacy from '@vitejs/plugin-legacy';
// import styleImport, { VantResolve } from 'vite-plugin-style-import';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import { defineConfig, loadEnv } from 'vite';
import { createProxy } from './build/proxy'
import DefineOptions from 'unplugin-vue-define-options/vite';
import AutoImport from 'unplugin-auto-import/vite';
import postcsspxtoviewport from 'postcss-px-to-viewport'
var path = require('path');
const fs = require('fs');
export default ({ command, mode }) => {
const root = process.cwd();
const viteEnv = loadEnv(mode, root);
// let isProd = (command === 'serve'); // 情景配置是否为开发模式 serve 或 build
return defineConfig({
// root: '',
// root: './src/packages', // 多页面应用配置入口根目录
base: viteEnv.VITE_BASE, // 开发或生产环境服务的公共基础路径。
// base: isProd ? '/' : '/f/voice/', // 开发或生产环境服务的公共基础路径。
// mode: '', // 在配置中指明将会把 serve 和 build 时的模式 都 覆盖掉。也可以通过命令行 --mode 选项来重写。
// define: '', // 定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换。
plugins: [ // 将要用到的插件数组。Falsy 虚值的插件将被忽略,插件数组将被扁平化(flatten)。查看 插件 API 获取 Vite 插件的更多细节。
vue(),
Components({
resolvers: [VantResolver()],
}),
// styleImport({
// resolves: [VantResolve()],
// libs: [
// {
// libraryName: 'vant',
// esModule: true,
// resolveStyle: name => `../es/${name}/style`
// }
// ]
// }), // 按需引入 vant 位置报错问题
dynamicImport(), // 增强 Vite 内置的 dynamic import, 支持在 import() 中使用别名
// legacy({
// targets: ['defaults', 'not IE 11']
// }), // Vite 的默认旧版浏览器支持时提供此插件本机ESM的支持。
DefineOptions(), // TAG: 插件来对组件名进行注册的, 解决setup没法写name的问题
AutoImport({ // API 自动导入
// 可以自定义文件生成的位置,默认是根目录下,使用ts的建议放src目录下
dts: 'src/auto-imports.d.ts',
imports: ['vue', 'vue-router'],
// 解决eslint报错问题
eslintrc: {
enabled: true
}
}),
],
publicDir: 'public', // 作为静态资源服务的文件夹。这个目录中的文件会在开发中被服务于 /,在开发模式时,会被拷贝到 outDir 的根目录,并没有转换,永远只是复制到这里。该值可以是文件系统的绝对路径,也可以是相对于项目的根目录路径。
// cacheDir: '', // 存储缓存文件的目录。此目录下会存储预打包的依赖项或 vite 生成的某些缓存文件,使用缓存可以提高性能。如需重新生成缓存文件,你可以使用 --force 命令行选项或手动删除目录。此选项的值可以是文件的绝对路径,也可以是以项目根目录为基准的相对路径。
resolve: {
alias: { // 将会被传递到 @rollup/plugin-alias 作为 entries 的选项。也可以是一个对象,或一个 { find, replacement } 的数组. 当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会被原封不动地使用,因此无法被正常解析。 更高级的自定义解析方法可以通过 插件 实现。
"@": path.resolve(__dirname, "src"),
"@components": path.resolve(__dirname, "src/components"),
"@composables": path.resolve(__dirname, "src/composables"),
"@utils": path.resolve(__dirname, "src/utils"),
"@images": path.resolve(__dirname, "src/assets/images"),
"@css": path.resolve(__dirname, "src/assets/css"),
"@mock": path.resolve(__dirname, "src/assets/mock"),
"common": path.resolve(__dirname, "src/common"),
},
// dedupe: [''], // 如果你在你的应用程序中有相同依赖的副本(比如 monorepos),使用这个选项来强制 Vite 总是将列出的依赖关系解析到相同的副本(从项目根目录)。
// conditions: [''], // 在解析包的 情景导出 时允许的附加条件。
// mainFields: [''], // package.json 中,在解析包的入口点时尝试的字段列表。注意,这比从 exports 字段解析的情景导出优先级低:如果一个入口点从 exports 成功解析,主字段将被忽略。
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], // 导入时想要省略的扩展名列表。注意,不 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会干扰 IDE 和类型支持。
},
css: {
modules: '', // 配置 CSS modules 的行为。选项将被传递给 postcss-modules。
postcss: { // 内联的 PostCSS 配置(格式同 postcss.config.js),或者一个(默认基于项目根目录的)自定义的 PostCSS 配置路径。其路径搜索是通过 postcss-load-config 实现的。 注意,如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源。
plugins: [
postcsspxtoviewport({
unitToConvert: 'px', // 要转化的单位
viewportWidth: 375, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否转换后直接更换属性值
// exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
exclude: [],
landscape: false // 是否处理横屏情况
})
]
},
preprocessorOptions: {
less: {
javascriptEnabled: true,
additionalData: `@import "${path.resolve(__dirname, 'src/assets/styles/base.less')}";`
}
} // 指定传递给 CSS 预处理器的选项。
},
// json: {
// namedExports: true, // 是否支持从 .json 文件中进行按名导入。
// stringify: false, // 若设置为 true,导入的 JSON 会被转换为 export default JSON.parse("...") 会比转译成对象字面量性能更好,尤其是当 JSON 文件较大的时候。 开启此项,则会禁用按名导入。
// },
// esbuild: false, //
// assetsInclude: '', // 指定其他文件类型作为静态资源处理
logLevel: 'info', // 调整控制台输出的级别,默认为 'info'。
// clearScreen: true, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息。命令行模式下请通过 --clearScreen false 设置。
server: {
host: '0.0.0.0',
port: viteEnv.VITE_PORT, // 本地服务端口
// strictPort: true, // 设为true时若端口已被占用则会直接退出, 而不是尝试下一个可用端口
https: {
key: fs.readFileSync(path.resolve(__dirname, 'keys/localhost+2-key.pem')),
cert: fs.readFileSync(path.resolve(__dirname, 'keys/localhost+2.pem')),
},
// open: false, // 在服务器启动时自动在浏览器中打开应用程序. 当此值为字符串时, 会被当作URL的路径名.
// proxy: { // 代理
// '/srv/': {
// // target: 'http://voice.onwall.cn',
// target: viteEnv.VITE_PROXY_TARGET,
// changeOrigin: true,
// // rewrite: (path) => path.replace(/^\/api/, '')
// },
// },
proxy: createProxy(viteEnv.VITE_PROXY_PREFIX, viteEnv.VITE_PROXY_TARGET),
// cors: '', // 为开发服务器配置 CORS。默认启用并允许任何源,传递一个 选项对象 来调整行为或设为 false 表示禁用。
// force: '', // 设置为 true 强制使依赖预构建。
// hmr: '', // 禁用或配置 HMR 连接(用于 HMR websocket 必须使用不同的 http 服务器地址的情况)。 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层。
// watch: '', // 传递给 chokidar 的文件系统监视器选项。
},
build: {
// outDir: 'voice', // 指定输出路径(相对于项目根目录).
outDir: viteEnv.VITE_OUTDIR, // 指定输出路径(相对于项目根目录).
assetsDir: 'static',
rollupOptions: {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
},
input: { // 多页面应用模式, 打包时配置,运行配置要处理root
main: path.resolve(__dirname, 'index.html'),
// mono1: path.resolve(__dirname, 'src/packages/mono1/index.html'),
// mono2: path.resolve(__dirname, 'src/packages/mono2/index.html'),
}
},
},
optimizeDeps: {
// entries: '',
// exclude: [],
include: ['jquery', 'lodash', 'moment', 'axios', 'pinia', 'vue-router', 'vant'], // 默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
// keepNames: false, // 打包器有时需要重命名符号以避免冲突。 设置此项为 true 可以在函数和类上保留 name 属性。 若想获取更多详情,请参阅 keepNames
}
});
};
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.