# kankandx
**Repository Path**: totodo/kankandx
## Basic Information
- **Project Name**: kankandx
- **Description**: dadaxue app
- **Primary Language**: JavaScript
- **License**: OSL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-04-24
- **Last Updated**: 2024-06-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# kankandx
#### 介绍
侃侃大学里的那些专业 APP
#### 软件架构
1. VUE3 vue-router https://vuejs.org
2. Vite 5.0 https://cn.vuejs.org/guide/scaling-up/tooling.html#vite
3. DesignSystem tdesign-vue-next https://tdesign.tencent.com/
4. Css tailwindcsss https://tailwindcss.com/
#### 安装教程
全局安装
```
npm i
```
安装Tdesginer组件
```
npm install tdesign-vue-next
```
安装tailwindcss
```
npm install tailwindcss postcss autoprefixer
```
#### 使用说明
```
npm run dev
```
#### 开发教程
##### 1开发配置
###### 1.1. 配置t-designe
```javascript
//main.js
import TDesign from 'tdesign-vue-next';
import 'tdesign-vue-next/es/style/index.css';
const app = createApp(App)
app.use(TDesign)
```
###### 1.2. 配制tailwindcss
配置文件 tailwind.config.js
```javascript
//tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{vue,html,js}"],
theme: {
extend: {},
},
plugins: [],
}
```
配置文件 postcss.config.js
```javascript
//postcss.config.js
plugins: {
tailwindcss: {},
autoprefixer: {},
},
```
配置css文件 src/assets/index.csss
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
引入tailwindcsss mian.js中
```javascript
import './assets/index.css'
```
###### 1.3. 配置Vite
```javascript
//vite.config.JS
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from 'tailwindcss'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
```
##### 2. Vue开发使用指南
###### 2.1 使用Vue-rotuer
```javascript
//router/index.js
//引入组件
import Home from './components/Home.vue'
import AddAdvice from './components/AddAdvice.vue'
// 引入路由
import { createRouter, createWebHashHistory } from 'vue-router'
// 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: '/', component: Home },
{ path: '/addadvice', component: AddAdvice },
{ path: '/feedback', component: FeedBack },
]
// 创建路由实例
const router = createRouter({
routes,
history: createWebHashHistory()
})
// 使用路由
const app = createApp(App)
app.use(router)
```
###### 2.2 VUE 模板中跳转
```html
Add
Home
```
###### 2.3 script 方法中调用
* 方式一 使用全局属性 $router
```javascript
this.$router.push('/') //跳转到 Home.vue
this.$router.push('/addadvice') //跳转到AddAdvice.vue
```
* 方式二 使用 Composition API 的 useRouter 钩子
```javascript
// main.js文件中
app.provide('router', router);
```
```javascript
//UserRegister.vue文件 中
import { inject } from 'vue';//引入
const router = inject('router');
router.push("/")
```
VUE模板中使用展示
```html
```
###### 2.2 使用TDesigner下拉选择组件
选用t-input-selector 组件
* 参考文档
https://tdesign.tencent.com/vue-next/components/select?tab=demo
定义formdata,selectInput,以及下拉中的事件
```javascript
data(){
selectSchool: '', //学校下拉选择输入内容,可根据这个值进行后台过滤
popupVisibleSchool: false, //弹出下拉选择列表的展示控制
formdata:{
school:'', //v-model 绑定formdata.school 传递给后台
},
schools:[] //学校选择器的数组
}
```
定义t-input-select 中绑定的事件
```javascript
methods:{
//学校下拉 输入下来
onInputChangeSchool(val, content) {
//console.log(val, content)
this.getCategroySelect(val,'学校')
},
onOptionClickSchool(o) {
//console.log(school)
this.selectSchool = o.tagname;
// 选中后立即关闭浮层
this.popupVisibleSchool = false;
//选中后赋予值
this.formData.school = o.tagname;
},
onPopupVisibleChangeSchool(val,content){
this.popupVisibleSchool = val;
}
}
```
使用t-input-select组件
``` html
```
#### 3 Form表单验证
##### 给form 添加 规则
引用参考
https://tdesign.tencent.com/vue-next/components/form#%E4%B8%8D%E5%90%8C%E6%A0%A1%E9%AA%8C%E8%A7%84%E5%88%99%E7%9A%84%E8%A1%A8%E5%8D%95
```vue
{{ title }}
```
在 javascript 中添加 rules 对象
```javascript
const rules = {
username: [
{ required: true, message: '用户名必填', type: 'error' },
{
min: 3,
message: '至少需要两3个字符',
type: 'error',
trigger: 'blur',
},
{
max: 32,
message: '最长不能超过32个字符',
type: 'error',
trigger: 'blur',
},
],
password: [
{ required: true, message: '密码必填', type: 'error' },
],
repassword: [
{ required: true, message: '密码必填', type: 'error' },
{ validator: rePassword, message: '两次密码不一致' } // rePassword 设置为可自定义的校验方法
]
};
const rePassword = (val) =>
new Promise((resolve) => {
const timer = setTimeout(() => {
resolve(formData.password === val);
clearTimeout(timer);
}, 500); // 假设验证延时为0.5秒
});
```
注:使用 validator 自定义校验函数,支持异步返回结果 Promise,返回结果可以设置不同的校验结果、校验结果类型、校验结果信息。
示例一 : validator: (val) => { result: !!val, message: '该项必填', type: 'error' }。
示例二:validator: (val) => new Promise((resolve) => resolve({ result: false, message: '校验未通过', type: 'warning' }))。如果是异步校验,必须返回所有情况的校验结果,不能只返回 resolve(false) 校验不通过的情况,还需要注意返回 resolve(true) 校验通过的情况。
#### 4 VUE 部署环境配置
##### 创建环境变量文件:
在项目根目录下,创建或编辑以下两个文件:
.env:全局环境变量,对所有环境生效。
.env.local:本地环境变量,会覆盖 .env 中的相同变量。
.env.development:开发环境特定的环境变量。
.env.production:生产环境特定的环境变量。
###### 在代码中使用环境变量:
在Vite项目中,你可以通过import.meta.env来访问这些环境变量。例如:
```javascript
const baseUrl = import.meta.env.VITE_APP_API_BASE_URL;
```
#### 5 VUE第三方组件使用
###### ChartJs做普通图表 (EcCharts ChartJS)
vue-chartjs 是Chart.js 的扩展. 可以方便的创建使用图表的扩展组件
目前最新支持 Chart.js v4.
##### 安装
```bash
npm i vue-chartjs chart.js
```
##### 创建图表
饼状图摸版
``` vue
```
脚本
``` javascript
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
export default {
name: 'BarChart',
components: { Bar },
data() {
return {
chartData: {
labels: ['January', 'February', 'March','April','May'],
datasets: [
{
label: '同比增长',
backgroundColor: '#f87979',
data: [40, 45, 50, 60, 55]
},
{
label: '环比增长',
backgroundColor: '#7989f8',
data: [25, 35, 40, 45, 50]
}
]
},
chartOptions: {
responsive: true,
maintainAspectRatio: false
}
}
},
```
##### 更新图表。动态获取数据
更新图表的数据,不能直接修改选项式申明中的data,他是只读。 所以需要用相应方式去绑定, 在export default 中使用coumpute: 在组合式API方法中,可以对相应的对象,直接修改复制。
``` javascript
import { ref } from 'vue'
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
import { useIntervalFn } from '@vueuse/core'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
const chartData =ref({
labels: ['January', 'February', 'March', 'April', 'May'],
datasets: [
{
label: '同比增长',
backgroundColor: '#f87979',
data: [40, 45, 50, 60, 55]
},
{
label: '环比增长',
backgroundColor: '#7989f8',
data: [25, 35, 40, 45, 50]
}
]}
)
const chartOptions = ref({
responsive: true,
maintainAspectRatio: false
})
//更新图表数据
const updateData = () => {
chartData.value = {
labels: ['January', 'February', 'March', 'April', 'May'],
datasets: [
{
label: '同比增长',
backgroundColor: '#f87979',
data: [Math.random()*100, Math.random()*100, Math.random()*100, Math.random()*100, Math.random()*100]
},
{
label: '环比增长',
backgroundColor: '#7989f8',
data: [Math.random()*100, Math.random()*100, Math.random()*100, Math.random()*100, Math.random()*100]
}
]
}
}
//采用usecore 动态调用函数定时器 useIntervalFn() 实现动态更新
useIntervalFn(() => {
updateData()
}, 1000)
```
##### ApexChartjs 实现股票实时走势图
##### 安装 vue3-ApexChartjs
``` bash
npm install --save apexcharts
npm install --save vue3-apexcharts
```
candlestick 图表魔板
``` vue
```
``` javascript
import { ref } from 'vue'
import ApexCharts from 'vue3-apexcharts'
import { useIntervalFn } from '@vueuse/core'
const chartRef = ref(null)
const ohlcData = [{
x: new Date(1538778600000),
y: [6629.81, 6650.5, 6623.04, 6633.33]
},
{
x: new Date(1538780400000),
y: [6632.01, 6643.59, 6620, 6630.11]
},
{
x: new Date(1538782200000),
y: [6630.71, 6648.95, 6623.34, 6635.65]
},
{
x: new Date(1538784000000),
y: [6635.65, 6651, 6629.67, 6638.24]
},
{
x: new Date(1538785800000),
y: [6638.24, 6640, 6620, 6624.47]
},
{
x: new Date(1538787600000),
y: [6624.53, 6636.03, 6621.68, 6624.31]
},
{
x: new Date(1538789400000),
y: [6624.61, 6632.2, 6617, 6626.02]
},
{
x: new Date(1538791200000),
y: [6627, 6627.62, 6584.22, 6603.02]
},
{
x: new Date(1538793000000),
y: [6605, 6608.03, 6598.95, 6604.01]
},
{
x: new Date(1538794800000),
y: [6604.5, 6614.4, 6602.26, 6608.02]
},
{
x: new Date(1538796600000),
y: [6608.02, 6610.68, 6601.99, 6608.91]
},
{
x: new Date(1538798400000),
y: [6608.91, 6618.99, 6608.01, 6612]
},
{
x: new Date(1538800200000),
y: [6612, 6615.13, 6605.09, 6612]
},
{
x: new Date(1538802000000),
y: [6612, 6624.12, 6608.43, 6622.95]
},
{
x: new Date(1538803800000),
y: [6623.91, 6623.91, 6615, 6615.67]
},
{
x: new Date(1538805600000),
y: [6618.69, 6618.74, 6610, 6610.4]
},
{
x: new Date(1538807400000),
y: [6611, 6622.78, 6610.4, 6614.9]
},
{
x: new Date(1538809200000),
y: [6614.9, 6626.2, 6613.33, 6623.45]
},
{
x: new Date(1538811000000),
y: [6623.48, 6627, 6618.38, 6620.35]
},
{
x: new Date(1538812800000),
y: [6619.43, 6620.35, 6610.05, 6615.53]
},
{
x: new Date(1538814600000),
y: [6615.53, 6617.93, 6610, 6615.19]
},
{
x: new Date(1538816400000),
y: [6615.19, 6621.6, 6608.2, 6620]
},
{
x: new Date(1538818200000),
y: [6619.54, 6625.17, 6614.15, 6620]
},
{
x: new Date(1538820000000),
y: [6620.33, 6634.15, 6617.24, 6624.61]
},
{
x: new Date(1538821800000),
y: [6625.95, 6626, 6611.66, 6617.58]
},
{
x: new Date(1538823600000),
y: [6619, 6625.97, 6595.27, 6598.86]
},
{
x: new Date(1538825400000),
y: [6598.86, 6598.88, 6570, 6587.16]
},
{
x: new Date(1538827200000),
y: [6588.86, 6600, 6580, 6593.4]
},
{
x: new Date(1538829000000),
y: [6593.99, 6598.89, 6585, 6587.81]
},
{
x: new Date(1538830800000),
y: [6587.81, 6592.73, 6567.14, 6578]
},
{
x: new Date(1538832600000),
y: [6578.35, 6581.72, 6567.39, 6579]
},
{
x: new Date(1538834400000),
y: [6579.38, 6580.92, 6566.77, 6575.96]
},
{
x: new Date(1538836200000),
y: [6575.96, 6589, 6571.77, 6588.92]
},
{
x: new Date(1538838000000),
y: [6588.92, 6594, 6577.55, 6589.22]
},
{
x: new Date(1538839800000),
y: [6589.3, 6598.89, 6589.1, 6596.08]
},
{
x: new Date(1538841600000),
y: [6597.5, 6600, 6588.39, 6596.25]
},
{
x: new Date(1538843400000),
y: [6598.03, 6600, 6588.73, 6595.97]
},
{
x: new Date(1538845200000),
y: [6595.97, 6602.01, 6588.17, 6602]
},
{
x: new Date(1538847000000),
y: [6602, 6607, 6596.51, 6599.95]
},
{
x: new Date(1538848800000),
y: [6600.63, 6601.21, 6590.39, 6591.02]
},
{
x: new Date(1538850600000),
y: [6591.02, 6603.08, 6591, 6591]
},
{
x: new Date(1538852400000),
y: [6591, 6601.32, 6585, 6592]
},
{
x: new Date(1538854200000),
y: [6593.13, 6596.01, 6590, 6593.34]
},
{
x: new Date(1538856000000),
y: [6593.34, 6604.76, 6582.63, 6593.86]
},
{
x: new Date(1538857800000),
y: [6593.86, 6604.28, 6586.57, 6600.01]
},
{
x: new Date(1538859600000),
y: [6601.81, 6603.21, 6592.78, 6596.25]
},
{
x: new Date(1538861400000),
y: [6596.25, 6604.2, 6590, 6602.99]
},
{
x: new Date(1538863200000),
y: [6602.99, 6606, 6584.99, 6587.81]
},
{
x: new Date(1538865000000),
y: [6587.81, 6595, 6583.27, 6591.96]
},
{
x: new Date(1538866800000),
y: [6591.97, 6596.07, 6585, 6588.39]
},
{
x: new Date(1538868600000),
y: [6587.6, 6598.21, 6587.6, 6594.27]
},
{
x: new Date(1538870400000),
y: [6596.44, 6601, 6590, 6596.55]
},
{
x: new Date(1538872200000),
y: [6598.91, 6605, 6596.61, 6600.02]
},
{
x: new Date(1538874000000),
y: [6600.55, 6605, 6589.14, 6593.01]
},
{
x: new Date(1538875800000),
y: [6593.15, 6605, 6592, 6603.06]
},
{
x: new Date(1538877600000),
y: [6603.07, 6604.5, 6599.09, 6603.89]
},
{
x: new Date(1538879400000),
y: [6604.44, 6604.44, 6600, 6603.5]
},
{
x: new Date(1538881200000),
y: [6603.5, 6603.99, 6597.5, 6603.86]
},
{
x: new Date(1538883000000),
y: [6603.85, 6605, 6600, 6604.07]
},
{
x: new Date(1538884800000),
y: [6604.98, 6606, 6604.07, 6606]
},
]
const series = ref([
{
data: ohlcData
}
])
const chartOptions = ref({
chart: {
type: 'candlestick',
height: 350
},
title: {
text: '铜价期货跟踪图标',
align: 'center'
},
xaxis: {
type: 'datetime',
range: 60480000,
tooltip: {
enabled: true,
}
},
yaxis: {
tooltip: {
enabled: true
}
}
})
//推送新数据更新图表的方法
const updateData = (n) => {
const newData = {
x: new Date()+1800000,
y: [6600+Math.random()*20, 6600+Math.random()*20,6600-Math.random()*20, 6600-Math.random()*20]
}
series.value[0].data.push(newData)
console.log(series.value[0].data.length)
series.value[0].data.shift();
}
useIntervalFn(() => {
updateData(1800000)
}, 3000)
```