commit dbf485e0d5100d3b6433be070de2fb912582a9bb Author: 梁泽军 <5654792+tcubic21@user.noreply.gitee.com> Date: Fri Mar 7 10:31:57 2025 +0800 初始化 diff --git a/.env.development.example b/.env.development.example new file mode 100644 index 0000000..c26c7fb --- /dev/null +++ b/.env.development.example @@ -0,0 +1,3 @@ + +# 请求域名 +VITE_APP_BASE_URL='' \ No newline at end of file diff --git a/.env.production.example b/.env.production.example new file mode 100644 index 0000000..c26c7fb --- /dev/null +++ b/.env.production.example @@ -0,0 +1,3 @@ + +# 请求域名 +VITE_APP_BASE_URL='' \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..86f5ee0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,39 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + ignorePatterns: ['src/uni_modules/'], + extends: [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript/recommended', + '@vue/eslint-config-prettier' + ], + rules: { + 'prettier/prettier': [ + 'warn', + { + semi: false, + singleQuote: true, + printWidth: 100, + proseWrap: 'preserve', + bracketSameLine: false, + endOfLine: 'lf', + tabWidth: 4, + useTabs: false, + trailingComma: 'none' + } + ], + 'vue/multi-word-component-names': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + 'no-undef': 'off', + 'vue/prefer-import-from-vue': 'off', + 'no-prototype-builtins': 'off', + 'prefer-spread': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'off' + }, + globals: {} +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d73bcf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.hbuilderx +# .env +.env.development +.env.production diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..91f12b2 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2a24d8a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.detectIndentation": false, + "editor.tabSize": 4, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" +}, + "css.validate": false, + "less.validate": false, + "scss.validate": false +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..043bc01 --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + +
+ + + diff --git a/initialize.js b/initialize.js new file mode 100644 index 0000000..20fd930 --- /dev/null +++ b/initialize.js @@ -0,0 +1 @@ +const fs = require('fs') const { spawn } = require('child_process') class InitializeItem { static instance = null constructor() { if (InitializeItem.instance) { return InitializeItem.instance } InitializeItem.instance = this } async promptUser(question) { return new Promise((resolve, reject) => { const readline = require('readline') const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) rl.question(question, (res) => { resolve(res) rl.close() }) }) } async shouldInstallDependencies() { const isInstall = await this.promptUser( '是否需要自动帮您安装依赖(y/n):' ) if (isInstall.toLowerCase() === 'y') { return true } else if (isInstall.toLowerCase() === 'n') { return false } else { return this.shouldInstallDependencies() } } async installDependencies() { return new Promise((resolve, reject) => { console.log('开始安装相关依赖...') const command = process.platform === 'win32' ? 'cmd.exe' : 'npm' const args = process.platform === 'win32' ? ['/c', 'npm', 'install'] : ['install'] const installProcess = spawn(command, args) installProcess.stdout.on('data', (data) => { console.log(data.toString()) }) installProcess.stderr.on('data', (data) => { console.error(data.toString()) }) installProcess.on('close', (code) => { if (code !== 0) { reject( new Error( `运行安装依赖命令错误,请查看以下报错信息寻找解决方法: ${error.message}` ) ) } else { console.log('安装依赖成功!') resolve() } }) }) } async copyFile(sourceDir, targetDir) { return new Promise((resolve, reject) => { fs.copyFile(sourceDir, targetDir, (error) => { if (error) { reject(error) throw new Error(`复制文件失败: ${error.message}`) } resolve() }) }) } async writeToFile(filePath, { sourceData, targetData }) { return new Promise((resolve, reject) => { fs.readFile(filePath, 'utf8', (err, data) => { if (err) { console.error('读取文件失败:', err) return } const modifiedData = data.replace(sourceData, targetData) fs.writeFile(filePath, modifiedData, 'utf8', (err) => { if (err) { console.error('写入文件错误:', err) return } resolve() }) }) }) } async initialize(targetVersion) { const currentVersion = process.versions.node if (currentVersion < targetVersion) { throw new Error( `你的当前node版本为(${currentVersion}),需要安装目标版本为 ${targetVersion} 以上!!` ) } const shouldInstall = await this.shouldInstallDependencies() if (shouldInstall) { await this.installDependencies() } await this.copyFile('.env.development.example', '.env.development') await this.copyFile('.env.production.example', '.env.production') const domain = await this.promptUser('请输入您的服务器域名地址:') await this.writeToFile('.env.development', { sourceData: `VITE_APP_BASE_URL=''`, targetData: `VITE_APP_BASE_URL='${domain}'` }) await this.writeToFile('.env.production', { sourceData: `VITE_APP_BASE_URL=''`, targetData: `VITE_APP_BASE_URL='${domain}'` }) require('./scripts/develop'); } static getInstance() { if (!InitializeItem.instance) { InitializeItem.instance = new InitializeItem() } return InitializeItem.instance } } ;(async () => { const initializeItem = InitializeItem.getInstance() try { await initializeItem.initialize('16.16.0') } catch (error) { console.error(error.message) } })() \ No newline at end of file diff --git a/my-release-key.keystore b/my-release-key.keystore new file mode 100644 index 0000000..4448243 Binary files /dev/null and b/my-release-key.keystore differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..8f01c05 --- /dev/null +++ b/package.json @@ -0,0 +1,108 @@ +{ + "name": "uni-preset-vue", + "version": "0.0.0", + "scripts": { + "init": "node initialize.js", + "dev": "node scripts/develop.js", + "dev:app": "uni -p app", + "dev:custom": "uni -p", + "dev:h5": "uni", + "dev:h5:ssr": "uni --ssr", + "dev:mp-alipay": "uni -p mp-alipay", + "dev:mp-baidu": "uni -p mp-baidu", + "dev:mp-kuaishou": "uni -p mp-kuaishou", + "dev:mp-lark": "uni -p mp-lark", + "dev:mp-qq": "uni -p mp-qq", + "dev:mp-toutiao": "uni -p mp-toutiao", + "dev:mp-weixin": "uni -p mp-weixin", + "dev:quickapp-webview": "uni -p quickapp-webview", + "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei", + "dev:quickapp-webview-union": "uni -p quickapp-webview-union", + "build": "node scripts/publish.js", + "build:app": "uni build -p app", + "build:custom": "uni build -p", + "build:h5": "uni build && node scripts/release.mjs -t h5 -o mobile", + "build:h5:ssr": "uni build --ssr", + "build:mp-alipay": "uni build -p mp-alipay", + "build:mp-baidu": "uni build -p mp-baidu", + "build:mp-kuaishou": "uni build -p mp-kuaishou", + "build:mp-lark": "uni build -p mp-lark", + "build:mp-qq": "uni build -p mp-qq", + "build:mp-toutiao": "uni build -p mp-toutiao", + "build:mp-weixin": "uni build -p mp-weixin && node scripts/release.mjs -t mp-weixin -o weapp", + "build:quickapp-webview": "uni build -p quickapp-webview", + "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei", + "build:quickapp-webview-union": "uni build -p quickapp-webview-union", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" + }, + "dependencies": { + "@dcloudio/uni-app": "3.0.0-3070920230324001", + "@dcloudio/uni-app-plus": "3.0.0-3070920230324001", + "@dcloudio/uni-components": "3.0.0-3070920230324001", + "@dcloudio/uni-h5": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-alipay": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-baidu": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-jd": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-kuaishou": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-lark": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-qq": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-toutiao": "3.0.0-3070920230324001", + "@dcloudio/uni-mp-weixin": "3.0.0-3070920230324001", + "@dcloudio/uni-quickapp-webview": "3.0.0-3070920230324001", + "@dcloudio/uni-webview-js": "0.0.3", + "@iktakahiro/markdown-it-katex": "4.0.1", + "@vueuse/core": "9.8.2", + "css-color-function": "1.3.3", + "github-markdown-css": "5.2.0", + "highlight.js": "11.0.0", + "howler": "2.2.4", + "js-mp3": "0.1.0", + "jsonc-parser": "3.2.1", + "js-base64": "^3.7.5", + "lodash-es": "4.17.21", + "markdown-it": "^13.0.1", + "markdown-it-math": "4.1.1", + "markmap-common": "0.15.3", + "markmap-lib": "0.15.4", + "markmap-view": "0.15.4", + "mathjs": "11.8.0", + "pinia": "2.0.20", + "recorder-core": "1.3.23122400", + "uniapp-router-next": "1.2.7", + "uniapp-router-next-zm": "^1.0.1", + "vconsole": "3.14.6", + "vue": "3.2.45", + "vue-i18n": "9.1.9", + "weixin-js-sdk": "1.6.0", + "z-paging": "2.7.6" + }, + "devDependencies": { + "@dcloudio/types": "^3.3.2", + "@dcloudio/uni-automator": "3.0.0-3070920230324001", + "@dcloudio/uni-cli-shared": "3.0.0-3070920230324001", + "@dcloudio/uni-stacktracey": "3.0.0-3070920230324001", + "@dcloudio/vite-plugin-uni": "3.0.0-3070920230324001", + "@rushstack/eslint-patch": "1.1.4", + "@types/howler": "2.2.11", + "@types/lodash-es": "4.17.6", + "@types/markdown-it": "12.2.3", + "@types/node": "18.7.16", + "@vue/eslint-config-prettier": "7.0.0", + "@vue/eslint-config-typescript": "11.0.0", + "autoprefixer": "10.4.8", + "eslint": "8.22.0", + "eslint-plugin-vue": "9.4.0", + "execa": "6.1.0", + "fs-extra": "10.1.0", + "minimist": "1.2.8", + "postcss": "8.4.16", + "postcss-rem-to-responsive-pixel": "5.1.3", + "prettier": "2.7.1", + "sass": "1.54.5", + "tailwindcss": "3.3.2", + "typescript": "4.7.4", + "unplugin-uni-router": "1.2.7", + "vite": "4.1.4", + "weapp-tailwindcss-webpack-plugin": "1.12.8" + } +} diff --git a/scripts/develop.js b/scripts/develop.js new file mode 100644 index 0000000..f8aa332 --- /dev/null +++ b/scripts/develop.js @@ -0,0 +1,105 @@ +const { spawn } = require('child_process') +const readline = require('readline') + +class DevelopClientScript { + constructor() { + if (DevelopClientScript.instance) { + return DevelopClientScript.instance + } + DevelopClientScript.instance = this + } + + promptUser(question) { + return new Promise((resolve) => { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }) + rl.question(question, (res) => { + resolve(res) + rl.close() + }) + }) + } + + async runClient() { + console.error('请选择你需要运行的客户端(回复数字后回车)') + console.error('0.取消') + console.error('1.微信小程序') + console.error('2.公众号或者H5') + const runClientRes = await this.promptUser('请输入运行的客户端:') + switch (runClientRes) { + case '0': + break + case '1': + await this.runNpmScript('dev:mp-weixin') + break + case '2': + await this.runNpmScript('dev:h5') + break + default: + await this.runClient() + break + } + } + + runNpmScript(scriptName) { + return new Promise((resolve, reject) => { + const isWindows = process.platform === 'win32' + const command = isWindows ? 'cmd.exe' : 'npm' + const args = isWindows + ? ['/c', 'npm', 'run', scriptName] + : ['run', scriptName] + + const runProcess = spawn(command, args) + + runProcess.stdout.on('data', (data) => { + console.log(data.toString()) + }) + + runProcess.stderr.on('data', (data) => { + console.error(data.toString()) + }) + + runProcess.on('close', (code) => { + if (code !== 0) { + reject( + new Error( + `运行错误,请查看以下报错信息寻找解决方法: ${error.message}` + ) + ) + } else { + resolve() + } + }) + }) + } + + async run(targetVersion) { + const currentVersion = process.versions.node + + if (currentVersion < targetVersion) { + throw new Error( + `你的当前node版本为(${currentVersion}),需要安装目标版本为 ${targetVersion} 以上!!` + ) + } + + await this.runClient() + } + + static getInstance() { + if (!DevelopClientScript.instance) { + DevelopClientScript.instance = new DevelopClientScript() + } + return DevelopClientScript.instance + } +} + +;(async () => { + const develop = DevelopClientScript.getInstance() + try { + await develop.run('16.16.0') + } catch (error) { + console.error(error.message) + } +})() diff --git a/scripts/publish.js b/scripts/publish.js new file mode 100644 index 0000000..1658328 --- /dev/null +++ b/scripts/publish.js @@ -0,0 +1 @@ +const { spawn } = require('child_process') const readline = require('readline') class PublishClientScript { constructor() { if (PublishClientScript.instance) { return PublishClientScript.instance } PublishClientScript.instance = this } promptUser(question) { return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) rl.question(question, (res) => { resolve(res) rl.close() }) }) } async runClient() { console.error('请选择你需要打包的客户端(回复数字后回车) ') console.error('0.取消') console.error('1.微信小程序') console.error('2.公众号或者H5') const runClientRes = await this.promptUser('请输入打包的客户端:') switch (runClientRes) { case '0': break case '1': await this.runNpmScript('build:mp-weixin') break case '2': await this.runNpmScript('build:h5') break default: await this.runClient() break } } runNpmScript(scriptName) { return new Promise((resolve, reject) => { const isWindows = process.platform === 'win32' const command = isWindows ? 'cmd.exe' : 'npm' const args = isWindows ? ['/c', 'npm', 'run', scriptName] : ['run', scriptName] const runProcess = spawn(command, args) runProcess.stdout.on('data', (data) => { console.log(data.toString()) }) runProcess.stderr.on('data', (data) => { console.error(data.toString()) }) runProcess.on('close', (code) => { if (code !== 0) { reject( new Error( `运行错误,请查看以下报错信息寻找解决方法: ${error.message}` ) ) } else { resolve() } }) }) } async run(targetVersion) { const currentVersion = process.versions.node if (currentVersion < targetVersion) { throw new Error( `你的当前node版本为(${currentVersion}),需要安装目标版本为 ${targetVersion} 以上!!` ) } await this.runClient() } static getInstance() { if (!PublishClientScript.instance) { PublishClientScript.instance = new PublishClientScript() } return PublishClientScript.instance } } ;(async () => { const publish = PublishClientScript.getInstance() try { await publish.run('16.16.0') } catch (error) { console.error(error.message) } })() \ No newline at end of file diff --git a/scripts/release.mjs b/scripts/release.mjs new file mode 100644 index 0000000..cab0f19 --- /dev/null +++ b/scripts/release.mjs @@ -0,0 +1,46 @@ +import path from 'path' +import fsExtra from 'fs-extra' +import minimist from 'minimist' +const { existsSync, remove, copy } = fsExtra +const cwd = process.cwd() +const argv = minimist(process.argv.slice(2), { + alias: { + target: 't', + output: 'o' + } +}) +//打包发布路径,谨慎改动 +const releaseRelativePath = `../public/${argv.output}` +const distPath = path.resolve(cwd, `dist/build/${argv.target}`) +const releasePath = path.resolve(cwd, releaseRelativePath) + +async function build() { + if (existsSync(releasePath)) { + await remove(releasePath) + } + console.log( + `文件正在复制:dist/build/${argv.target} ==> ${releaseRelativePath}` + ) + try { + await copyFile(distPath, releasePath) + } catch (error) { + console.log(`\n ${error}`) + } + console.log( + `文件已复制:dist/build/${argv.target} ==> ${releaseRelativePath}` + ) +} + +function copyFile(sourceDir, targetDir) { + return new Promise((resolve, reject) => { + copy(sourceDir, targetDir, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) +} + +build() diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..01e75b0 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,76 @@ + + diff --git a/src/androidPrivacy.json b/src/androidPrivacy.json new file mode 100644 index 0000000..5fc48cb --- /dev/null +++ b/src/androidPrivacy.json @@ -0,0 +1,40 @@ +{ + "version" : "1", + "prompt" : "template", + "title" : "用户协议及隐私政策", + "message" : "  为了更好保证您的合法权益,请仔细阅读并同意以下协议。
《用户协议》《隐私政策》", + "buttonAccept" : "同意并接受", + "buttonRefuse" : "暂不同意", + "hrefLoader" : "system|default", + "backToExit" : "false", + "second" : { + "title" : "确认提示", + "message" : "  进入应用前,你需先同意《用户协议》《隐私政策》,否则将退出应用。", + "buttonAccept" : "同意并继续", + "buttonRefuse" : "退出应用" + }, + "disagreeMode" : { + "support" : false, + "loadNativePlugins" : false, + "visitorEntry" : true, + "showAlways" : false + }, + "styles" : { + "backgroundColor" : "#ffffff", + "borderRadius" : "5px", + "title" : { + "color" : "#000000", + "fontWeight" : "bolder" + }, + "buttonAccept" : { + "color" : "#000000" + }, + "buttonRefuse" : { + "color" : "#000000", + "backgroundColor" : "#FFB529" + }, + "buttonVisitor" : { + "color" : "#000000" + } + } +} diff --git a/src/api/account.ts b/src/api/account.ts new file mode 100644 index 0000000..ba2aa37 --- /dev/null +++ b/src/api/account.ts @@ -0,0 +1,74 @@ +import request from '@/utils/request' +import { getClient } from '@/utils/client' + +// 登录 +export function mobileLogin(data: Record) { + return request.post({ url: '/login/mobileLogin', data }) +} + +// 账号登录 +export function accountLogin(data: Record) { + return request.post({ url: '/login/accountLogin', data }) +} + +// 邮箱登录 +export function emailLogin(data: any) { + return request.post({ + url: '/login/emailLogin', + data: { ...data, terminal: getClient() } + }) +} + +//邮箱注册 +export function emailRegister(data: any) { + return request.post({ + url: '/login/email/register', + data + }) +} + +//发送邮箱验证码 +export function sendEmailCode(data: any) { + return request.post({ url: '/index/sendEmail', data }) +} + +//注册 +export function register(data: Record) { + return request.post({ url: '/login/register', data }) +} + +//忘记密码 +export function forgotPassword(data: Record) { + return request.post({ url: '/user/forgotPwd', data }) +} + +//邮箱忘记密码 +export function emailForgotPassword(data: Record) { + return request.post({ url: '/user/email/forgotPwd', data }) +} + +//向微信请求code的链接 +export function getWxCodeUrl(data: Record) { + return request.get({ url: '/login/oaCodeUrl', data }) +} + +// 微信小程序登录 + +export function mnpLogin(data: Record) { + return request.post({ url: '/login/mnpLogin', data }) +} + +// APP登录 +export function uninAppLogin(data: Record) { + return request.post({ url: '/login/appLogin', data }) +} + +// 公众号登录 +export function OALogin(data: Record) { + return request.post({ url: '/login/oaLogin', data }) +} + +//获取图形验证码 +export function captcha() { + return request.get({ url: '/login/captcha' }) +} \ No newline at end of file diff --git a/src/api/app.ts b/src/api/app.ts new file mode 100644 index 0000000..9fe596a --- /dev/null +++ b/src/api/app.ts @@ -0,0 +1,48 @@ +import wechatOa from '@/utils/wechat' +import request from '@/utils/request' + +//发送短信 +export function smsSend(data: any) { + return request.post({ url: '/index/sendSms', data: data }) +} + +export function getConfig(data: any) { + return request.get({ url: '/index/config', data }) +} + +export function getPolicy(data: any) { + return request.get({ url: '/index/policy', data: data }) +} + +export function uploadImage(file: any, token?: string) { + return request.uploadFile({ + url: '/upload/image', + filePath: file, + name: 'file', + header: { + token + }, + fileType: 'image' + }) +} + +export function uploadFile( + type: 'image' | 'file' | 'video', + options: Omit, + onProgress?: (progress: number) => void +) { + return request.uploadFile( + { ...options, url: `/upload/${type}`, name: 'file' }, + { + onProgress + } + ) +} + +export function wxJsConfig(data: any) { + return request.get({ url: '/wechat/jsConfig', data }) +} + +export function getMnpQrCode(data: any) { + return request.post({ url: '/wechat/getMnpQrCode', data: data }) +} \ No newline at end of file diff --git a/src/api/chat.ts b/src/api/chat.ts new file mode 100644 index 0000000..576ea98 --- /dev/null +++ b/src/api/chat.ts @@ -0,0 +1,130 @@ +import request, { RequestEventStreamConfig } from '@/utils/request' + +//获取技能列表 +export function getSkillLists(data: any) { + return request.get({ url: '/ai/skill', data }) +} +//获取创作列表 +export function getCreationLists(data: { keyword: string }) { + return request.get({ url: '/ai/creation', data }) +} + +export function getSamplesLists() { + return request.get({ url: '/ai/question' }) +} + +export function questionChat(data: any) { + return request.post({ url: '/chat_records/chat', data }, { isAuth: true }) +} + +// 对话记录 +export function getChatRecord(data: any) { + return request.get({ + url: '/chats/chatRecord', + data + }) +} + +//清空会话 +export function cleanChatRecord(data: any) { + return request.post( + { + url: '/chats/chatClean', + data + }, + { isAuth: true } + ) +} + +//清空会话 +export function delChatRecord(data: any) { + return request.post( + { + url: '/chats/record/del', + data + }, + { isAuth: true } + ) +} + +//收藏 +export function collectChatRecord(data: any) { + return request.post({ url: '/chats/addCollect', data }, { isAuth: true }) +} +//取消收藏 +export function cancelCollectChatRecord(data: any) { + return request.post({ url: '/chats/cancelCollect', data }, { isAuth: true }) +} + +//收藏列表 +export function getCollectChatRecordLists(data: any) { + return request.get({ url: '/chats/listCollect', data }) +} + +export function getCreationDetail(data: any) { + return request.get({ url: '/ai/creation/detail', data }) +} + +export function getSkillDetail(data: any) { + return request.get({ url: '/ai/skill/detail', data }) +} + +export function chatSendText(data: any, config: RequestEventStreamConfig) { + return request.eventStream({ url: '/chats/chatSend', data, method: 'POST' }, config) +} + +// 对话分类列表 +export function getChatCategoryLists(data: any) { + return request.get({ url: '/ai/category', data }) +} + +// 对话分类新增 +export function chatCategoryAdd(data: any) { + return request.post({ url: '/ai/category/add', data }, { isAuth: true }) +} + +// 对话分类编辑 +export function chatCategoryEdit(data: any) { + return request.post({ url: '/ai/category/update', data }, { isAuth: true }) +} + +// 对话分类删除 +export function chatCategoryDelete(data: any) { + return request.post({ url: '/ai/category/del', data }, { isAuth: true }) +} + +// 对话分类清空 +export function chatCategoryClear() { + return request.post({ url: '/ai/category/delAll' }, { isAuth: true }) +} + +// 创作 +export function creationChat(data: any, config: RequestEventStreamConfig) { + return request.eventStream({ url: '/chat/creationChat', data, method: 'POST' }, config) +} + +//获取聊天模型接口 +export function getChatModelApi() { + return request.get({ url: '/chats/getChatBillingConfigList' }) +} + +export function getChatBroadcast(data: any) { + return request.post({ url: '/voice/execute', data }) +} + +export function getChatVoiceGenerate(data: any) { + return request.post({ url: '/chats/voiceGenerate', data }) +} + +export function audioTransfer(filePath: string, formData: Record) { + return request.uploadFile({ + url: '/voice/voiceTransfer', + filePath, + formData, + name: 'file' + }) +} + +export function getPlugLists() { + return request.get({ url: '/chats/plugLists' }) +} diff --git a/src/api/drawing.ts b/src/api/drawing.ts new file mode 100644 index 0000000..997aafc --- /dev/null +++ b/src/api/drawing.ts @@ -0,0 +1 @@ +import request, { RequestEventStreamConfig } from '@/utils/request' export type DrawingFormType = { prompt: string // 是 关键词 action: string // 是 操作 generate=生成图片 upsample{index}=放大 variation{index}=变换 imageBase: string // 否 图片地址 图生成图时必填 imageId: string // 否 图片id 图片放大或变换时必填 model: string // 是 绘画的模型 version: string // 是 版本 scale: string // 否 图片比例 no_content: string // 否 忽略的关键词 other: string // 否 其它参数 style: string // 否 风格 动漫-default 可爱-cute 丰富-expressive 风景-scenic engine: string // 否 意间sd-绘画引擎 quality: string // 否 DALLE-3 画质 } // 生成图片 export function drawing(data: DrawingFormType) { return request.post({ url: '/draw/execute', data, method: 'POST' }) } // 生成图片详情 export function drawingDetail(data: number[]) { return request.post({ url: '/draw/records/detail', data }) } // 生成图片记录 export function drawingRecord(data: any) { return request.get({ url: '/draw/records/list', data }) } // 删除 export function drawingDelete(data: number[]) { return request.post({ url: '/draw/records/del', data, method: 'POST' }) } // 关键词分类 export function keywordCate() { return request.get({ url: '/draw/category/get' }) } // 关键词 export function keywordPrompt(data: any) { return request.get({ url: '/draw/prompt/get', data }) } // 绘画示例 export function drawingExample() { return request.get({ url: '/draw/prompt/example/get' }) } // 关键词翻译 export function keywordPromptTranslate(data: any) { return request.post({ url: '/draw/translate', data, method: 'POST' }) } // 绘画模型 export function drawingModel() { return request.get({ url: '/draw/getDrawBillingConfig' }) } // 意间绘画风格选择 export function yjStyleSelector() { return request.get({ url: '/draw/getSelector' }) } // SD export function sdModelList() { return request.get({ url: '/draw/sd/getModel' }) } \ No newline at end of file diff --git a/src/api/member.ts b/src/api/member.ts new file mode 100644 index 0000000..dc1ace8 --- /dev/null +++ b/src/api/member.ts @@ -0,0 +1,17 @@ +import request from '@/utils/request' + +export function getMemberLists() { + return request.get({ url: '/member/packageList' }, { isAuth: true }) +} + +export function getCommentLists(data: any) { + return request.get({ url: '/member/commentList', data }, { isAuth: true }) +} + +export function memberBuy(data: any) { + return request.post({ url: '/member/buy', data }, { isAuth: true }) +} + +export function getMemberBuyLog(data?: any) { + return request.get({ url: '/member/buyLog', data }, { isAuth: true }) +} diff --git a/src/api/news.ts b/src/api/news.ts new file mode 100644 index 0000000..72cc346 --- /dev/null +++ b/src/api/news.ts @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +/** + * @description 获取文章分类 + * @return { Promise } + */ +export function getArticleCate() { + return request.get({ url: '/article/category' }) +} + +/** + * @description 获取文章列表 + * @return { Promise } + */ +export function getArticleList(data: Record) { + return request.get({ url: '/article/list', data: data }) +} + +/** + * @description 获取文章详情 + * @param { number } id + * @return { Promise } + */ +export function getArticleDetail(data: { id: number }) { + return request.get({ url: '/article/detail', data: data }) +} + +/** + * @description 加入收藏 + * @param { number } articleId + * @return { Promise } + */ +export function addCollect(data: { articleId: number }) { + return request.post({ url: '/article/collectAdd', data: data }, { isAuth: true }) +} + +/** + * @description 取消收藏 + * @param { number } id + * @return { Promise } + */ +export function cancelCollect(data: { articleId: number }) { + return request.post({ url: '/article/collectCancel', data: data }, { isAuth: true }) +} + +/** + * @description 获取收藏列表 + * @return { Promise } + */ +export function getCollect() { + return request.get({ url: '/article/collectList' }) +} diff --git a/src/api/pay.ts b/src/api/pay.ts new file mode 100644 index 0000000..cf56c8b --- /dev/null +++ b/src/api/pay.ts @@ -0,0 +1,16 @@ +import request from '@/utils/request' + +//支付方式 +export function getPayWay(data: any) { + return request.get({ url: '/pay/payWay', data }, { isAuth: true }) +} + +// 预支付 +export function prepay(data: any) { + return request.post({ url: '/pay/prepay', data }, { isAuth: true }) +} + +// 预支付 +export function getPayResult(data: any) { + return request.get({ url: '/pay/payStatus', data }, { isAuth: true }) +} diff --git a/src/api/promotion.ts b/src/api/promotion.ts new file mode 100644 index 0000000..34a554e --- /dev/null +++ b/src/api/promotion.ts @@ -0,0 +1,55 @@ +import request from '@/utils/request' + +// 分销中心 +export function getDistributionIndex(data?: any) { + return request.get({ url: '/distribution/center', data }, { isAuth: true }) +} + +// 分销申请 +export function distributionApply(data: any) { + return request.post( + { url: '/distribution/apply', data }, + { isAuth: true } + ) +} + +// 分销订单 +export function distributionOrder(data?: any) { + return request.get( + { url: '/distribution/order/list', data }, + { isAuth: true } + ) +} + +// 粉丝列表 +export function distributionFans(data?: any) { + return request.get( + { url: '/distribution/user/invite/list', data }, + { isAuth: true } + ) +} + +// 提现 --------------------------------------------------------------------------------- +export type WithdrawApplyType = { + money: string | number // 提现金额 + account: string | number // 支付宝账号 + realName: string | number // 支付宝姓名 + type: string | number + moneyQrcode: string[] | string +} +// 提现申请 +export function withdrawApply(data: WithdrawApplyType) { + return request.post({ url: '/distribution/withdrawal/apply', data }, { isAuth: true }) +} + +// 提现记录 +export function withdrawList(data?: { pageNo: number; pageSize: number }) { + return request.get({ url: '/distribution/pc/withdrawal/list', data }, { isAuth: true }) +} + +export function accountLog(data?: any) { + return request.get( + { url: '/distribution/getRevenueDetails', data }, + { isAuth: true } + ) +} \ No newline at end of file diff --git a/src/api/qrcode.ts b/src/api/qrcode.ts new file mode 100644 index 0000000..7876cc1 --- /dev/null +++ b/src/api/qrcode.ts @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +export type QrcodeFormType = { + model: string // 是 绘画模型 + type: number // 是 生成模式 1-文本模式 2-图片模式 + way: number // 是 生成模式 1-自定义(模型) 2-模板 + qr_content: string // 否 二维码内容 (文本模式时必填) + qr_image: string // 否 二维码图片 (图片模式时必填) + prompt: string // 否 关键词 + prompt_params: PromptParams | string // 否 其他参数 + model_id: string | number // 否 模型id + template_name: string // 否 模板名称 + template_id: string | number // 否 模板id + aspect_ratio: string | number // 否 比例 (知数云) + pixel_style: string | number // 否 码点形状(知数云) + marker_shape: string | number // 否 码眼选择(知数云) +} + +export type PromptParams = { + v: string // 版本取值枚举 2 1.1 1) 示例:--v 2 --v 1.1 + iw: number // (明显程序取值范围 0 - 1, 保留两位小数) 示例: --iw 0.45 + seed: string // (取值范围1 - 999999999 ) 示例: --seed 123 + shape: string // (码眼选择范围) ["square", "circle", "plus", "box", "octagon", "random", "tiny-plus"], 示例 --shape random ,默认为 random + ar: string // (尺寸选择) 范围 ["1:1", "9:16", "16:9", "3:4","4:3"] 示例 --ar 1:1 ,默认为 1:1 +} + +// 获取艺术二维码配置 +export function qrcodeConfig() { + return request.get({ url: '/qrcode/config' }) +} + +// 生成艺术二维码 +export function qrcodeImagine(data: QrcodeFormType) { + return request.post({ url: '/qrcode/execute', data, method: 'POST' }) +} + +// 生成艺术二维码详情 +export function qrcodeDetail(data: { records_id: number[] }) { + return request.post({ url: '/qrcode/records/detail', data }) +} + +// 生成艺术二维码记录 +export function qrcodeRecord(data: any) { + return request.get( + { + url: '/qrcode/records/list', + data + }, + { ignoreCancel: true } + ) +} + +// 删除 +export function qrcodeDelete(data: number[]) { + return request.post({ + url: '/qrcode/records/del', + data, + method: 'POST' + }) +} diff --git a/src/api/recharge.ts b/src/api/recharge.ts new file mode 100644 index 0000000..535bb0b --- /dev/null +++ b/src/api/recharge.ts @@ -0,0 +1,21 @@ +import request from '@/utils/request' + +//充值 +export function recharge(data: any) { + return request.post({ url: '/recharge/placeOrder', data }, { isAuth: true }) +} + +//充值记录 +export function rechargeRecord(data: any) { + return request.get({ url: '/recharge/record', data }, { isAuth: true }) +} + +// 充值配置 +export function rechargeConfig() { + return request.get({ url: '/recharge/config' }, { isAuth: true }) +} + +// 充值配置 +export function getRechargeConfig() { + return request.get({ url: '/recharge/rechargePackage' }, { isAuth: true }) +} diff --git a/src/api/redeem_code.ts b/src/api/redeem_code.ts new file mode 100644 index 0000000..308e56b --- /dev/null +++ b/src/api/redeem_code.ts @@ -0,0 +1 @@ +import request from '@/utils/request' export type RedeemCodeResponse = { content: string // 卡密内容 failure_time: string // 失效时间 id: string | number // 卡密ID sn: string | number // 卡密编号 type: string // 卡密类型 type_desc: string // 卡密类型说明 } /** * @description 卡密查询 * @return { RedeemCodeResponse } * @param data */ export function checkRedeemCode(data: { sn: number | string }): Promise { return request.get({ url: '/card_code/record/get', data: data }) } /** * @description 卡密兑换 * @param data */ export function useRedeemCode(data: { sn: number | string }) { return request.post({ url: '/card_code/record/use', data: data }) } \ No newline at end of file diff --git a/src/api/shop.ts b/src/api/shop.ts new file mode 100644 index 0000000..478ba2c --- /dev/null +++ b/src/api/shop.ts @@ -0,0 +1,16 @@ +import { client } from '@/utils/client' +import request from '@/utils/request' + +//首页数据 +export function getIndex() { + return request.get({ url: '/index/index' }) +} + +// 装修页面 +export function getDecorate(data: any) { + return request.get({ url: '/index/decorate', data }, { ignoreCancel: true }) +} + +export function addVisit() { + return request.post({ url: '/index/visit/add', data: { terminal: client } }) +} diff --git a/src/api/square.ts b/src/api/square.ts new file mode 100644 index 0000000..4f9890d --- /dev/null +++ b/src/api/square.ts @@ -0,0 +1 @@ +import request from '@/utils/request' /** * @description 绘画广场列表 * @return { Promise } * @param params */ export function getDrawSquareLists(data?: any) { return request.get({ url: '/draw/square/list', data }) } /** * @description 绘画广场列表 * @return { Promise } */ export function getDrawSquareCateLists() { return request.get({ url: '/draw/square/category/list' }) } /** * @description 分享至绘画广场 * @return { Promise } */ export function shareDrawSquare(data: any) { return request.post({ url: '/draw/square/add', data }) } /** * @description 喜欢绘画 * @return { Promise } */ export function collectDraw(data: any) { return request.post({ url: '/draw/square/collect', data }) } /** * @description 取消喜欢绘画 * @return { Promise } */ export function cancelCollectDraw(data: any) { return request.post({ url: '/draw/square/cancelCollect', data }) } \ No newline at end of file diff --git a/src/api/task.ts b/src/api/task.ts new file mode 100644 index 0000000..1c54450 --- /dev/null +++ b/src/api/task.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getShareId() { + return request.post({ url: '/share/share' }) +} + +export function shareClick(data: any) { + return request.post({ url: '/share/click', data }) +} + +export function bindInvite(data: any, token: string) { + return request.post({ url: '/share/invite', data, header: { token } }) +} + +export function bindRegisterInvite(data: any) { + return request.post({ url: '/share/register/invite', data }) +} + +export function getTask() { + return request.get({ url: '/rewards/task' }) +} + +export function signClick() { + return request.post({ url: '/sign/click' }) +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..c46e6ad --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,58 @@ +import request from '@/utils/request' + +export function getUserCenter(header?: any) { + return request.get({ url: '/user/center', header }) +} + +// 个人信息 +export function getUserInfo() { + return request.get({ url: '/user/info' }, { isAuth: true }) +} + +// 个人编辑 +export function userEdit(data: any) { + return request.post({ url: '/user/edit', data }, { isAuth: true }) +} + +// 绑定手机 +export function userBindMobile(data: any, header?: any) { + return request.post({ url: '/login/bindMobile', data, header }, { isAuth: true }) +} + +// 微信电话 +export function userMnpMobile(data: any, header?: any) { + return request.post({ url: '/user/mnpMobile', data, header }, { isAuth: true }) +} +export function userChangePwd(data: any) { + return request.post({ url: '/user/changePwd', data }, { isAuth: true }) +} + +// 绑定小程序 +export function mnpAuthBind(data: any) { + return request.post({ url: '/user/bindMnp', data }) +} + +// 绑定公众号 +export function oaAuthBind(data: any) { + return request.post({ url: '/user/bindOa', data }) +} + +//更新微信小程序头像昵称 +export function updateUser(data: Record, header: any) { + return request.post({ url: '/user/updateUser', data, header }) +} + +//余额明细 +export function accountLog(data: any) { + return request.get({ url: '/logs/userMoney', data }) +} + +//一键反馈 +export function feedbackPost(data: any) { + return request.post({ url: '/feedback/add', data }) +} + +//注销账号 +export function cancelled(data?: any) { + return request.post({ url: '/login/cancelled', data }) +} \ No newline at end of file diff --git a/src/components/agreement/agreement.vue b/src/components/agreement/agreement.vue new file mode 100644 index 0000000..199bb33 --- /dev/null +++ b/src/components/agreement/agreement.vue @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/audio-play/audio-play.vue b/src/components/audio-play/audio-play.vue new file mode 100644 index 0000000..b4b921e --- /dev/null +++ b/src/components/audio-play/audio-play.vue @@ -0,0 +1,135 @@ + + + + diff --git a/src/components/avatar-upload/avatar-upload.vue b/src/components/avatar-upload/avatar-upload.vue new file mode 100644 index 0000000..07eb3f4 --- /dev/null +++ b/src/components/avatar-upload/avatar-upload.vue @@ -0,0 +1,111 @@ + + + + diff --git a/src/components/chat-plugins/chat-plugins.vue b/src/components/chat-plugins/chat-plugins.vue new file mode 100644 index 0000000..8d44669 --- /dev/null +++ b/src/components/chat-plugins/chat-plugins.vue @@ -0,0 +1,166 @@ + + + + diff --git a/src/components/chat-plugins/vip-use.vue b/src/components/chat-plugins/vip-use.vue new file mode 100644 index 0000000..1106541 --- /dev/null +++ b/src/components/chat-plugins/vip-use.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/components/chat-record-item/chat-record-item.vue b/src/components/chat-record-item/chat-record-item.vue new file mode 100644 index 0000000..4ab6f1f --- /dev/null +++ b/src/components/chat-record-item/chat-record-item.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/src/components/chat-record-item/record-file.vue b/src/components/chat-record-item/record-file.vue new file mode 100644 index 0000000..7f615a0 --- /dev/null +++ b/src/components/chat-record-item/record-file.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/components/chat-record-item/record-image.vue b/src/components/chat-record-item/record-image.vue new file mode 100644 index 0000000..84e45c6 --- /dev/null +++ b/src/components/chat-record-item/record-image.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/chat-record-item/text-item.vue b/src/components/chat-record-item/text-item.vue new file mode 100644 index 0000000..c96e1cb --- /dev/null +++ b/src/components/chat-record-item/text-item.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/components/chat-scroll-view/chat-scroll-view.vue b/src/components/chat-scroll-view/chat-scroll-view.vue new file mode 100644 index 0000000..dd77c2f --- /dev/null +++ b/src/components/chat-scroll-view/chat-scroll-view.vue @@ -0,0 +1,865 @@ + + + + + diff --git a/src/components/chat-scroll-view/components/app-chat.vue b/src/components/chat-scroll-view/components/app-chat.vue new file mode 100644 index 0000000..a560859 --- /dev/null +++ b/src/components/chat-scroll-view/components/app-chat.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/components/chat-scroll-view/components/online-voice.vue b/src/components/chat-scroll-view/components/online-voice.vue new file mode 100644 index 0000000..a69ac00 --- /dev/null +++ b/src/components/chat-scroll-view/components/online-voice.vue @@ -0,0 +1,431 @@ + + + + + diff --git a/src/components/chat-scroll-view/components/request/http.ts b/src/components/chat-scroll-view/components/request/http.ts new file mode 100644 index 0000000..c8b97ab --- /dev/null +++ b/src/components/chat-scroll-view/components/request/http.ts @@ -0,0 +1,202 @@ +import { merge } from 'lodash-es' +import {Base64} from 'js-base64' +import { useUserStore } from '@/stores/user' +import type { + HttpRequestOptions, + RequestConfig, + RequestEventStreamConfig, + RequestHooks, + RequestOptions +} from './type' +import { RequestCodeEnum, RequestMethodsEnum } from '@/enums/requestEnums' + +function isStreamResponse(contentType?: string) { + if (typeof contentType !== 'string') return false + return contentType.includes('text/event-stream') +} + +const requestHooks: RequestHooks = { + requestInterceptorsHook(options, config) { + const { urlPrefix, baseUrl, withToken } = config + options.header = options.header || {} + if (urlPrefix) { + options.url = `${urlPrefix}${options.url}` + } + if (baseUrl) { + options.url = `${baseUrl}${options.url}` + } + const token = config.token + + options.header['terminal'] = config!.terminal + // 添加token + if (withToken && !options.header.token) { + options.header['ai-token'] = token + } + return options + }, + async responseInterceptorsHook(response, config, options) { + const { isTransformResponse, isReturnDefaultResponse, isAuth } = config + + //返回默认响应,当需要获取响应头及其他数据时可使用 + if (isReturnDefaultResponse) { + return response + } + // 是否需要对数据进行处理 + if (!isTransformResponse) { + return response.data + } + // const { logout } = useUserStore() + const { code, data, msg, show } = response.data as any + switch (code) { + case RequestCodeEnum.SUCCESS: + // msg && show && uni.$u.toast(msg) + return data + case RequestCodeEnum.FAILED: + // msg && uni.$u.toast(msg) + return Promise.reject(msg) + + case RequestCodeEnum.TOKEN_INVALID: + // logout() + if (isAuth && options.method?.toUpperCase() !== 'GET') { + // router.navigateTo({ path: '/pages/login/login' }) + } + return Promise.reject(msg) + + default: + return data + } + }, + async responseInterceptorsCatchHook(options, error) { + if (options.method?.toUpperCase() == RequestMethodsEnum.POST) { + // uni.$u.toast('请求失败,请重试') + } + return error + } +} + +export const defaultOptions: HttpRequestOptions = { + requestOptions: { + timeout: 30 * 1000 + }, + // baseUrl: `${import.meta.env.VITE_APP_BASE_URL || ''}/`, + baseUrl: '', + + //是否返回默认的响应 + isReturnDefaultResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // 接口拼接地址 + urlPrefix: 'api', + // 忽略重复请求 + ignoreCancel: false, + // 是否携带token + withToken: true, + isAuth: false, + retryCount: 2, + retryTimeout: 1000, + requestHooks: requestHooks, + token: '' +} + +export const eventStream = ( + options: RequestOptions, + config: RequestEventStreamConfig +) => { + let mergeOptions = merge({}, defaultOptions.requestOptions, options) + + const mergeConfig: RequestEventStreamConfig = merge( + {}, + defaultOptions, + config + ) + const { requestInterceptorsHook, responseInterceptorsHook } = + mergeConfig.requestHooks || {} + + // if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) { + mergeOptions = requestInterceptorsHook( + mergeOptions, + mergeConfig as RequestConfig + ) + // } + + let body: any = undefined + body = JSON.stringify(mergeOptions.data) + + const { onmessage, onclose, onstart } = config + + const decoder = new TextDecoder() + const push = async (controller: any, reader: any) => { + try { + const { value, done } = await reader.read() + if (done) { + controller.close() + onclose?.() + } else { + const tempval = Base64.decode(decoder.decode(value)) + onmessage?.(tempval) + controller.enqueue(value) + push(controller, reader) + } + } catch (error) { + onclose?.() + } + } + + return new Promise((resolve, reject) => { + console.log('asdas-----------------d', JSON.stringify(mergeOptions)) + fetch(mergeOptions.url, { + ...mergeOptions, + body, + headers: { + 'content-type': 'application/json; charset=utf-8', + Accept: 'text/event-stream', + ...mergeOptions.header + } + }) + .then(async (response) => { + if (response.status == 200) { + if ( + isStreamResponse(response.headers?.get('content-type')!) + ) { + const reader = response.body!.getReader() + // console.log(reader) + onstart?.(reader) + new ReadableStream({ + start(controller) { + push(controller, reader) + } + }) + } else { + //@ts-ignore + response.data = await response.json() + return response + } + } else { + reject(response.statusText) + } + }) + .then(async (response: any) => { + if (!response) { + resolve(response) + return + } + if (responseInterceptorsHook) { + try { + response = await responseInterceptorsHook( + response, + mergeConfig as RequestConfig, + mergeOptions + ) + resolve(response) + } catch (error) { + reject(error) + } + return + } + resolve(response) + }) + .catch((error) => { + reject(error) + }) + }) +} diff --git a/src/components/chat-scroll-view/components/request/index.ts b/src/components/chat-scroll-view/components/request/index.ts new file mode 100644 index 0000000..4caa99a --- /dev/null +++ b/src/components/chat-scroll-view/components/request/index.ts @@ -0,0 +1,13 @@ +import { eventStream } from './http' + +export const getChat = (data: any, config: any) => { + console.log('qweqwe----------------', config) + return eventStream( + { + url: '/chats/chatSend', + data, + method: 'POST' + }, + config + ) +} diff --git a/src/components/chat-scroll-view/components/request/type.d.ts b/src/components/chat-scroll-view/components/request/type.d.ts new file mode 100644 index 0000000..ed001ec --- /dev/null +++ b/src/components/chat-scroll-view/components/request/type.d.ts @@ -0,0 +1,44 @@ +export type RequestOptions = UniApp.RequestOptions +export type ResponseResult = + | UniApp.RequestSuccessCallbackResult + | UniApp.UploadFileSuccessCallbackResult +export type RequestOptionsResponseError = UniApp.GeneralCallbackResult +export type RequestTask = UniApp.RequestTask +export type UploadFileOption = UniApp.UploadFileOption +export interface HttpRequestOptions extends RequestConfig { + requestOptions: Partial +} + +export interface RequestConfig { + baseUrl: string + requestHooks: RequestHooks + isReturnDefaultResponse: boolean + isTransformResponse: boolean + urlPrefix: string + ignoreCancel: boolean + withToken: boolean + isAuth: boolean + retryCount: number + retryTimeout: number + hasRetryCount?: number + token: string +} + +export interface RequestEventStreamConfig extends Partial { + onstart?: (event: ReadableStreamDefaultReader | UniApp.RequestTask) => void + onmessage?: (value: string) => void + onclose?: () => void +} + +export interface RequestHooks { + requestInterceptorsHook?( + options: RequestOptions, + config: RequestConfig + ): RequestOptions + responseInterceptorsHook?( + response: ResponseResult, + config: RequestConfig, + options: RequestOptions + ): any + responseInterceptorsCatchHook?(options: RequestOptions, error: any): any +} diff --git a/src/components/dialog-poster/dialog-poster.vue b/src/components/dialog-poster/dialog-poster.vue new file mode 100644 index 0000000..8690496 --- /dev/null +++ b/src/components/dialog-poster/dialog-poster.vue @@ -0,0 +1,385 @@ + + + diff --git a/src/components/dragon-button/dragon-button.vue b/src/components/dragon-button/dragon-button.vue new file mode 100644 index 0000000..08a1e0a --- /dev/null +++ b/src/components/dragon-button/dragon-button.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/components/drop-down/drop-down.vue b/src/components/drop-down/drop-down.vue new file mode 100644 index 0000000..af83eb6 --- /dev/null +++ b/src/components/drop-down/drop-down.vue @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/file-upload/choose-file.ts b/src/components/file-upload/choose-file.ts new file mode 100644 index 0000000..0b194ad --- /dev/null +++ b/src/components/file-upload/choose-file.ts @@ -0,0 +1,247 @@ +const ERR_MSG_FAIL = 'chooseFile:fail' +interface BaseOptions { + type: 'file' | 'image' | 'video' +} +type ChooseFileOptions = UniApp.ChooseFileOptions +type ChooseImageOptions = UniApp.ChooseImageOptions +type ChooseVideoOptions = UniApp.ChooseVideoOptions +type ChooseOptions = BaseOptions & + (ChooseFileOptions | ChooseImageOptions | ChooseVideoOptions) + +export interface ChooseResult { + tempFilePaths: string[] | string + tempFiles: any[] + errMsg?: string +} + +export interface FileData { + name: string + uuid: number + extname: string + fileType: string + url: string + path: string + size: string + progress: number + status: 'ready' | 'success' | 'error' + errMsg: string +} + +function chooseImage(opts: ChooseImageOptions) { + const { + count, + sizeType = ['original', 'compressed'], + sourceType, + extension + } = opts + return new Promise((resolve, reject) => { + uni.chooseImage({ + count, + sizeType, + sourceType, + extension, + success(res) { + resolve(normalizeFileRes(res as ChooseResult, 'image')) + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL) + }) + } + }) + }) +} + +function chooseVideo(opts: ChooseVideoOptions) { + const { camera, compressed, maxDuration, sourceType, extension } = opts + return new Promise((resolve, reject) => { + uni.chooseVideo({ + camera, + compressed, + maxDuration, + sourceType, + extension, + success(res) { + const { tempFilePath, duration, size, height, width } = res + resolve( + normalizeFileRes( + { + errMsg: 'chooseVideo:ok', + tempFilePaths: [tempFilePath], + tempFiles: [ + { + name: + (res.tempFile && res.tempFile.name) || + '', + path: tempFilePath, + size, + type: + (res.tempFile && res.tempFile.type) || + '', + width, + height, + duration, + fileType: 'video' + } + ] + }, + 'video' + ) + ) + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL) + }) + } + }) + }) +} + +function chooseAll(opts: ChooseFileOptions) { + const { count, extension } = opts + return new Promise((resolve, reject) => { + let chooseFile = uni.chooseFile + if ( + typeof wx !== 'undefined' && + typeof wx.chooseMessageFile === 'function' + ) { + chooseFile = wx.chooseMessageFile + } + if (typeof chooseFile !== 'function') { + return reject({ + errMsg: + ERR_MSG_FAIL + + ' 请指定 type 类型,该平台仅支持选择 image 或 video。' + }) + } + chooseFile({ + type: 'all', + count, + extension, + success(res) { + resolve(normalizeFileRes(res as ChooseResult)) + }, + fail(res) { + reject({ + errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL) + }) + } + }) + }) +} + +function normalizeFileRes(res: ChooseResult, fileType?: BaseOptions['type']) { + res.tempFiles.forEach((item) => { + if (!item.name) { + item.name = item.path.substring(item.path.lastIndexOf('/') + 1) + } + if (fileType) { + item.fileType = fileType + } + }) + if (!res.tempFilePaths) { + res.tempFilePaths = res.tempFiles.map((file) => file.path) + } + return res +} + +function chooseFile( + opts: ChooseOptions = { + type: 'file' + } +): Promise { + if (opts.type === 'image') { + return chooseImage(opts as ChooseImageOptions) + } else if (opts.type === 'video') { + return chooseVideo(opts as ChooseVideoOptions) + } + return chooseAll(opts as ChooseFileOptions) +} + +/** + * @description 获取文件扩展名和文件名 + * @param name + * @returns + */ +const getFileExt = (name: string) => { + const lastLen = name.lastIndexOf('.') + const len = name.length + const fileName = name.substring(0, lastLen) + const ext = name.substring(lastLen + 1, len) + return { + name: fileName, + ext + } +} +/** + * @description 路径中获取文件名称 + * @param name + * @returns + */ +const getFileName = (path: string) => { + const lastLen = path.lastIndexOf('.') + const lastPath = path.lastIndexOf('/') + // 不是文件 + if (lastLen === -1) return path + return path.substring(lastPath + 1) +} + +const normalizeFileData = (files: any) => { + const fileFullName = getFileExt(files.name) + const extname = fileFullName.ext.toLowerCase() + const filedata: FileData = { + name: files.name, + uuid: files.uuid, + extname: extname || '', + fileType: files.fileType, + path: files.path, + url: files.path, + size: files.size, + progress: 0, + status: 'ready', + errMsg: '' + } + return filedata +} + +// 检验扩展名是否正确 +const getFilesByExtname = (res: ChooseResult, extname: string[] = []) => { + const filePaths: any[] = [] + const files: any[] = [] + if (!extname.length) { + return { + filePaths: res.tempFilePaths, + files: res.tempFiles + } + } + res.tempFiles.forEach((v) => { + const fileFullName = getFileExt(v.name) + const ext = fileFullName.ext.toLowerCase() + if (extname.indexOf(ext) !== -1) { + files.push(v) + filePaths.push(v.path) + } + }) + if (files.length !== res.tempFiles.length) { + uni.showToast({ + title: `当前选择了${res.tempFiles.length}个文件 ,${ + res.tempFiles.length - files.length + } 个文件格式不正确`, + icon: 'none', + duration: 5000 + }) + } + return { + filePaths, + files + } +} + +export { + chooseFile, + getFileExt, + getFilesByExtname, + normalizeFileData, + getFileName +} diff --git a/src/components/file-upload/file-upload.vue b/src/components/file-upload/file-upload.vue new file mode 100644 index 0000000..9002fd3 --- /dev/null +++ b/src/components/file-upload/file-upload.vue @@ -0,0 +1,394 @@ + + + + diff --git a/src/components/floating-menu/floating-menu.vue b/src/components/floating-menu/floating-menu.vue new file mode 100644 index 0000000..47030ec --- /dev/null +++ b/src/components/floating-menu/floating-menu.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/src/components/guided-popup/guided-popup.vue b/src/components/guided-popup/guided-popup.vue new file mode 100644 index 0000000..0341ec7 --- /dev/null +++ b/src/components/guided-popup/guided-popup.vue @@ -0,0 +1,94 @@ + + + diff --git a/src/components/l-textarea/l-textarea.vue b/src/components/l-textarea/l-textarea.vue new file mode 100644 index 0000000..d507e53 --- /dev/null +++ b/src/components/l-textarea/l-textarea.vue @@ -0,0 +1,90 @@ +