Browse Source

修改 bug

master
王泽彦 9 months ago
parent
commit
1059296971
  1. 28
      niucloud/app/api/route/route.php
  2. 173
      niucloud/课程安排资料.md
  3. 56
      uniapp/api/apiRoute.js
  4. 240
      uniapp/components/CommentList.vue
  5. 166
      uniapp/components/J-skeleton/J-skeleton.vue
  6. 77
      uniapp/components/J-skeleton/README.md
  7. 438
      uniapp/components/aui-dialog/aui-dialog.vue
  8. 292
      uniapp/components/aui-dialog/common/aui/css/aui.css
  9. 1
      uniapp/components/aui-dialog/common/aui/css/aui.iconfont.css
  10. 55
      uniapp/components/aui-dialog/common/aui/js/aui.js
  11. 181
      uniapp/components/coolc-coupon/coolc-coupon.vue
  12. 234
      uniapp/components/custom-modal/example.vue
  13. 393
      uniapp/components/modal/modal.vue
  14. 96
      uniapp/components/uni-icons/icons.js
  15. 57
      uniapp/components/uni-icons/uni-icons.vue
  16. 4
      uniapp/components/uni-nav-bar/uni-nav-bar.vue
  17. 13
      uniapp/pages.json
  18. 295
      uniapp/pages/market/clue/clue_info.vue
  19. 8
      uniapp/pages/market/clue/order_list.vue

28
niucloud/app/api/route/route.php

@ -290,6 +290,34 @@ Route::group(function () {
//员工端-更新学员课程人员配置
Route::post('updateStudentCoursePersonnel', 'apiController.Course/updateStudentCoursePersonnel');
// 课程安排相关接口
//员工端-获取课程安排列表
Route::get('courseSchedule/list', 'apiController.CourseSchedule/getScheduleList');
//员工端-获取课程安排详情
Route::get('courseSchedule/info', 'apiController.CourseSchedule/getScheduleInfo');
//员工端-创建课程安排
Route::post('courseSchedule/create', 'apiController.CourseSchedule/createSchedule');
//员工端-批量创建课程安排
Route::post('courseSchedule/batchCreate', 'apiController.CourseSchedule/batchCreateSchedule');
//员工端-更新课程安排
Route::post('courseSchedule/update', 'apiController.CourseSchedule/updateSchedule');
//员工端-删除课程安排
Route::post('courseSchedule/delete', 'apiController.CourseSchedule/deleteSchedule');
//员工端-获取场地列表
Route::get('courseSchedule/venues', 'apiController.CourseSchedule/getVenueList');
//员工端-获取场地可用时间
Route::get('courseSchedule/venueAvailableTime', 'apiController.CourseSchedule/getVenueAvailableTime');
//员工端-检查教练时间冲突
Route::get('courseSchedule/checkCoachConflict', 'apiController.CourseSchedule/checkCoachConflict');
//员工端-获取课程安排统计
Route::get('courseSchedule/statistics', 'apiController.CourseSchedule/getScheduleStatistics');
//员工端-学员加入课程安排
Route::post('courseSchedule/joinSchedule', 'apiController.CourseSchedule/joinSchedule');
//员工端-学员退出课程安排
Route::post('courseSchedule/leaveSchedule', 'apiController.CourseSchedule/leaveSchedule');
//员工端-获取筛选选项
Route::get('courseSchedule/filterOptions', 'apiController.CourseSchedule/getFilterOptions');

173
niucloud/课程安排资料.md

@ -0,0 +1,173 @@
school_campus(校区表)
CREATE TABLE `school_campus` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`campus_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '校区名称',
`campus_address` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '校区地址',
`campus_preview_image` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '校区预览图,存储图片路径',
`campus_coordinates` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '校区坐标,格式为经度,纬度',
`campus_introduction` text COLLATE utf8mb4_general_ci COMMENT '校区介绍',
`campus_status` tinyint DEFAULT '1' COMMENT '校区状态:0-禁用,1-启用',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '校区创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '校区更新时间',
`delete_time` int NOT NULL DEFAULT '0' COMMENT '逻辑删除字段,0表示未删除,非空表示已删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='校区表';
做为基础数据,下面一级就是场地。
school_venue(场地表)
CREATE TABLE `school_venue` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '场地编号',
`campus_id` int NOT NULL COMMENT '校区ID',
`venue_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '场地名称',
`capacity` int NOT NULL COMMENT '场地可容纳人数上限',
`availability_status` tinyint(1) NOT NULL COMMENT '场地可用状态: 1-可用, 0-不可用',
`time_range_type` enum('range','fixed','all') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '场地可用时间范围类型: range-范围类型, fixed-固定时间范围类型',
`time_range_start` varchar(8) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '范围类型的开始时间',
`time_range_end` varchar(8) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '范围类型的结束时间',
`fixed_time_ranges` json DEFAULT NULL COMMENT '固定时间范围类型的可用时间, 存储为JSON数组',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`deleted_at` int DEFAULT '0' COMMENT '逻辑删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='场地表';
场地表做为课程的容器,主要是用来限制人数,时间,和可用状态。如果场地被设置为不可用,那么该场地下的所有课程都会被取消。其中time_range_type字段决定这个时间范围是范围类型还是固定时间类型。
这个字段配合time_range_start,time_range_end,fixed_time_ranges这三个字段,可以确定这个场地可用的时间范围。
school_course(课程表)
CREATE TABLE `school_course` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '课程编号',
`course_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '课程名称',
`course_type` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '课程类型',
`duration` int NOT NULL COMMENT '课程时长',
`session_count` int NOT NULL COMMENT '课时数量',
`single_session_count` int NOT NULL DEFAULT '0' COMMENT '单次消课数量',
`gift_session_count` int NOT NULL DEFAULT '0' COMMENT '赠送课时数量',
`price` decimal(10,2) NOT NULL COMMENT '课程价格',
`internal_reminder` int NOT NULL COMMENT '内部提醒课时',
`customer_reminder` int NOT NULL COMMENT '客户提醒课时',
`remarks` text COLLATE utf8mb4_general_ci COMMENT '课程备注',
`created_at` int DEFAULT '0' COMMENT '创建时间',
`updated_at` int DEFAULT '0' COMMENT '更新时间',
`deleted_at` int DEFAULT '0' COMMENT '逻辑删除时间',
`contract_id` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='课程表';
课程表主要是用户上课的内容,在排课阶段主要是看用户排的是什么课在哪个课程安排里展示。课程表和课程安排表是一对多的关系,一个课程可以有多个课程安排。但是在一个周期范围内,这个安排的数量始终是不会超过课程表的课时数量的。
举例来说single_session_count字段表示一次课程安排要消耗多少课时,如果值为 2,session_count课时数量是 10,那么这次课程周期一个用户只能排 5 次课程安排。
school_course_schedule(课程安排表)
CREATE TABLE `school_course_schedule` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '课程安排编号',
`campus_id` int NOT NULL COMMENT '校区ID',
`venue_id` int NOT NULL COMMENT '场地ID',
`course_date` date NOT NULL COMMENT '上课日期',
`time_slot` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '上课时段',
`course_id` int NOT NULL COMMENT '课程ID',
`coach_id` int NOT NULL COMMENT '上课教练ID',
`participants` json DEFAULT NULL COMMENT '参与人员列表,存储为JSON数组,包含学员ID和来源信息',
`student_ids` json DEFAULT NULL COMMENT '上课学生ID列表,存储为JSON数组',
`available_capacity` int DEFAULT NULL COMMENT '根据场地容量判断的可安排学员位置数量',
`status` enum('pending','upcoming','ongoing','completed') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'pending' COMMENT '课程状态: pending-待开始, upcoming-即将开始, ongoing-进行中, completed-已结束',
`auto_schedule` tinyint(1) DEFAULT NULL COMMENT '是否自动排课1是0否',
`created_by` enum('manual','system') COLLATE utf8mb4_general_ci NOT NULL COMMENT '课程安排创建方式: manual-人员安排, system-系统创建',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`deleted_at` int DEFAULT '0' COMMENT '逻辑删除时间',
`assistant_ids` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '助教ID列表(逗号分隔)',
`education_id` int DEFAULT NULL COMMENT '教务ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='课程安排表';
这个表是在学校层面针对教室的情况做的课程安排情况表。这个表和课程表是一对多的关系,一个课程可以有多个课程安排。而且支持一次配置后自动排课的功能。这个表的主要作用是记录课程安排的情况,包括上课日期,时间段,教练,参与人员等信息。
school_person_course_schedule(人员与课程安排关系表)
CREATE TABLE `school_person_course_schedule` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '关系编号',
`resources_id` int DEFAULT NULL COMMENT '资源ID',
`person_id` int DEFAULT NULL COMMENT '人员ID',
`student_id` int DEFAULT NULL COMMENT '学员ID',
`person_type` enum('student','customer_resource') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '人员类型: student-正式学员, customer_resource-客户资源,teacher教练',
`schedule_id` int NOT NULL COMMENT '课程安排ID',
`course_date` date NOT NULL COMMENT '上课日期',
`schedule_type` tinyint(1) DEFAULT NULL COMMENT '课程安排类型1临时课2固定课',
`course_type` tinyint(1) DEFAULT NULL COMMENT '课程类型1加课2补课3 等待位',
`time_slot` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '上课时段',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` int DEFAULT '0' COMMENT '删除',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态0待上课1已上课2请假',
`remark` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请假备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='人员与课程安排关系表';
这个表记录着学员和school_course_schedule中安排的关系。这里面有几种情况 1.正式的付费学员上课(临时的)2.临时的体验学员上课 3.正式的付费学员固定这个时段上课的。
然后这个课程安排的属性还有是正常消耗课时的,还是补课、还是送课。还是这个教室没有位置单纯是等待的课程。
school_student_courses(学员课程表)
CREATE TABLE `school_student_courses` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '记录编号',
`student_id` int NOT NULL COMMENT '学员ID',
`course_id` int NOT NULL COMMENT '课程ID',
`total_hours` int NOT NULL COMMENT '总正式课时数',
`gift_hours` int DEFAULT '0' COMMENT '赠送课时数',
`start_date` date NOT NULL COMMENT '课程开始日期',
`end_date` date NOT NULL COMMENT '课程结束日期',
`use_total_hours` int NOT NULL DEFAULT '0' COMMENT '已使用课包课时数',
`use_gift_hours` int NOT NULL DEFAULT '0' COMMENT '已使用课包赠送课时数',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`single_session_count` int DEFAULT NULL COMMENT '单次消课数量',
`status` tinyint(1) DEFAULT NULL COMMENT '课程状态1有效2过期3等待期4延期',
`resource_id` int DEFAULT NULL COMMENT '资源ID',
`main_coach_id` int DEFAULT NULL COMMENT '主教练ID',
`assistant_ids` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '助教ID列表(逗号分隔)',
`education_id` int DEFAULT NULL COMMENT '教务ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='学员课程表';
这个是一个学员在一个课程周期里可以上课的课时记录以及课时有效期记录,在这个周期范围内为这个学员服务的教练和助教信息。这个表的主要作用是记录学员的课程信息,包括总课时数,赠送课时数,开始和结束日期等信息。这个表和人员与课程安排关系表是一对多的关系,一个学员可以有多个课程安排。
school_student_course_usage(学员课程使用记录表)
CREATE TABLE `school_student_course_usage` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '记录编号',
`student_course_id` int NOT NULL COMMENT '学员课程ID(关联到student_courses表)',
`used_hours` int NOT NULL COMMENT '本次使用的课时数',
`usage_date` date NOT NULL COMMENT '课时使用日期',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='学员课时消费记录表';
这个表记录了学员在某个课程周期内使用的课时数,这个表和学员课程表是一对多的关系,一个学员可以有多个课时使用记录。
school_class(班级表)
CREATE TABLE `school_class` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '班级编号',
`campus_id` int NOT NULL COMMENT '校区ID',
`campus_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '校区名称',
`class_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '班级名称',
`head_coach` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '班继续
级主教练',
`age_group` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '班级授课年龄段',
`class_type` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '班级类型',
`assistant_coach` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '班级助教',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`deleted_at` int DEFAULT '0' COMMENT '逻辑删除时间',
`status` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '班级状态(1开启 2关闭)',
`sort_order` int NOT NULL COMMENT '班级排序',
`remarks` text COLLATE utf8mb4_general_ci COMMENT '班级备注',
`educational_id` int NOT NULL DEFAULT '0' COMMENT '教务id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='班级表';
学员报名时会分配班级,默认班级里的主教练和助教会被分配到学员课程表里。班级表主要是记录班级的信息,包括班级名称,主教练,助教,授课年龄段等信息。这个表和学员课程表是一对多的关系,一个班级可以有多个学员。
school_class_resources_rel(班级学员关系表)
CREATE TABLE `school_class_resources_rel` (
`id` int NOT NULL AUTO_INCREMENT,
`class_id` int NOT NULL COMMENT '班级id',
`resource_id` int DEFAULT NULL COMMENT '资源id',
`campus_id` int DEFAULT NULL COMMENT '校区id',
`source_id` int DEFAULT NULL COMMENT '数据id',
`source_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据资源类型student是学员,temporary是非正式学员',
`join_time` int DEFAULT NULL COMMENT '加入时间',
`out_time` int DEFAULT NULL COMMENT '离开时间',
`status` tinyint DEFAULT NULL COMMENT '状态1新入2续费3过期4转班5转校',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='班级和资源关系表';
这个表记录了班级和资源的关系,包括班级id,资源id,校区id,数据id,数据资源类型,加入时间,离开时间,状态等信息。这个表和班级表是一对多的关系,一个班级可以有多个资源。

56
uniapp/api/apiRoute.js

@ -397,8 +397,62 @@ export default {
return await http.post('/updateStudentCoursePersonnel', data);
},
// 获取订单支付二维码
// 获取订单支付二维码
async getOrderPayQrcode(data = {}) {
return await http.get('/getQrcode', data);
},
//↓↓↓↓↓↓↓↓↓↓↓↓-----课程安排相关接口-----↓↓↓↓↓↓↓↓↓↓↓↓
// 获取课程安排列表
async getCourseScheduleList(data = {}) {
return await http.get('/courseSchedule/list', data);
},
// 获取课程安排详情
async getCourseScheduleInfo(data = {}) {
return await http.get('/courseSchedule/info', data);
},
// 创建课程安排
async createCourseSchedule(data = {}) {
return await http.post('/courseSchedule/create', data);
},
// 批量创建课程安排
async batchCreateCourseSchedule(data = {}) {
return await http.post('/courseSchedule/batchCreate', data);
},
// 更新课程安排
async updateCourseSchedule(data = {}) {
return await http.post('/courseSchedule/update', data);
},
// 删除课程安排
async deleteCourseSchedule(data = {}) {
return await http.post('/courseSchedule/delete', data);
},
// 获取场地列表
async getCourseScheduleVenues(data = {}) {
return await http.get('/courseSchedule/venues', data);
},
// 获取场地可用时间
async getVenueAvailableTime(data = {}) {
return await http.get('/courseSchedule/venueAvailableTime', data);
},
// 检查教练时间冲突
async checkCoachConflict(data = {}) {
return await http.get('/courseSchedule/checkCoachConflict', data);
},
// 获取课程安排统计
async getCourseScheduleStatistics(data = {}) {
return await http.get('/courseSchedule/statistics', data);
},
// 学员加入课程安排
async joinCourseSchedule(data = {}) {
return await http.post('/courseSchedule/joinSchedule', data);
},
// 学员退出课程安排
async leaveCourseSchedule(data = {}) {
return await http.post('/courseSchedule/leaveSchedule', data);
},
// 获取筛选选项
async getCourseScheduleFilterOptions(data = {}) {
return await http.get('/courseSchedule/filterOptions', data);
},
}

240
uniapp/components/CommentList.vue

@ -1,240 +0,0 @@
<template>
<view>
<view style="" v-if="list.length>0">
<fui-collapse-item v-for="(item,index) in list" :key="index" :disabled="shouldDisableItem(item)" :arrow="shouldDisableItems(item)">
<view class="fui-item__box">
<view style="display: flex;width: 100%;position: relative;">
<view class="content_img" v-if="item.headimg != 0">
<image style="width: 50rpx;height:50rpx;border-radius: 50%;" :src="item.headimg"></image>
</view>
<view class="content_img" v-else>
<image style="width: 50rpx;height: 50rpx;border-radius: 50%;" src="/static/images/home/tixing.png"></image>
</view>
<view style="padding: 5rpx 20rpx;">
{{item.content}}
</view>
<view style="position: absolute;right: 7%;top: 1%;" @click="comments(item.comment_id)">
评论
</view>
</view>
<view class="middles_con" v-if="item.imagesarr!=0" style="">
<view style="width: 32%;height: 200rpx;margin:2rpx;" v-for="(item2, index2) in item.imagesarr"
:key="index2" @click="tankuang(item2,item.imagesarr)">
<image :src="item2" style="width: 100%;height: 100%;"></image>
</view>
</view>
</view>
<template v-slot:content>
<view class="fui-descr" v-if="item.comments_list.length>0">
<view class="flex" style="position: relative;" v-for="(item1,index1) in item.comments_list" :key="index1">
<view style="display: flex;width: 100%;position: relative;">
<view class="content_img" v-if="item1.headimg != 0">
<image style="width: 50rpx;height:50rpx;border-radius: 50%;" :src="item1.headimg"></image>
</view>
<view class="content_img" v-else>
<image style="width: 50rpx;height: 50rpx;border-radius: 50%;" src="/static/images/home/tixing.png"></image>
</view>
<view style="padding: 5rpx 20rpx;">
{{item1.content}}
</view>
</view>
<view class="middles_con" v-if="item1.imagesarr!=0" style="">
<view style="width: 32%;height: 200rpx;margin:2rpx;" v-for="(item2, index2) in item1.imagesarr"
:key="index2" @click="tankuang(item2,item1.imagesarr)">
<image :src="item2" style="width: 100%;height: 100%;"></image>
</view>
</view>
</view>
</view>
<view class="fui-descr" v-else style="text-align: center;">
暂无子评论
</view>
</template>
</fui-collapse-item>
</view>
<view style="font-size: 40rpx;font-weight: bold;text-align: center;padding-top: 50rpx;" v-else>
来当第一个评论的人吧!
</view>
<view style="margin-top: 30rpx;width: 100%;background-color: #fff;">
<view style="width: 95%;height: 200rpx;margin: auto;">
<textarea v-model="textAreaValue" placeholder="输入内容"
:style="{ width: '100%',padding:'30rpx'}"></textarea>
</view>
<view class="fui-section__title" style="width: 95%;margin: auto;z-index: 9999;">
<fui-upload :max="3" immediate :url="url" ref="upload" @complete="complete" @success="success"
:isDel="false">
<fui-icon name="plus"></fui-icon>
</fui-upload>
</view>
<fui-button background="#00be8c" width="95%" :margin="['35rpx','0','0','35rpx']" @click="submit()">
</fui-button>
</view>
<view style="height: 30rpx;width: 100%;"></view>
</view>
</template>
<script>
// import user from '@/api/user.js';
import fuiCollapse from "@/components/firstui/fui-collapse/fui-collapse.vue"
import fuiCollapseItem from "@/components/firstui/fui-collapse-item/fui-collapse-item.vue"
import fuiUpload from "@/components/firstui/fui-upload/fui-upload.vue"
import fuiIcon from "@/components/firstui/fui-icon/fui-icon.vue"
import fuiButton from "@/components/firstui/fui-button/fui-button.vue"
export default {
name: 'CommentList',
props: {
list: Array, //
actid: {
type: String,
default: '' //
}, //
um_id: {
type: String,
default: '' //
}, //
},
components: {
fuiCollapse,
fuiCollapseItem,
fuiUpload,
fuiIcon,
fuiButton
},
data() {
return {
url: 'http://medication.zeyan.wang/dnseyeapi/Base/upload1',
urls: [],
status: '',
textAreaValue: '',
lists: [],
listlength: ''
}
},
onLoad() {
this.actid = uni.getStorageSync('actid');
this.um_id = uni.getStorageSync('um_id');
this.fetchData(this.actid)
},
methods: {
fetchData(actid) {
user.comment_list({
act_id: actid
}).then(res => {
console.log(res)
if (res.status == 200) {
this.list = res.data
} else {
uni.showToast({
title: res.msg,
icon: 'none'
})
}
});
},
onPullDownRefresh(){
this.fetchData(this.actid)
},
complete(e) {
console.log(e)
this.status = e.status
// this.urls = e.urls
if (this.status === 'success' && e.action === 'upload') {
this.fui.toast('上传完成!')
// this.urls
// console.log(this.urls)
}
},
success(e) {
var responseString = e.res.data;
var cleanedString = responseString.replace('{"status":"200","msg":"文件上传成功","data":"', '').replace('"}',
'');
console.log(cleanedString)
this.urls += cleanedString + ','
},
submit() {
user.comment({
act_id: this.actid,
um_id: this.um_id,
content: this.textAreaValue,
image: this.urls,
}).then(res => {
console.log(res)
if (res.status == 200) {
this.fetchData(this.actid)
this.textAreaValue = ''
} else {
uni.showToast({
title: res.msg,
icon: 'none'
})
}
});
},
tankuang(url,arr){
uni.previewImage({
current: url,
urls: arr,
loop: true,
});
},
comments(id){
uni.setStorageSync('comment_id',id);
uni.redirectTo({
url: '/pages/index/comments'
});
},
shouldDisableItem(item){
return item.comments_list.length == 0;
},
shouldDisableItems(item){
return !item.comments_list.length == 0;
}
}
}
</script>
<style scoped>
.middles_con {
width: 100%;
display: flex;
margin: 20rpx 0;
font-size: 30rpx;
}
.flex {
padding: 20rpx 45rpx;
}
.fui-item__box {
width: 100%;
padding: 26rpx 32rpx;
box-sizing: border-box;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.fui-logo {
width: 48rpx;
height: 48rpx;
margin-right: 24rpx;
display: block;
}
.fui-descr {
width: 100%;
padding: 32rpx;
font-size: 28rpx;
line-height: 52rpx;
color: #7F7F7F;
word-break: break-all;
box-sizing: border-box;
}
</style>

166
uniapp/components/J-skeleton/J-skeleton.vue

@ -1,166 +0,0 @@
<template>
<view>
<view v-if="loading" class="skeleton" :class="{ animate: animate }" :style="{ justifyContent: flexType}">
<!-- 轮播图 -->
<view
v-if="imgTitle"
class="skeleton-imgTitle"
style="width: 95%;border-radius: 10px;height: 100px;display: block;"
></view>
<!-- 头像图 -->
<view
v-if="showAvatar && !imgTitle"
class="skeleton-avatar"
v-for="(item, index) in nameRow"
:key="index"
:class="[avatarShape]"
:style="{ width: avatarSize, height: avatarSize}"
></view>
<!-- 文字条 -->
<view class="skeleton-content" v-if="showTitle && !imgTitle">
<view class="skeleton-title" :style="{ width: titleWidth }"></view>
<view class="skeleton-rows">
<view
class="skeleton-row-item"
v-for="(item, index) in rowList"
:key="index"
:style="{ width: item.width }"
></view>
</view>
</view>
</view>
<view v-else><slot></slot></view>
</view>
</template>
<script>
const DEFAULT_ROW_WIDTH = '100%'
const DEFAULT_LAST_ROW_WIDTH = '60%'
export default {
props: {
loading: {
type: Boolean,
default: true,
},
imgTitle: {
type: Boolean,
default: false,
},
nameRow:{
type: Number,
default: 1,
},
flexType:{
type: String,
default: 'flex-start', // center space-between space-around flex-start flex-end
},
showAvatar: {
type: Boolean,
default: true,
},
avatarSize: {
type: String,
default: '50px',
},
avatarShape: {
type: String,
default: 'round', // square | round
},
showTitle: {
type: Boolean,
default: false,
},
titleWidth: {
type: String,
default: '40%',
},
row: {
type: Number,
default: 3,
},
animate: {
type: Boolean,
default: true,
},
},
data() {
return {}
},
computed: {
rowList() {
let list = []
for (let i = 0; i < this.row; i++) {
list.push({
width: i === this.row - 1 && i !== 0 ? DEFAULT_LAST_ROW_WIDTH : DEFAULT_ROW_WIDTH,
})
}
return list
},
},
}
</script>
<style scoped>
.skeleton {
display: flex;
margin: 16px;
--bg-color: #f2f3f5;
--row-height: 16px;
--row-margin-top: 16px;
}
.skeleton-imgTitle {
flex-wrap: wrap;
background: var(--bg-color);
margin: 10px auto;
}
.skeleton-avatar {
flex-shrink: 0;
background: var(--bg-color);
margin-right: 8px;
}
.skeleton-avatar.round {
border-radius: 50%;
}
.skeleton-content {
width: 100%;
}
.skeleton-title {
background-color: var(--bg-color);
height: var(--row-height);
}
.skeleton-title + .skeleton-rows {
margin-top: var(--row-margin-top);
}
.skeleton-rows {
}
.skeleton-row-item {
background-color: var(--bg-color);
height: var(--row-height);
}
.skeleton-row-item:not(:first-child) {
margin-top: var(--row-margin-top);
}
.skeleton.animate {
animation: skeleton-blink 1.2s ease-in-out infinite;
}
@keyframes skeleton-blink {
0% {
opacity: 1;
}
50% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
</style>

77
uniapp/components/J-skeleton/README.md

@ -1,77 +0,0 @@
# skeleton
感谢原作者 https://ext.dcloud.net.cn/plugin?id=852
自己项目非常需要骨架,正好原作者发布了1.0 根据自己项目 自己修改了下。
目前仅支持:
1.轮播图
2.分类栏
3.头像
4.文章条
5.动态心情
以上是根据自己项目修改的,后续再拓展,或者自己根据自己项目修改,原作者写的还是很灵活的,修改方便!
## 属性说明
|属性名|类型|默认值|说明|
| -- | -- | --|--|
| loading | Boolean | true | 是否显示占位图 |
| flexType | String | flex-start | 排列方式 center 居中 √ space-between 两端对齐 √ space-around 子元素拉手分布 √ flex-start 居左 flex-end 居右 |
| imgTitle | Boolean | false | 轮播图占位图 |
| showAvatar | Boolean | true | 是否显示头像占位图 |
| nameRow | Number | 1 | 显示头像圆1个 |
| avatarSize | String | 50px | 头像站占位图大小 |
| avatarShape | String | round | 头像形状,可选值:round, square |
| showTitle | Boolean | true | 是否显示标题占位图 |
| titleWidth | String | 40% | 标题占位图宽度 |
| row | Number| 3 | 标题段落占位图行数 |
| animate | Boolean | true | 是否开启动画 |
## 使用示例
```html
<skeleton
:loading="loading"
:avatarSize="skeleton1.avatarSize"
:row="skeleton1.row"
:showTitle="skeleton1.showTitle"
>
<view class="section-content">我是段落1</view>
</skeleton>
```
```javascript
import Skeleton from '../components/skeleton/index.vue'
export default {
components: {
Skeleton
},
data() {
return {
loading: true,
skeleton1 : {
avatarSize: '52px',
row: 3,
showTitle: true,
}
}
},
created() {
this.reloadData()
},
methods: {
reloadData() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 3000)
},
},
}
```
## 效果图
![](http://images.alisali.cn/img_20191014113211.png)

438
uniapp/components/aui-dialog/aui-dialog.vue

@ -1,438 +0,0 @@
<template name="aui-dialog">
<view class="aui-dialog" v-if="SHOW" :class="{'aui-dialog-in': FADE==1, 'aui-dialog-out': FADE==0}">
<view class="aui-mask" v-if="mask" @touchmove.stop.prevent @click.stop="maskTapClose ? hide() : ''"></view>
<view class="aui-dialog-main"
:class="{
'aui-dialog-main-style-1': theme==1,
'aui-dialog-main-style-2': theme==2,
'aui-dialog-main-style-3': theme==3
}"
>
<view class="aui-dialog-title" v-if="title">{{title}}</view>
<view class="aui-dialog-content" v-if="msg!=''" :style="{'text-align': msg.length > 15 ? 'left' : 'center'}" v-html="msg"></view>
<view class="aui-dialog-content" v-if="items.length > 0">
<view class="aui-dialog-input-list" v-for="(item, index) in items" :key="index" :data-index="index">
<view class="aui-dialog-input-label" v-if="item.label">{{item.label}}</view>
<view class="aui-dialog-input-list-input">
<input :type="item.type ? item.type : 'text'" :value="item.value" :data-index="index" @input="_onInput" :placeholder="item.placeholder" />
</view>
</view>
</view>
<view class="aui-dialog-down">
<view
class="aui-dialog-down-btn"
v-for="(item, index) in btns"
:class="{'aui-dialog-down-cancel-btn': item.name=='取消', 'aui-dialog-down-delete-btn': item.name=='删除'}"
:key="index"
:data-index="index"
:style="{
'color': touchIndex == index ? touchStyle.color : item.color,
'background': touchIndex == index ? touchStyle.background : '',
'width': theme==1?'calc(100% / '+ btns.length +')':''
}"
@click.stop="_btnTab($event)"
@touchstart="_btnTouchStart($event)"
@touchmove="_btnTouchEnd($event)"
@touchend="_btnTouchEnd($event)"
>{{item.name}}</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "aui-dialog",
props: {
title: { //
type: String,
default: ''
},
msg: { //
type: String,
default: ''
},
mask: { //false
type: Boolean,
default: true
},
maskTapClose: { //
type: Boolean,
default: true
},
btns: { //("row")("col")
type: Array,
default (){
return [
{name: '确定', color: '#197DE0', isTouch: false}
]
}
},
items: {
type: Array,
default (){
return [
{label: '', type: 'text', value: '', placeholder: ''}
]
}
},
theme: { //
type: Number,
default: 1
},
},
data() {
return {
SHOW: false,
FADE: -1,
ITEMS: [],
touchIndex: -1, //
touchStyle: { //
color: '',
background: '#EFEFEF'
}
};
},
created(){
var _this = this;
},
onLoad(){
},
methods:{
//
show(){
var _this = this;
return new Promise(function(resolve, reject){
_this.SHOW = true;
var _showtimer = setTimeout(()=>{
_this.FADE = 1;
clearTimeout(_showtimer);
},50)
resolve();
});
},
//
hide(){
var _this = this;
return new Promise(function(resolve, reject){
_this.FADE = 0;
var _hidetimer = setTimeout(()=>{
_this.SHOW = false;
_this.FADE = -1;
clearTimeout(_hidetimer);
},50)
resolve();
});
},
//
_btnTab(e){
var _this = this,
index = Number(e.currentTarget.dataset.index);
_this.hide();
var _closetimer = setTimeout(()=>{
var data = {
status: 0,
msg: _this.btns[index].name,
index: index
};
_this.$emit("callback", data);
clearTimeout(_closetimer);
},100)
},
//
_onInput(e){
var _this = this,
index = Number(e.currentTarget.dataset.index),
value = e.detail.value;
if(_this.ITEMS.length <= 0)
{
_this.items.forEach((item, index)=>{
_this.ITEMS.push({label: item.label, type: item.type, value: item.value, placeholder: item.placeholder});
});
}
_this.$set(_this.ITEMS[index], 'value', value);
},
getVal(){
var _this = this;
setTimeout(()=>{
_this.ITEMS = [];
},200)
return _this.ITEMS;
},
_btnTouchStart(e){
var _this = this,
index = Number(e.currentTarget.dataset.index);
_this.touchIndex = index;
},
_btnTouchEnd(e){
var _this = this,
index = Number(e.currentTarget.dataset.index);
_this.touchIndex = -1;
},
}
}
</script>
<style>
/* dialog 模态弹窗样式 */
.aui-dialog{
width: 100vw;
height: 100vh;
opacity: 0;
position: fixed;
top: 0;
left: 0;
z-index: 999;
}
.aui-dialog-main{
min-width: 280px;
max-width: 300px;
background: #fff;
border-radius: 13px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transition-property: -webkit-transform,opacity;
transition-property: transform,opacity;
-webkit-transform: translate3d(-50%,-50%,0) scale(1.185);
transform: translate3d(-50%,-50%,0) scale(1.185);
opacity: 0;
z-index: 999;
}
.aui-dialog.aui-dialog-in{
-webkit-transition-duration: 100ms;
transition-duration: 100ms;
opacity: 1;
}
.aui-dialog.aui-dialog-out{
-webkit-transition-duration: 100ms;
transition-duration: 100ms;
opacity: 0;
}
.aui-dialog.aui-dialog-in .aui-mask{
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
opacity: 1;
}
.aui-dialog.aui-dialog-out .aui-mask{
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
opacity: 0;
}
.aui-dialog.aui-dialog-out .aui-dialog-main{
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
-webkit-transform: translate3d(-50%,-50%,0) scale(0.8);
transform: translate3d(-50%,-50%,0) scale(0.8);
opacity: 0
}
.aui-dialog.aui-dialog-in .aui-dialog-main{
-webkit-transition-duration: 200ms;
transition-duration: 200ms;
-webkit-transform: translate3d(-50%,-50%,0) scale(1);
transform: translate3d(-50%,-50%,0) scale(1);
opacity: 1;
}
.aui-dialog-title{
width: 100%;
height: 40px;
line-height: 55px;
position: relative;
font-size: 18px;
/*font-weight: bolder;*/
display: inline-block;
border-top-left-radius: 13px;
border-top-right-radius: 13px;
text-align: center;
color: #333;
box-sizing: border-box;
}
.aui-dialog-content{
width: 100%;
max-height: 70vh;
line-height: 27px;
font-size: 16px;
color: #555555;
text-align: center;
display: inline-block;
overflow-y: scroll;
padding: 30px 20px 25px 20px;
box-sizing: border-box;
}
.aui-dialog-content::-webkit-scrollbar {
width: 0px;
}
.aui-dialog-down{
width: 100%;
height: 50px;
text-align: right;
position: relative;
overflow: hidden;
}
.aui-dialog-down-btn{
width: auto;
height: 100%;
display: inline-block;
font-size: 17px;
color: #197DE0;
text-align: center;
position: relative;
}
.aui-dialog-down-btn.active{
background: #EFEFEF;
}
.aui-dialog-down-cancel-btn{
color: #909090;
}
.aui-dialog-down-delete-btn{
color: #FF0000;
}
.aui-dialog-main-style-1 .aui-dialog-content{
text-align: center;
}
.aui-dialog-main-style-1 .aui-dialog-down{
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.aui-dialog-main-style-1 .aui-dialog-down-btn{
line-height: 50px;
display: flex;
justify-content: center;
align-items: center;
flex: auto;
}
.aui-dialog-main-style-1 .aui-dialog-down:before{
content: '';
width: 100%;
height: 1px;
-ms-transform: scaleY(.3);
-webkit-transform: scaleY(.3);
transform: scaleY(.3);
background: rgba(100,100,100,.3);
position: absolute;
top: 0;
left: 0;
z-index: 999;
}
.aui-dialog-main-style-1 .aui-dialog-down-btn:first-child{
border-bottom-left-radius: 13px;
}
.aui-dialog-main-style-1 .aui-dialog-down-btn:last-child{
border-bottom-right-radius: 13px;
}
.aui-dialog-main-style-1 .aui-dialog-down-btn:after{
content: '';
width: 1px;
height: 100%;
-ms-transform: scaleX(.3);
-webkit-transform: scaleX(.3);
transform: scaleX(.3);
background: rgba(100,100,100,.3);
position: absolute;
top: 0;
right: 0;
z-index: 999;
}
.aui-dialog-main-style-1 .aui-dialog-down-btn:last-child:after{display: none;}
.aui-dialog-main-style-2{
border-radius: 6px;
}
.aui-dialog-main-style-2 .aui-dialog-title{
padding: 0 15px;
box-sizing: border-box;
}
.aui-dialog-main-style-2 .aui-dialog-down{
height: 40px;
padding: 0 10px 10px 10px;
box-sizing: border-box;
}
.aui-dialog-main-style-2 .aui-dialog-down-btn{
height: 30px;
line-height: 30px;
padding: 0 10px;
margin: 0 0 0 10px;
}
.aui-dialog-main-style-3 .aui-dialog-down{
height: auto;
}
.aui-dialog-main-style-3 .aui-dialog-down-btn{
width: 100%;
line-height: 50px;
}
.aui-dialog-main-style-3 .aui-dialog-down-btn:before{
content: '';
width: 100%;
height: 1px;
-ms-transform: scaleY(.3);
-webkit-transform: scaleY(.3);
transform: scaleY(.3);
background: rgba(100,100,100,.4);
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.aui-dialog-main-style-3 .aui-dialog-down-btn:last-child{
border-bottom-left-radius: 13px;
border-bottom-right-radius: 13px;
}
.aui-dialog-main-style-3 .aui-dialog-down-btn:first-child:after{display: none;}
/*input 输入弹窗样式设置*/
.aui-dialog-input-list{
width: 100%;
position: relative;
text-align: left;
}
.aui-dialog-input-list .aui-dialog-input-label{
width: 260px;
height: 40px;
line-height: 40px;
display: inline-block;
font-size: 16px;
color: #646464;
}
.aui-dialog-input-list-input{
width: 100%;
background: #FFFFFF;
border-radius: 3px;
border: none;
box-sizing: border-box;
padding: 2px;
margin: 0 0 15px 0;
color: #515151;
position: relative;
}
.aui-dialog-input-list input{
width: 100%;
height: 40px;
line-height: 20px;
border-radius: 3px;
border: none;
margin: 0;
padding: 0 10px;
box-sizing: border-box;
font-size: 15px;
color: #515151;
position: relative;
z-index: 1;
}
.aui-dialog-input-list-input:after{
content: '';
width: 200%;
height: 200%;
border: 1px solid rgba(100,100,100,.3);
-ms-transform: scale(.5, .5);
-webkit-transform: scale(.5, .5);
transform: scale(.5, .5);
position: absolute;
top: -50%;
left: -50%;
border-radius: 10px;
z-index: 0;
}
</style>

292
uniapp/components/aui-dialog/common/aui/css/aui.css

@ -1,292 +0,0 @@
.aui-content{
width: 100%;
height: 100vh;
/* #ifndef MP */
height: -webkit-calc(100vh - 44px);
height: calc(100vh - 44px);
/* #endif */
background: #EFEFEF;
overflow-y: scroll;
padding: 0;
box-sizing: border-box;
position: relative;
}
/* 横向分割线 */
.row-before{position: relative;}
.row-before:before{content: ''; width: 100%; height: 1px !important; background: rgba(100,100,100,.3); -ms-transform: scaleY(.3); -webkit-transform: scaleY(.3); transform: scaleY(.3); position: absolute; top: 0; right: 0; left: auto; z-index: 1;}
.row-after{position: relative;}
.row-after:after{content: ''; width: 100%; height: 1px !important; background: rgba(100,100,100,.3); -ms-transform: scaleY(.3); -webkit-transform: scaleY(.3); transform: scaleY(.3); position: absolute; bottom: 0; right: 0; left: auto; z-index: 1;}
/* 纵向分割线 */
.col-before{position: relative;}
.col-before:before{content: ''; width: 1px !important; height: 100%; background: rgba(100,100,100,.3); -ms-transform: scaleX(.3); -webkit-transform: scaleX(.3); transform: scaleX(.3); position: absolute; top: 0; left: 0; z-index: 1;}
.col-after{position: relative;}
.col-after:after{content: ''; width: 1px !important; height: 100%; background: rgba(100,100,100,.3); -ms-transform: scaleX(.3); -webkit-transform: scaleX(.3); transform: scaleX(.3); position: absolute; top: 0; right: 0; z-index: 1;}
/*按钮边框线*/
.border{position: relative;}
.border:after{content: ''; width: -webkit-calc(200% - 2px); width: calc(200% - 2px); height: -webkit-calc(200% - 2px); height: calc(200% - 2px); border-radius: 3px; border: 1px solid rgba(100,100,100,.3); position: absolute; left: -50%; top: -50%; -ms-transform: scale(.5, .5); -webkit-transform: scale(.5, .5); transform: scale(.5, .5); z-index: 1;}
.aui-lists{
width: 100%;
}
.aui-list{
width: 100%;
height: 55px;
font-size: 0;
padding: 0 15px;
background: #FFFFFF;
box-sizing: border-box;
position: relative;
z-index: 1;
}
.aui-list:after{
content: '';
width: 100%;
height: 1px;
background: rgba(100,100,100,.3);
-ms-transform: scaleY(.3);
-webkit-transform: scaleY(.3);
transform: scaleY(.3);
position: absolute;
bottom: 0;
left: 0;
}
.aui-list:last-child:after{
display: none;
}
.aui-list-title{
width: 100%;
height: 44px;
line-height: 44px;
font-size: 14px;
padding: 0 15px;
box-sizing: border-box;
color: #999;
display: inline-block;
}
.aui-list-left{
height: 100%;
line-height: 55px;
font-size: 15px;
color: #333;
display: inline-block;
vertical-align: top;
}
.aui-list-right{
height: 100%;
display: inline-block;
vertical-align: top;
float: right;
}
.aui-list-right .aui-btn-right{
height: 55px;
text-align: center;
line-height: 55px;
font-size: 14px;
display: inline-block;
color: #aaa;
vertical-align: top;
}
.aui-btn{
width: -webkit-calc(100% - 30px);
width: calc(100% - 30px);
height: 50px;
line-height: 50px;
text-align: center;
border: none;
color: #333;
font-size: 15px;
border-radius: 5px;
margin: 0 15px 15px 15px;
padding: 0 10px;
transition: background-color .2s;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
}
.aui-btn-blue{
background: #197DE0;
color: #FFF;
}
/* 遮罩层样式 */
.aui-mask{
width: 100%;
height: 100%;
background: rgba(0,0,0,.6);
-ms-animation: aui-fade-in .2s ease-out forwards;
-webkit-animation: aui-fade-in .2s ease-out forwards;
animation: aui-fade-in .2s ease-out forwards;
position: fixed;
top: 0px;
left: 0px;
z-index: 998;
}
/* 动画设计 */
/* fade-in */
@-ms-keyframes aui-fade-in{
0%{opacity: 0;}
100%{opacity: 1;}
}
@-webkit-keyframes aui-fade-in{
0%{opacity: 0;}
100%{opacity: 1;}
}
@keyframes aui-fade-in{
0%{opacity: 0;}
100%{opacity: 1;}
}
/* fade-out */
@-ms-keyframes aui-fade-out{
0%{opacity: 1;}
100%{opacity: 0;}
}
@-webkit-keyframes aui-fade-out{
0%{opacity: 1;}
100%{opacity: 0;}
}
@keyframes aui-fade-out{
0%{opacity: 1;}
100%{opacity: 0;}
}
/* aui-scale-in */
@-ms-keyframes aui-scale-in{
0%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
@-webkit-keyframes aui-scale-in{
0%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
@keyframes aui-scale-in{
0%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
/* aui-scale-out */
@-ms-keyframes aui-scale-out{
0%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
100%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
}
@-webkit-keyframes aui-scale-out{
0%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
100%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
}
@keyframes aui-scale-out{
0%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
100%{-ms-transform: scale(0.8); -webkit-transform: scale(0.8); transform: scale(0.8);}
}
/* aui-scale-in-tosmall */
@-ms-keyframes aui-scale-in-tosmall{
0%{-ms-transform: scale(1.2); -webkit-transform: scale(1.2); transform: scale(1.2);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
@-webkit-keyframes aui-scale-in-tosmall{
0%{-ms-transform: scale(1.2); -webkit-transform: scale(1.2); transform: scale(1.2);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
@keyframes aui-scale-in-tosmall{
0%{-ms-transform: scale(1.2); -webkit-transform: scale(1.2); transform: scale(1.2);}
100%{-ms-transform: scale(1); -webkit-transform: scale(1); transform: scale(1);}
}
/* aui-scale-in-tosmall-dialog */
@-ms-keyframes aui-scale-in-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1.16); -webkit-transform: translate3d(-50%,-50%,0) scale(1.16); transform: translate3d(-50%,-50%,0) scale(1.16); opacity: 0;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3(-50%,-50%,0) scale(1); opacity: 1;}
}
@-webkit-keyframes aui-scale-in-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1.16); -webkit-transform: translate3d(-50%,-50%,0) scale(1.16); transform: translate3d(-50%,-50%,0) scale(1.16); opacity: 0;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3(-50%,-50%,0) scale(1); opacity: 1;}
}
@keyframes aui-scale-in-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1.16); -webkit-transform: translate3d(-50%,-50%,0) scale(1.16); transform: translate3d(-50%,-50%,0) scale(1.16); opacity: 0;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3(-50%,-50%,0) scale(1); opacity: 1;}
}
/* aui-scale-out-tosmall-dialog */
@-ms-keyframes aui-scale-out-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3d(-50%,-50%,0) scale(1); opacity: 1;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(0.8); -webkit-transform: translate3d(-50%,-50%,0) scale(0.8); transform: translate3(-50%,-50%,0) scale(0.8); opacity: 0;}
}
@-webkit-keyframes aui-scale-out-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3d(-50%,-50%,0) scale(1); opacity: 1;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(0.8); -webkit-transform: translate3d(-50%,-50%,0) scale(0.8); transform: translate3(-50%,-50%,0) scale(0.8); opacity: 0;}
}
@keyframes aui-scale-out-tosmall-dialog{
0%{-ms-transform: translate3d(-50%,-50%,0) scale(1); -webkit-transform: translate3d(-50%,-50%,0) scale(1); transform: translate3d(-50%,-50%,0) scale(1); opacity: 1;}
100%{-ms-transform: translate3d(-50%,-50%,0) scale(0.8); -webkit-transform: translate3d(-50%,-50%,0) scale(0.8); transform: translate3(-50%,-50%,0) scale(0.8); opacity: 0;}
}
/* aui-slide-up */
@-ms-keyframes aui-slide-up{
0%{bottom: -40vh;}
100%{bottom: 10px;}
}
@-webkit-keyframes aui-slide-up{
0%{bottom: -40vh;}
100%{bottom: 10px;}
}
@keyframes aui-slide-up{
0%{bottom: -40vh;}
100%{bottom: 10px;}
}
/* aui-slide-down */
@-ms-keyframes aui-slide-down{
0%{bottom: 10px;}
100%{bottom: -40vh;}
}
@-webkit-keyframes aui-slide-down{
0%{bottom: 10px;}
100%{bottom: -40vh;}
}
@keyframes aui-slide-down{
0%{bottom: 10px;}
100%{bottom: -40vh;}
}
/* aui-slide-up-screen */
@-ms-keyframes aui-slide-up-screen{
0%{bottom: -60vh;}
100%{bottom: 0px;}
}
@-webkit-keyframes aui-slide-up-screen{
0%{bottom: -60vh;}
100%{bottom: 0px;}
}
@keyframes aui-slide-up-screen{
0%{bottom: -60vh;}
100%{bottom: 0px;}
}
/* aui-slide-down-screen */
@-ms-keyframes aui-slide-down-screen{
0%{bottom: 0px;}
100%{bottom: -60vh;}
}
@-webkit-keyframes aui-slide-down-screen{
0%{bottom: 0px;}
100%{bottom: -60vh;}
}
@keyframes aui-slide-down-screen{
0%{bottom: 0px;}
100%{bottom: -60vh;}
}
@-webkit-keyframes aui-slide-up_to_middle {
0%{opacity: 0; top: -50vh; -ms-transform: translate(0,0); -webkit-transform: translate(0,0); transform: translate(0,0);}
100%{opacity: 1; top: 45%; -ms-transform: translate(0, -50%); -webkit-transform: translate(0, -50%); transform: translate(0, -50%);}
}
@keyframes aui-slide-up_to_middle {
0%{opacity: 0; top: -50vh; -ms-transform: translate(0,0); -webkit-transform: translate(0,0); transform: translate(0,0);}
100%{opacity: 1; top: 45%; -ms-transform: translate(0, -50%); -webkit-transform: translate(0, -50%); transform: translate(0, -50%);}
}
@-webkit-keyframes aui-slide-middle_to_up {
0%{opacity: 1; top: 45%; -ms-transform: translate(0, -50%); -webkit-transform: translate(0, -50%); transform: translate(0, -50%);}
100%{opacity: 0; top: -50vh; -ms-transform: translate(0,0); -webkit-transform: translate(0,0); transform: translate(0,0);}
}
@keyframes aui-slide-middle_to_up {
0%{opacity: 1; top: 45%; -ms-transform: translate(0, -50%); -webkit-transform: translate(0, -50%); transform: translate(0, -50%);}
100%{opacity: 0; top: -50vh; -ms-transform: translate(0,0); -webkit-transform: translate(0,0); transform: translate(0,0);}
}

1
uniapp/components/aui-dialog/common/aui/css/aui.iconfont.css

File diff suppressed because one or more lines are too long

55
uniapp/components/aui-dialog/common/aui/js/aui.js

@ -1,55 +0,0 @@
const aui = {
console: function(str){
console.log(str);
},
/***
@param {string} url 页面路径
@param {Object} opts 参数 {id: ''}
@example: aui.openWin("index.html", {id: 1})
*/
openWin(url, opts){
var _this = this;
var str = '?';
for(var i in opts){
if(_this.isDefine(opts[i])){
str += i + '=' + opts[i] + '&';
}
}
uni.navigateTo({
url: _this.isDefine(opts) ? url + str : url
})
},
/***
@example: aui.closeWin()
*/
closeWin(callback){
//直接关闭页面,并向后台发送数据
if(typeof callback == "function"){
if(window.addEventListener) {
window.addEventListener("beforeunload", callback, false);
} else {
window.attachEvent("onbeforeunload", callback, false);
}
}
uni.navigateBack({
delta: 1
});
},
/***
@param {string} str 变量
@example: aui.isDefine("变量");
*/
isDefine(str){
if (str == null || str == "" || str == "undefined" || str == undefined || str == "null" || str == "(null)" || str == 'NULL' || typeof (str) == 'undefined'){
return false;
}else{
str = str + "";
str = str.replace(/\s/g, "");
if (str == ""){return false;}
return true;
}
},
}
export {
aui
}

181
uniapp/components/coolc-coupon/coolc-coupon.vue

@ -1,181 +0,0 @@
<template>
<view class="coupon-item">
<view class="coupon-money">
<view class="nick" v-if="!types">{{item.full}}使用</view>
<view class="layof" :style="{color:theme}">{{item.reduce}}</view>
<view class="end_time">{{item.end_time}}前使用</view>
<view v-if="!types">
<!-- <view class="tit">券号{{item.ticket}}</view> -->
<view class="demand">{{item.coupon.name}}</view>
</view>
</view>
<!-- <view class="get-btn" v-if="types" :style="{color:color, borderColor:color, background:solid}">选择使用</view> -->
<button @tap="jump" class="get-btn" v-if="item.status == 0" :style="{color:color, borderColor:color, background:solid}">立即使用</button>
<image v-else-if="item.status == 1" class="img" src="../../static/icon-img/used.png" mode=""></image>
<image v-else-if="item.status == 3" class="img" src="../../static/icon-img/guoqi.png" mode=""></image>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
}
},
mounted() {
},
props: {
item: {
type: Object
},
types: {
type: String,
default: ''
},
theme: {
type: String,
default: '#ff9000'
},
solid: {
type: String,
default: '#ffffff'
},
color: {
type: String,
default: '#ff9000'
},
},
methods: {
jump() {
uni.switchTab({
url: '../../pages/index/index'
})
}
}
}
</script>
<style lang='scss'>
.coupon-item {
width: 100%;
height: auto;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 10upx;
padding: 0 20upx;
margin-top: 22upx;
border: 1px solid #eeeeee;
position: relative;
background: linear-gradient(to bottom right, transparent, #DBA871);
.coupon-money {
width: 465upx;
height: auto;
display: table;
float: left;
padding: 26upx 0;
border-style: none dotted none none;
border-color: #eeeeee;
.nick {
width: 100%;
height: 50upx;
line-height: 30upx;
font-size: $font-sm;
color: $font-color-999;
}
.tit {
width: 100%;
height: 50upx;
line-height: 50upx;
font-size: $font-sm;
color: $font-color-999;
}
.demand {
width: 100%;
height: 30upx;
line-height: 30upx;
font-size: $font-sm;
color: $font-color-999;
}
.layof {
width: 100%;
height: 48upx;
line-height: 30upx;
font-size: 44upx;
color: #ff9000;
font-weight: bold;
}
.end_time {
width: 100%;
height: 30upx;
line-height: 30upx;
font-size: $font-sm;
color: $font-color-999;
margin-bottom: 10px;
}
}
.img {
position: absolute;
width: 150rpx;
height: 150rpx;
right: 28upx;
top: 40upx;
}
.get-btn {
width: 160upx;
height: 52upx;
line-height: 50upx;
position: absolute;
top: 50%;
right: 26upx;
margin-top: -26upx;
text-align: center;
border-radius: 60upx;
color: #ff9000;
border: 1px solid #ff9000;
font-size: $font-sm;
float: right;
}
}
.coupon-item:after {
width: 40upx;
height: 20upx;
position: absolute;
left: 460upx;
top: -1px;
border-radius: 0 0 40upx 40upx;
content: "";
display: block;
background: #F8F8F8;
border: 1px solid #eeeeee;
border-top: 0px;
}
.coupon-item:before {
width: 40upx;
height: 20upx;
position: absolute;
left: 460upx;
bottom: -1px;
border-radius: 40upx 40upx 0 0;
content: "";
display: block;
background: #F8F8F8;
border: 1px solid #eeeeee;
border-bottom: 0px;
}
</style>

234
uniapp/components/custom-modal/example.vue

@ -1,234 +0,0 @@
<template>
<view class="container">
<fui-button @click="showSuccessModal = true" text="显示成功弹窗"></fui-button>
<fui-button @click="showConfirmModal = true" text="显示确认弹窗"></fui-button>
<fui-button @click="showCustomModal = true" text="显示自定义弹窗"></fui-button>
<!-- 成功弹窗示例 -->
<custom-modal
:show="showSuccessModal"
width="600"
@cancel="handleModalCancel"
>
<fui-icon name="checkbox-fill" :size="108" color="#09BE4F"></fui-icon>
<text class="fui-title">购买成功</text>
<text class="fui-descr">成功购买一张月卡可免费阅读30天</text>
<template #buttons>
<fui-button
text="我知道了"
width="240rpx"
height="72rpx"
:size="28"
radius="36rpx"
background="#FFB703"
borderWidth="0"
:margin="['0','0','24rpx']"
@click="handleButtonClick('success_confirm')"
/>
</template>
</custom-modal>
<!-- 确认弹窗示例 -->
<custom-modal
:show="showConfirmModal"
width="500"
@cancel="handleModalCancel"
>
<fui-icon name="warning-fill" :size="108" color="#FF6B35"></fui-icon>
<text class="fui-title">确认删除</text>
<text class="fui-descr">删除后无法恢复确定要继续吗</text>
<template #buttons>
<fui-button
text="取消"
width="200rpx"
height="72rpx"
:size="28"
radius="36rpx"
background="#F5F5F5"
color="#333"
borderWidth="0"
:margin="['0','0','12rpx']"
@click="handleButtonClick('confirm_cancel')"
/>
<fui-button
text="确定删除"
width="200rpx"
height="72rpx"
:size="28"
radius="36rpx"
background="#FF6B35"
borderWidth="0"
@click="handleButtonClick('confirm_delete')"
/>
</template>
</custom-modal>
<!-- 自定义内容弹窗示例 -->
<custom-modal
:show="showCustomModal"
width="700"
:showClose="false"
@cancel="handleModalCancel"
>
<view class="custom-content">
<text class="custom-title">支付二维码</text>
<view class="custom-form">
<fui-qrcode :value="qrcode"></fui-qrcode>
</view>
</view>
<template #buttons>
<view class="button-row">
<fui-button
text="发送二维码给用户"
width="200rpx"
height="72rpx"
:size="28"
radius="36rpx"
background="#007AFF"
borderWidth="0"
@click="handleButtonClick('custom_submit')"
/>
</view>
</template>
</custom-modal>
</view>
</template>
<script>
import CustomModal from './custom-modal.vue'
export default {
components: {
CustomModal
},
data() {
return {
showSuccessModal: false,
showConfirmModal: false,
showCustomModal: false,
qrcode: 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET',
formData: {
name: '',
phone: ''
}
}
},
methods: {
//
handleModalCancel(type) {
console.log('弹窗取消:', type)
this.showSuccessModal = false
this.showConfirmModal = false
this.showCustomModal = false
},
//
handleButtonClick(action) {
console.log('按钮点击:', action)
switch(action) {
case 'success_confirm':
this.showSuccessModal = false
uni.showToast({
title: '确认成功',
icon: 'success'
})
break
case 'confirm_cancel':
this.showConfirmModal = false
break
case 'confirm_delete':
this.showConfirmModal = false
uni.showToast({
title: '删除成功',
icon: 'success'
})
break
case 'custom_cancel':
this.showCustomModal = false
break
case 'custom_submit':
if (!this.formData.name || !this.formData.phone) {
uni.showToast({
title: '请填写完整信息',
icon: 'none'
})
return
}
this.showCustomModal = false
uni.showToast({
title: '提交成功',
icon: 'success'
})
//
this.formData = {
name: '',
phone: ''
}
break
}
}
}
}
</script>
<style lang="less" scoped>
.container {
padding: 40rpx;
display: flex;
flex-direction: column;
gap: 30rpx;
}
.fui-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
text-align: center;
margin: 20rpx 0;
}
.fui-descr {
font-size: 28rpx;
color: #666;
text-align: center;
margin: 0 0 30rpx 0;
line-height: 1.5;
}
.custom-content {
width: 100%;
padding: 20rpx;
}
.custom-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
text-align: center;
display: block;
margin-bottom: 30rpx;
}
.custom-form {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.button-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 40rpx;
}
</style>

393
uniapp/components/modal/modal.vue

@ -1,393 +0,0 @@
<template>
<view @touchmove.stop.prevent>
<view class="modal-box" :style="{width:width,padding:padding,borderRadius:radius}" :class="[(fadein || show)?'modal-normal':'modal-scale',show?'modal-show':'']">
<view v-if="custom">
<slot></slot>
</view>
<view v-else>
<view class="modal-title" v-if="title">{{title}}</view>
<view class="modal-content" :class="[title?'':'mtop']" :style="{color:color,fontSize:size+'rpx'}">
<slot></slot>
</view>
<view class="modalBtn-box" :class="[button.length!=2?'flex-column':'']">
<block v-for="(item,index) in button" :key="index">
<button class="modal-btn"
:class="[
''+(item.type || 'primary')+(item.plain?'-outline':''),
button.length!=2?'btn-width':'',
button.length>2?'mbtm':'',
shape=='circle'?'circle-btn':'',
'btn-' + (item.size || 'default'),
]"
:hover-class="''+(item.plain?'outline':(item.type || 'primary'))+'-hover'" :data-index="index" @tap="handleClick">{{item.text || "确定"}}</button>
</block>
</view>
</view>
</view>
<view class="modal-mask" :class="[show?'mask-show':'']" @tap="handleClickCancel"></view>
</view>
</template>
<script>
export default {
name: "Modal",
props: {
//
show: {
type: Boolean,
default: false
},
//modal
custom: {
type: Boolean,
default: false
},
width: {
type: String,
default: "80%"
},
padding: {
type: String,
default: "30rpx"
},
radius: {
type: String,
default: "12rpx"
},
//
title: {
type: String,
default: ""
},
//
content: {
type: String,
default: ""
},
//
color: {
type: String,
default: "#343434"
},
// rpx
size: {
type: Number,
default: 28
},
// circle, square
shape: {
type: String,
default: 'square'
},
button: {
type: Array,
default: function() {
return [{
text: "取消",
type: "red",
plain: true //
}, {
text: "确定",
type: "red",
plain: false
}]
}
},
//
maskClosable: {
type: Boolean,
default: true
},
//inputtrue
fadein: {
type: Boolean,
default: false
}
},
data() {
return {
};
},
methods: {
handleClick(e) {
if (!this.show) return;
const dataset = e.currentTarget.dataset;
this.$emit('click', {
index: Number(dataset.index)
});
},
handleClickCancel() {
if (!this.maskClosable) return;
this.$emit('cancel');
}
}
}
</script>
<style lang="scss">
.modal-box {
position: fixed;
left: 50%;
top: 50%;
margin: auto;
background: #fff;
z-index: 1000;
transition: all 0.3s ease-in-out;
opacity: 0;
box-sizing: border-box;
visibility: hidden;
}
.modal-scale {
transform: translate(-50%, -50%) scale(0);
}
.modal-normal {
transform: translate(-50%, -50%) scale(1);
}
.modal-show {
opacity: 1;
visibility: visible;
}
.modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 999;
transition: all 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.mask-show {
visibility: visible;
opacity: 1;
}
.modal-title {
text-align: center;
font-size: 34rpx;
color: #333;
padding-top: 20rpx;
font-weight: bold;
}
.modal-content {
color: #999;
font-size: 28rpx;
padding-top: 20rpx;
padding-bottom: 60rpx;
}
.mtop {
margin-top: 30rpx;
}
.mbtm {
margin-bottom: 30rpx;
}
.modalBtn-box {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between
}
.flex-column {
flex-direction: column;
}
.modal-btn {
width: 46%;
height: 68rpx;
line-height: 68rpx;
position: relative;
border-radius: 60rpx;
font-size: 28rpx;
overflow: visible;
margin-left: 0;
margin-right: 0;
&.btn-default {
font-size: 28rpx;
}
&.btn-lg {
font-size: 32rpx;
}
&.btn-sm {
font-size: 24rpx;
}
}
.modal-btn::after {
content: "";
position: absolute;
width: 200%;
height: 200%;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scale(0.5, 0.5);
transform: scale(0.5, 0.5);
left: 0;
top: 0;
border-radius: 60rpx;
}
.btn-width {
width: 80% !important;
}
.primary {
background: #97AF13;
color: #fff;
}
.primary-hover {
background: #97AF13;
color: #e5e5e5;
}
.primary-outline {
color: #97AF13;
background: none;
}
.primary-outline::after {
border: 1px solid #97AF13;
}
.danger {
background: #ed3f14;
color: #fff;
}
.danger-hover {
background: #d53912;
color: #e5e5e5;
}
.danger-outline {
color: #ed3f14;
background: none;
}
.danger-outline::after {
border: 1px solid #ed3f14;
}
.red {
background: #e41f19;
color: #fff;
}
.red-hover {
background: #c51a15;
color: #e5e5e5;
}
.red-outline {
color: #e41f19;
background: none;
}
.red-outline::after {
border: 1px solid #e41f19;
}
.warning {
background: #ff7900;
color: #fff;
}
.warning-hover {
background: #e56d00;
color: #e5e5e5;
}
.warning-outline {
color: #ff7900;
background: none;
}
.warning-outline::after {
border: 1px solid #ff7900;
}
.green {
background: #19be6b;
color: #fff;
}
.green-hover {
background: #16ab60;
color: #e5e5e5;
}
.green-outline {
color: #19be6b;
background: none;
}
.green-outline::after {
border: 1px solid #19be6b;
}
.white {
background: #fff;
color: #333;
}
.white-hover {
background: #f7f7f9;
color: #666;
}
.white-outline {
color: #333;
background: none;
}
.white-outline::after {
border: 1px solid #333;
}
.gray {
background: #ededed;
color: #999;
}
.gray-hover {
background: #d5d5d5;
color: #898989;
}
.gray-outline {
color: #999;
background: none;
}
.gray-outline::after {
border: 1px solid #999;
}
.outline-hover {
opacity: 0.6;
}
.circle-btn {
border-radius: 40rpx !important;
}
.circle-btn::after {
border-radius: 80rpx !important;
}
</style>

96
uniapp/components/uni-icons/icons.js

@ -1,96 +0,0 @@
export default {
'contact': '\ue100',
'person': '\ue101',
'personadd': '\ue102',
'contact-filled': '\ue130',
'person-filled': '\ue131',
'personadd-filled': '\ue132',
'phone': '\ue200',
'email': '\ue201',
'chatbubble': '\ue202',
'chatboxes': '\ue203',
'phone-filled': '\ue230',
'email-filled': '\ue231',
'chatbubble-filled': '\ue232',
'chatboxes-filled': '\ue233',
'weibo': '\ue260',
'weixin': '\ue261',
'pengyouquan': '\ue262',
'chat': '\ue263',
'qq': '\ue264',
'videocam': '\ue300',
'camera': '\ue301',
'mic': '\ue302',
'location': '\ue303',
'mic-filled': '\ue332',
'speech': '\ue332',
'location-filled': '\ue333',
'micoff': '\ue360',
'image': '\ue363',
'map': '\ue364',
'compose': '\ue400',
'trash': '\ue401',
'upload': '\ue402',
'download': '\ue403',
'close': '\ue404',
'redo': '\ue405',
'undo': '\ue406',
'refresh': '\ue407',
'star': '\ue408',
'plus': '\ue409',
'minus': '\ue410',
'circle': '\ue411',
'checkbox': '\ue411',
'close-filled': '\ue434',
'clear': '\ue434',
'refresh-filled': '\ue437',
'star-filled': '\ue438',
'plus-filled': '\ue439',
'minus-filled': '\ue440',
'circle-filled': '\ue441',
'checkbox-filled': '\ue442',
'closeempty': '\ue460',
'refreshempty': '\ue461',
'reload': '\ue462',
'starhalf': '\ue463',
'spinner': '\ue464',
'spinner-cycle': '\ue465',
'search': '\ue466',
'plusempty': '\ue468',
'forward': '\ue470',
'back': '\ue471',
'left-nav': '\ue471',
'checkmarkempty': '\ue472',
'home': '\ue500',
'navigate': '\ue501',
'gear': '\ue502',
'paperplane': '\ue503',
'info': '\ue504',
'help': '\ue505',
'locked': '\ue506',
'more': '\ue507',
'flag': '\ue508',
'home-filled': '\ue530',
'gear-filled': '\ue532',
'info-filled': '\ue534',
'help-filled': '\ue535',
'more-filled': '\ue537',
'settings': '\ue560',
'list': '\ue562',
'bars': '\ue563',
'loop': '\ue565',
'paperclip': '\ue567',
'eye': '\ue568',
'arrowup': '\ue580',
'arrowdown': '\ue581',
'arrowleft': '\ue582',
'arrowright': '\ue583',
'arrowthinup': '\ue584',
'arrowthindown': '\ue585',
'arrowthinleft': '\ue586',
'arrowthinright': '\ue587',
'pulldown': '\ue588',
'closefill': '\ue589',
'sound': '\ue590',
'scan': '\ue612'
}

57
uniapp/components/uni-icons/uni-icons.vue

File diff suppressed because one or more lines are too long

4
uniapp/components/uni-nav-bar/uni-nav-bar.vue

@ -42,13 +42,11 @@
<script>
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
import uniIcons from "../uni-icons/uni-icons.vue";
export default {
name: "UniNavBar",
components: {
uniStatusBar,
uniIcons
uniStatusBar
},
props: {
title: {

13
uniapp/pages.json

@ -666,6 +666,14 @@
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/coach/schedule/schedule_table",
"style": {
"navigationBarTitleText": "课程安排表",
"navigationBarBackgroundColor": "#292929",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/academic/home/index",
"style": {
@ -697,7 +705,10 @@
"easycom": {
"autoscan": true,
"custom": {
"fui-(.*)": "@/components/firstui/fui-$1/fui-$1.vue"
"fui-(.*)": "@/components/firstui/fui-$1/fui-$1.vue",
"uni-icons": "@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue",
"uni-calendar": "@/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue",
"uni-file-picker": "@/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue"
}
}
}

295
uniapp/pages/market/clue/clue_info.vue

@ -14,16 +14,21 @@
</view>
<view class="course_box_top_below">
<view class="course_box_top_below-left">
<view>{{ $util.formatToDateTime((safeGet(clientInfo, 'customerResource.updated_at', '')),'m-d H:i') }} 跟进</view>
<view>
{{ $util.formatToDateTime((safeGet(clientInfo, 'customerResource.updated_at', '')),'m-d H:i') }}
跟进</view>
<view style="display: flex;align-items: center;">
<view style="padding-left: 30rpx;">
<image v-if="safeGet(clientInfo, 'customerResource.initial_intent') == 'high'"
:src="$util.img('/uniapp_src/static/images/index/lvs.png')" class="drop-image-x"></image>
<image v-else-if="safeGet(clientInfo, 'customerResource.initial_intent') == 'medium'"
:src="$util.img('/uniapp_src/static/images/index/intention2.png')" class="drop-image-x"></image>
<image
v-else
v-if="safeGet(clientInfo, 'customerResource.initial_intent') == 'high'"
:src="$util.img('/uniapp_src/static/images/index/lvs.png')"
class="drop-image-x"></image>
<image
v-else-if="safeGet(clientInfo, 'customerResource.initial_intent') == 'medium'"
:src="$util.img('/uniapp_src/static/images/index/intention2.png')"
class="drop-image-x"></image>
<image v-else
:src="$util.img('/uniapp_src/static/images/index/intention1.png')"
class="drop-image-x">
</image>
@ -35,10 +40,13 @@
<!-- 操作按钮 -->
<view class="action-buttons">
<view class="btn-item" @click="handleMakeCall">
<image class="btn-icon" :src="$util.img('/uniapp_src/static/images/index/phone.png')"></image>
<image class="btn-icon"
:src="$util.img('/uniapp_src/static/images/index/phone.png')"></image>
</view>
<view class="btn-item" @click="handleSendMessage" v-if="safeGet(clientInfo, 'customerResource.member_id')">
<image class="btn-icon" :src="$util.img('/uniapp_src/static/images/index/message.png')"></image>
<view class="btn-item" @click="handleSendMessage"
v-if="safeGet(clientInfo, 'customerResource.member_id')">
<image class="btn-icon"
:src="$util.img('/uniapp_src/static/images/index/message.png')"></image>
</view>
</view>
</view>
@ -63,7 +71,7 @@
<view class="bg_box bg_bottom"></view>
</view>
<!-- 基本资料-->
<!-- 基本资料-->
<view class="basic-information" v-if="switch_tags_type == 1">
<view class="basic-message">基本信息</view>
<view class="basic-message-div">
@ -103,10 +111,11 @@
<view style="height: 200rpx;"></view>
</view>
<!-- 课程信息-->
<!-- 课程信息-->
<view class="course-info" v-if="switch_tags_type == 2">
<view v-if="courseInfo && courseInfo.length > 0">
<view v-for="(course, index) in courseInfo" :key="index" class="course-item" @click="openCourseEditDialog(course)">
<view v-for="(course, index) in courseInfo" :key="index" class="course-item"
@click="openCourseEditDialog(course)">
<view class="course-header">
<view class="course-title">{{ course.course_name || '未知课程' }}</view>
<view class="course-status" :class="'status-' + (course.status || 'default')">
@ -116,19 +125,24 @@
<view class="course-progress">
<view class="progress-bar">
<view class="progress-fill" :style="{width: ((course.total_count > 0 ? Math.round((course.used_count / course.total_count) * 100) : 0)) + '%'}"></view>
<view class="progress-fill"
:style="{width: ((course.total_count > 0 ? Math.round((course.used_count / course.total_count) * 100) : 0)) + '%'}">
</view>
</view>
<view class="progress-text">{{ course.used_count || 0 }}/{{ course.total_count || 0 }}
</view>
<view class="progress-text">{{ course.used_count || 0 }}/{{ course.total_count || 0 }}</view>
</view>
<view class="course-details">
<view class="detail-row">
<view class="detail-label">剩余课时</view>
<view class="detail-value">{{ (course.total_count || 0) - (course.used_count || 0) }}</view>
<view class="detail-value">{{ (course.total_count || 0) - (course.used_count || 0) }}
</view>
</view>
<view class="detail-row">
<view class="detail-label">有效期至</view>
<view class="detail-value">{{ $util.formatToDateTime(course.expiry_date, 'Y-m-d') || '无限期' }}</view>
<view class="detail-value">
{{ $util.formatToDateTime(course.expiry_date, 'Y-m-d') || '无限期' }}</view>
</view>
<view class="detail-row">
<view class="detail-label">请假次数</view>
@ -160,7 +174,7 @@
<view style="height: 200rpx;"></view>
</view>
<!-- 跟进记录-->
<!-- 跟进记录-->
<view class="follow-records" v-if="switch_tags_type == 4">
<view v-for="(v,k) in followList" :key="k">
<view class="basic-message">{{$util.formatToDateTime(v.follow_up_time,'m-d')}}</view>
@ -176,7 +190,7 @@
<view style="height: 200rpx;"></view>
</view>
<!-- 通话记录-->
<!-- 通话记录-->
<view class="call-log" v-if="switch_tags_type == 3">
<view class="call-record-wrapper" v-for="(v,k) in listCallUp" :key="k">
<view class="call-record-item">
@ -189,11 +203,7 @@
<text class="call-label">呼叫时间</text>
<text>{{v.created_at}}</text>
</view>
<button
type="primary"
size="mini"
class="remark-btn"
@click="openAddRemark(v)">
<button type="primary" size="mini" class="remark-btn" @click="openAddRemark(v)">
{{v.remarks ? '修改备注' : '添加备注'}}
</button>
</view>
@ -206,7 +216,7 @@
<view style="height: 200rpx;"></view>
</view>
<!-- 底部按钮组-->
<!-- 底部按钮组-->
<view class="bottom-label">
<view @click="openViewEditClues()">编辑详情</view>
<view @click="openViewEditClassLog()">课程安排</view>
@ -222,12 +232,8 @@
</view>
<view class="dialog-content">
<view class="remark-textarea-container">
<textarea
class="remark-textarea"
v-model="remark_content"
placeholder="请输入备注内容"
maxlength="200"
></textarea>
<textarea class="remark-textarea" v-model="remark_content" placeholder="请输入备注内容"
maxlength="200"></textarea>
<text class="remark-count">{{remark_content.length}}/200</text>
</view>
</view>
@ -250,10 +256,7 @@
<view class="section-title">主教练单选</view>
<view v-if="coachList.length === 0" class="empty-tip">暂无主教练数据</view>
<view class="coach-list">
<view
v-for="coach in coachList"
:key="coach.person_id"
class="coach-item"
<view v-for="coach in coachList" :key="coach.person_id" class="coach-item"
:class="{selected: selectedMainCoach === coach.person_id}"
@click="selectMainCoach(coach.person_id)">
<view class="coach-name">{{ coach.name }}</view>
@ -266,10 +269,7 @@
<view class="section-title">教务单选</view>
<view v-if="educationList.length === 0" class="empty-tip">暂无教务数据</view>
<view class="coach-list">
<view
v-for="education in educationList"
:key="education.person_id"
class="coach-item"
<view v-for="education in educationList" :key="education.person_id" class="coach-item"
:class="{selected: selectedEducation === education.person_id}"
@click="selectEducation(education.person_id)">
<view class="coach-name">{{ education.name }}</view>
@ -282,14 +282,12 @@
<view class="section-title">助教多选</view>
<view v-if="assistantList.length === 0" class="empty-tip">暂无助教数据</view>
<view class="coach-list">
<view
v-for="assistant in assistantList"
:key="assistant.person_id"
class="coach-item"
<view v-for="assistant in assistantList" :key="assistant.person_id" class="coach-item"
:class="{selected: selectedAssistants.includes(assistant.person_id)}"
@click="toggleAssistant(assistant.person_id)">
<view class="coach-name">{{ assistant.name }}</view>
<view class="coach-check" v-if="selectedAssistants.includes(assistant.person_id)"></view>
<view class="coach-check" v-if="selectedAssistants.includes(assistant.person_id)">
</view>
</view>
</view>
</view>
@ -318,21 +316,21 @@
switch_tags_type: 1,
select_type: 1,
resource_sharing_id:'',//id
clientInfo:{
id:'',//id
resource_id:'',//id
customerResource:{},//
sixSpeed:{},//
},//
resource_sharing_id: '', //id
clientInfo: {
id: '', //id
resource_id: '', //id
customerResource: {}, //
sixSpeed: {}, //
}, //
//
followList:[],
followList: [],
//
listCallUp:[],
listCallUp: [],
//
userInfo:{},
userInfo: {},
//
remark_content: '',
@ -378,15 +376,15 @@
return;
}
this.resource_sharing_id = options.resource_sharing_id//id
this.resource_sharing_id = options.resource_sharing_id //id
console.log('onLoad - 设置 resource_sharing_id:', this.resource_sharing_id);
},
onShow(){
onShow() {
console.log('onShow - 开始初始化');
this.init()
},
methods: {
async init(){
async init() {
console.log('init - 开始初始化流程');
//
@ -411,7 +409,7 @@
},
//
async getUserInfo(){
async getUserInfo() {
console.log('getUserInfo - 开始获取员工信息');
try {
let res = await apiRoute.getPersonnelInfo({})
@ -433,7 +431,7 @@
},
//
async getInfo(){
async getInfo() {
console.log('getInfo - 开始获取客户详情, resource_sharing_id:', this.resource_sharing_id);
try {
// resource_sharing_id
@ -447,12 +445,12 @@
}
let data = {
resource_sharing_id:this.resource_sharing_id//id
resource_sharing_id: this.resource_sharing_id //id
}
console.log('getInfo - 发起请求:', data);
let res = await apiRoute.xs_resourceSharingInfo(data)
console.log('getInfo - 请求响应:', res);
if(res.code != 1){
if (res.code != 1) {
console.error('getInfo - 请求失败:', res.msg);
uni.showToast({
title: res.msg,
@ -471,12 +469,12 @@
},
//
async getFollowList(){
async getFollowList() {
let data = {
sales_id:this.resource_sharing_id//
sales_id: this.resource_sharing_id //
}
let res = await marketApi.followList(data)
if(res.code != 1){
if (res.code != 1) {
uni.showToast({
title: res.msg,
icon: 'none'
@ -487,7 +485,7 @@
},
//
async getListCallUp(){
async getListCallUp() {
console.log('getListCallUp - 开始获取通话记录');
try {
// clientInfo.resource_id
@ -502,7 +500,7 @@
console.log('getListCallUp - 请求参数:', data);
let res = await apiRoute.listCallUp(data)
console.log('getListCallUp - 响应:', res);
if(res.code != 1){
if (res.code != 1) {
uni.showToast({
title: res.msg || '获取通话记录失败',
icon: 'none'
@ -519,7 +517,7 @@
},
//-
openViewEditClues(){
openViewEditClues() {
// resource_sharing_id
if (!this.resource_sharing_id) {
console.error('openViewEditClues - resource_sharing_id为空,无法跳转');
@ -530,7 +528,7 @@
return;
}
let resource_sharing_id = this.resource_sharing_id//id
let resource_sharing_id = this.resource_sharing_id //id
this.$navigateTo({
url: `/pages/market/clue/edit_clues?resource_sharing_id=${resource_sharing_id}`
})
@ -567,9 +565,9 @@
return;
}
let resource_name = this.safeGet(this.clientInfo, 'customerResource.name', '')//id
let staff_id = this.safeGet(this.userInfo, 'id', '')//id
let staff_id_name = this.safeGet(this.userInfo, 'name', '')//
let resource_name = this.safeGet(this.clientInfo, 'customerResource.name', '') //id
let staff_id = this.safeGet(this.userInfo, 'id', '') //id
let staff_id_name = this.safeGet(this.userInfo, 'name', '') //
this.$navigateTo({
url: `/pages/market/clue/order_list?resource_id=${resource_id}&resource_name=${resource_name}&staff_id=${staff_id}&staff_id_name=${staff_id_name}`
@ -578,11 +576,11 @@
//-
openViewEditClassLog() {
let resource_id = this.clientInfo.resource_id//id
let resource_name = this.clientInfo.customerResource.name || ''//id
let resource_id = this.clientInfo.resource_id //id
let resource_name = this.clientInfo.customerResource.name || '' //id
let staff_id = this.userInfo.id//id
let staff_id_name = this.userInfo.name || ''//
let staff_id = this.userInfo.id //id
let staff_id_name = this.userInfo.name || '' //
this.$navigateTo({
url: `/pages/market/clue/class_arrangement?resource_id=${resource_id}&resource_name=${resource_name}&staff_id=${staff_id}&staff_id_name=${staff_id_name}`
@ -728,7 +726,7 @@
},
//
async switch_tags(type){
async switch_tags(type) {
//
if (type === 2 && !this.hasCourseInfo) {
uni.showToast({
@ -751,7 +749,7 @@
console.log('刷新通话记录数据,当前记录数:', this.listCallUp.length);
}
},
getSelect(type){
getSelect(type) {
this.select_type = type
},
@ -892,28 +890,79 @@
//
getMockCoachList() {
return [
{ id: 1, person_id: 1, name: '张教练', head_img: '', phone: '' },
{ id: 5, person_id: 5, name: '陈教练', head_img: '', phone: '' },
{ id: 7, person_id: 7, name: '刘教练', head_img: '', phone: '' }
return [{
id: 1,
person_id: 1,
name: '张教练',
head_img: '',
phone: ''
},
{
id: 5,
person_id: 5,
name: '陈教练',
head_img: '',
phone: ''
},
{
id: 7,
person_id: 7,
name: '刘教练',
head_img: '',
phone: ''
}
];
},
//
getMockEducationList() {
return [
{ id: 2, person_id: 2, name: '李教务', head_img: '', phone: '' },
{ id: 8, person_id: 8, name: '周教务', head_img: '', phone: '' }
return [{
id: 2,
person_id: 2,
name: '李教务',
head_img: '',
phone: ''
},
{
id: 8,
person_id: 8,
name: '周教务',
head_img: '',
phone: ''
}
];
},
//
getMockAssistantList() {
return [
{ id: 3, person_id: 3, name: '王助教', head_img: '', phone: '' },
{ id: 4, person_id: 4, name: '赵助教', head_img: '', phone: '' },
{ id: 6, person_id: 6, name: '孙助教', head_img: '', phone: '' },
{ id: 9, person_id: 9, name: '钱助教', head_img: '', phone: '' }
return [{
id: 3,
person_id: 3,
name: '王助教',
head_img: '',
phone: ''
},
{
id: 4,
person_id: 4,
name: '赵助教',
head_img: '',
phone: ''
},
{
id: 6,
person_id: 6,
name: '孙助教',
head_img: '',
phone: ''
},
{
id: 9,
person_id: 9,
name: '钱助教',
head_img: '',
phone: ''
}
];
},
@ -1163,22 +1212,26 @@
background-color: #292929;
}
}
.course_box_top{
.course_box_top {
width: 100%;
height: 60%;
}
.course_box_centre{
.course_box_centre {
margin: auto;
width: 95%;
height: 4rpx;
background: #F5F5F8;
}
.course_box_below{
.course_box_below {
width: 100%;
height: 40%;
display: flex;
justify-content: space-between;
}
.course_box_top_top {
display: flex;
align-items: center;
@ -1195,66 +1248,78 @@
font-size: 28rpx;
}
}
.course_box_top_below{
.course_box_top_below {
display: flex;
align-items: center;
justify-content: space-between;
}
.course_box_top_below-left{
.course_box_top_below-left {
display: flex;
align-items: center;
padding-top: 16rpx;
font-size: 24rpx;
}
.drop-image-x {
width: 20rpx;
height: 20rpx;
}
.title-x {
font-size: 28rpx;
color: #333333;
padding-left: 10rpx;
}
.course_box_top_below-right{
.course_box_top_below-right {
padding-top: 16rpx;
font-size: 24rpx;
display: flex;
align-items: center;
}
.drop-image-star {
width: 40rpx;
height: 40rpx;
}
.selected-text{
.selected-text {
color: #1CD188;
display: flex;
align-items: center;
}
.text{
.text {
color: #333333;
display: flex;
align-items: center;
}
.basic-message{
.basic-message {
color: #fff;
padding: 16rpx 60rpx;
display: flex;
justify-content: space-between;
}
.basic-message-div{
.basic-message-div {
width: 92%;
margin: auto;
background: #555555;
border-radius: 16rpx;
padding: 16rpx 0;
}
.basic-message-div-txt{
.basic-message-div-txt {
display: flex;
justify-content: space-between;
color: #FFFFFF;
padding: 14rpx 30rpx;
}
.bottom-label{
.bottom-label {
width: 100%;
height: 150rpx;
background: #fff;
@ -1350,7 +1415,8 @@
font-size: 24rpx !important;
border-radius: 30rpx !important;
}
.follow-records-list{
.follow-records-list {
width: 92%;
background: #434544;
border-radius: 16rpx;
@ -1359,7 +1425,8 @@
color: #fff;
position: relative;
}
.same-community{
.same-community {
width: 120rpx;
background: #3d4a55;
color: #1e62a9;
@ -1370,7 +1437,8 @@
text-align: center;
border-radius: 40rpx 70rpx 70rpx 12rpx;
}
.coeducation{
.coeducation {
width: 120rpx;
background: #3d4a55;
color: #2e9380;
@ -1381,7 +1449,8 @@
text-align: center;
border-radius: 40rpx 70rpx 70rpx 12rpx;
}
.same-community{
.same-community {
width: 120rpx;
background: #40504c;
color: #1e62a9;
@ -1392,13 +1461,15 @@
text-align: center;
border-radius: 40rpx 70rpx 70rpx 12rpx;
}
.search{
.search {
width: 92%;
margin: auto;
display: flex;
margin-top: 20rpx;
}
.selected{
.selected {
background: #294e48;
border-radius: 16rpx;
padding: 12rpx 8rpx;
@ -1406,7 +1477,8 @@
color: #29d3b4;
margin-left: 5rpx;
}
.not-selected{
.not-selected {
margin-left: 5rpx;
background: #ffffff;
border: 4rpx #959595 solid;
@ -1414,6 +1486,7 @@
padding: 12rpx 8rpx;
text-align: center;
}
.call-record-item {
width: 100%;
background: #434544;
@ -1423,36 +1496,44 @@
color: #fff;
position: relative;
}
.call-record-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.call-name {
font-size: 28rpx;
font-weight: bold;
}
.call-time {
font-size: 24rpx;
color: #999;
}
.call-record-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.call-detail {
display: flex;
align-items: center;
}
.call-label {
font-size: 24rpx;
color: #999;
margin-right: 10rpx;
}
.call-remark {
margin-top: 10rpx;
}
.call-remark-content {
font-size: 24rpx;
color: #fff;

8
uniapp/pages/market/clue/order_list.vue

@ -259,7 +259,13 @@
<view class="custom-content">
<text class="custom-title">支付二维码</text>
<view class="custom-form">
<!-- #ifndef MP-WEIXIN -->
<fui-qrcode :value="qrcode"></fui-qrcode>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<image :src="qrcodeImage" mode="aspectFit"></image>
<!-- #endif -->
</view>
</view>
@ -298,6 +304,7 @@ export default {
isReachedBottom: false,//|true=|false=
showCustomModal: false,
qrcode: 'https://www.baidu.com',
qrcodeImage:'',
//
filteredData: {
page: 1,//
@ -842,6 +849,7 @@ export default {
//
apiRoute.getOrderPayQrcode({ order_id: orderData.id }).then(res => {
this.qrcode = res.data.code_url
this.qrcodeImage = res.data.qrcode_url
this.showCustomModal = true
})
},

Loading…
Cancel
Save