提交 7e0d7b045ee71b149ad97306fb514488f3f77788

作者 genglw
1 个父辈 60f302a9

feat: first

正在显示 75 个修改的文件 包含 10606 行增加496 行删除
... ... @@ -67,9 +67,8 @@ export default {
67 67
68 68 await this._getList();
69 69
70   -
71 70 // 判断是否全部加载完成
72   - if (this.total == 0) {
  71 + if (this.total == this.list.length) {
73 72 this.finished = true;
74 73 this.loading = 'nomore';
75 74 } else {
... ...
1 1 <template>
2 2 <view class="u-button">
3   - <u-button :text="text" color="#0CB17A" :plain="false" :hairline="false" :disabled="disabled" :throttleTime="1500"
4   - type="info" shape="circle" :open-type="openType" @getphonenumber="getPhoneNumber"
  3 + <u-button :text="text" :color="reversedColor" :plain="false" :hairline="false" :disabled="disabled"
  4 + :throttleTime="1500" type="default" :open-type="openType" @getphonenumber="getPhoneNumber"
5 5 :custom-style="getCustomStyle" @click="click">
6 6 </u-button>
7 7 </view>
... ... @@ -38,51 +38,70 @@
38 38 default: ''
39 39 },
40 40
  41 +
41 42 },
42 43 data() {
43 44 return {}
44 45 },
45 46
46   - watch: {
47   - buttonType: function(newVal, oldVal) {
  47 + computed: {
  48 + getCustomStyle() {
  49 +
  50 + const {
  51 + type = ''
  52 + } = this;
  53 +
  54 + let style = {};
  55 +
  56 + switch (type) {
  57 + case 'confirm':
  58 + return Object.assign({}, {
  59 + border: 'none',
  60 + color: '#FFFFFF',
  61 + }, this.customStyle);
  62 + break;
  63 +
  64 + case 'cancel':
  65 + return Object.assign({}, {
  66 + border: 'none',
  67 + color: 'rgba(0, 0, 0, 0.4500)',
  68 + }, this.customStyle);
  69 + break;
  70 + }
  71 + },
  72 +
  73 + reversedColor() {
  74 +
  75 + let color = '#0CB17A';
  76 +
48 77 switch (this.type) {
49 78 case 'confirm':
50   - this.color = "#0CB17A";
  79 + color = "#0CB17A";
  80 + break;
  81 +
  82 + case 'cancel':
  83 + color = "rgba(0, 0, 0, 0.0600)";
51 84 break;
52 85 }
  86 +
  87 + return color;
53 88 }
54 89 },
55 90
56   - computed: {
57   - // getCustomStyle() {
58   -
59   - // const {
60   - // type = ''
61   - // } = this;
62   -
63   - // let style = {};
64   -
65   - // switch (type) {
66   - // case 'confirm':
67   - // return Object.assign({}, {
68   - // backgroundColor: '#FF001A',
69   - // borderRadius: '8rpx',
70   - // }, this.customStyle);
71   - // break;
72   -
73   - // case 'cancel':
74   - // return Object.assign({}, {
75   - // backgroundColor: "rgba(0,0,0,0.15)",
76   - // borderRadius: '8rpx',
77   - // }, this.customStyle);
78   - // break;
79   -
80   - // case 'custom':
81   - // return Object.assign({}, this.customStyle);
82   - // break;
83   - // }
84   - // }
85   - },
  91 + // watch: {
  92 + // buttonType: function(newVal, oldVal) {
  93 + // switch (this.type) {
  94 + // case 'confirm':
  95 + // this.color = "#0CB17A";
  96 + // break;
  97 +
  98 + // case 'cancel':
  99 + // this.color = "#0CB17A";
  100 + // break;
  101 + // }
  102 + // }
  103 + // },
  104 +
86 105 methods: {
87 106 // 按钮点击
88 107 click(e) {
... ... @@ -97,5 +116,8 @@
97 116 </script>
98 117
99 118 <style lang="scss">
100   -
  119 + .u-button /deep/ .u-button {
  120 + border: nones;
  121 + border-radius: 8rpx;
  122 + }
101 123 </style>
... ...
1 1 <template>
2 2 <view class="m-loading">
3   - <u-loadmore :status="loading" :icon="icon" :loadText="loadText" bgColor="#F7F7F7" marginTop='12rpx' marginBottom='12rpx'></u-loadmore>
  3 + <u-loadmore :status="loading" :line="true" bgColor="#F7F7F7" fontSize="28rpx" iconSize="34rpx"></u-loadmore>
4 4 </view>
5 5 </template>
6 6
... ... @@ -10,21 +10,7 @@
10 10 loading: {
11 11 type: String,
12 12 default: 'loadmore'
13   - },
14   - icon: {
15   - type: Boolean,
16   - default: true
17   - },
18   - loadText: {
19   - type: Object,
20   - default () {
21   - return {
22   - loadmore: '点击或上拉加载更多',
23   - loading: '正在加载',
24   - nomore: '没有更多了'
25   - }
26   - }
27   - }
  13 + },
28 14 },
29 15 data() {
30 16 return {};
... ...
1 1 <template>
2 2 <view class="c-no-data" :style="[wrapStyle]" >
3 3 <view class="image">
4   - <u-image :src="vuex_baseImgUrl+'/nodata.png'" width="260rpx" height="200rpx"></u-image>
  4 + <u-image :src="vuex_baseImgUrl+'/no_data.png'" width="480rpx" height="480rpx"></u-image>
5 5 </view>
6 6 <view class="title">{{ title }}</view>
7 7 </view>
... ... @@ -49,19 +49,22 @@
49 49
50 50 <style scoped lang="scss">
51 51 .c-no-data {
52   - width: 100%;
  52 + width: 100%;
  53 + position: relative;
53 54
54 55 .image {
55   - width: 260rpx;
  56 + width: 480rpx;
56 57 margin: 0 auto;
57 58 }
58 59
59 60 .title {
60   - margin: 48rpx 0 0 0;
  61 + position: absolute;
  62 + top: 560rpx;
  63 + left: 326rpx;
61 64 text-align: center;
62   - font-size: 28rpx;
63   - line-height: 40rpx;
64   - color: #000000;
  65 + font-size: 24rpx;
  66 + line-height: 52rpx;
  67 + color: #909097;
65 68 }
66 69 }
67 70 </style>
... ...
1 1 const http = uni.$u.http
2 2
  3 +// 获取oss对应的图片地址
  4 +export const getImgUrlApi = (params) => http.get('/basic/v1/oss/sign_url', {
  5 + params: params
  6 +})
  7 +
  8 +// OssInit初始化
  9 +export const getOssInitApi = (params) => http.get('/basic/v1/oss/policy', {
  10 + params: params
  11 +})
  12 +
3 13 // 获取token
4 14 export const postTokenApi = (params, config = {}) => http.post('/auth/v1/login', params, config)
5 15
6 16 // 获取用户信息
7   -export const getUserInfoApi = (data) => http.get('/user/v1/detail', {
8   - params: data
  17 +export const getUserInfoApi = (params) => http.get('/user/v1/detail', {
  18 + params: params
9 19 })
10 20
11 21 // 获取短信验证码
12   -export const getSmsCodeApi = (data) => http.get('/basic/v1/sms_code/get', {
13   - params: data
  22 +export const getSmsCodeApi = (params) => http.get('/basic/v1/sms_code/get', {
  23 + params: params
  24 +})
  25 +
  26 +// 更新用户信息
  27 +export const updateUserInfoApi = (params) => http.put('/user/v1/update', params);
  28 +
  29 +//注销账户
  30 +export const delAccountApi = (params) => http.delete('/user/v1/annuluser', params);
  31 +
  32 +//撤销注销账户
  33 +export const cancelDelAccountApi = (params) => http.put('/user/v1/annulusercancel', params);
  34 +
  35 +// 切换老师身份
  36 +export const putTeacherRolesApi = (id, params) => http.put(`/user/v1/teacher/${id}/change_role`, params);
  37 +
  38 +// 待办事项统计
  39 +export const getTodoListStatisticsApi = (params) => http.get('/internship/v1/index/applet/waitHandleList', {
  40 + params: params
  41 +})
  42 +
  43 +// 实习项目列表
  44 +export const getProjectListApi = (params) => http.get('/internship/v1/project/list', {
  45 + params: params
  46 +})
  47 +
  48 +// 报名审核列表
  49 +export const getRegistrationReviewApi = (params) => http.get('/internship/v1/entry/list', {
  50 + params: params
  51 +})
  52 +
  53 +//报名审核详情
  54 +export const getRegistrationDetailApi = (id, params) => http.get(`/internship/v1/entry/detail/${id}`, {
  55 + params: params
  56 +})
  57 +
  58 +// 报名审核
  59 +export const putRegistrationReviewApi = (params) => http.put(`/internship/v1/entry/audit`, params);
  60 +
  61 +// 学生签到列表
  62 +export const getStudentSignInListApi = (params) => http.get('/internship/v1/attendance/applet/list', {
  63 + params: params
  64 +})
  65 +
  66 +// 日志批阅列表
  67 +export const getLogReviewListApi = (params) => http.get('/internship/v1/form_log/school/list', {
  68 + params: params
  69 +})
  70 +
  71 +// 实习日志详情
  72 +export const getLogDetailApi = (id, params) => http.get(`/internship/v1/form_log/detail/${id}`, {
  73 + params: params
  74 +})
  75 +
  76 +// 日志回复列表
  77 +export const getLogReplyListApi = (params) => http.get('/internship/v1/form_log_review/list', {
  78 + params: params
  79 +})
  80 +
  81 +// 创建日志回复
  82 +export const postLogReplyApi = (params) => http.post(`/internship/v1/form_log_review/save`, params);
  83 +
  84 +// 报告批阅列表
  85 +export const getReportReviewListApi = (params) => http.get('/internship/v1/report/list', {
  86 + params: params
  87 +})
  88 +
  89 +// 实习报告详情
  90 +export const getReportDetailApi = (id, params) => http.get(`/internship/v1/report/detail_by_student/${id}`, {
  91 + params: params
  92 +})
  93 +
  94 +//报告批阅
  95 +export const putReportReviewApi = (id, params) => http.put(`/internship/v1/report/examine/${id}`, params);
  96 +
  97 +//审批记录
  98 +export const getReportApprovalListApi = (formId, params) => http.get(`/internship/v1/report/examine_list/${formId}`, {
  99 + params: params
  100 +})
  101 +
  102 +// 成绩鉴定列表
  103 +export const getAchievementAppraisalListApi = (params) => http.get('/internship/v1/form/achievementAppraisalList', {
  104 + params: params
  105 +})
  106 +
  107 +// 成绩鉴定详情
  108 +export const getAchievementDetailApi = (id, params) => http.get(
  109 + `/internship/v1/form/achievementAppraisalDetail/${id}`, {
  110 + params: params
  111 + })
  112 +
  113 +//成绩鉴定
  114 +export const putAchievementAppraisalApi = (params) => http.post(`/internship/v1/form/evaluate`, params);
  115 +
  116 +// 班级列表
  117 +export const getClassListApi = (params) => http.get('/internship/v1/form/listByTeacherApplet', {
  118 + params: params
  119 +})
  120 +
  121 +// 学生列表
  122 +export const getStudentListApi = (params) => http.get('/internship/v1/form/traineeList', {
  123 + params: params
  124 +})
  125 +
  126 +//实习过程详情
  127 +export const getInternshipProcessDetailApi = (params) => http.get(`/internship/v1/form/internshipProcess`, {
  128 + params: params
  129 +})
  130 +
  131 +// 三方协议列表
  132 +export const getAgreementListApi = (params) => http.get('/internship/v1/treaty/list_by_school', {
  133 + params: params
  134 +})
  135 +
  136 +//三方协议详情
  137 +export const getAgreementDetailApi = (id, params) => http.get(`/internship/v1/treaty/detail/${id}`, {
  138 + params: params
  139 +})
  140 +
  141 +//签到列表
  142 +export const getsignInListApi = (params) => http.get('/internship/v1/attendance/applet/monthAttendanceList', {
  143 + params: params
  144 +})
  145 +
  146 +// 实习岗位列表
  147 +export const getInternshipJobListApi = (params) => http.get('/internship/v1/form/internshipJob', {
  148 + params: params
  149 +})
  150 +
  151 +// 实践课程列表
  152 +export const getPracticalCoursesListApi = (params) => http.get('/internship/v1/form/internshipCourse', {
  153 + params: params
  154 +})
  155 +
  156 +//实习单详情
  157 +export const getInternshipDetailApi = (id, params) => http.get(`/internship/v1/form/detail/${id}`, {
  158 + params: params
14 159 })
  160 +
  161 +
  162 +
... ...
... ... @@ -5,9 +5,11 @@ module.exports = (vm) => {
5 5 /* config 为默认全局配置*/
6 6
7 7 // 测试环境
8   - config.baseURL = "http://39.104.52.206:8000";
  8 + config.baseURL = "http://47.110.250.177:8000";
  9 +
9 10 // 预生产环境
10   - // config.baseURL = "https://api-isxpre.workai.com.cn";
  11 + // config.baseURL = "https://api-isxpre.workai.com.cn";
  12 +
11 13 // 线上环境
12 14 // config.baseURL = "https://api-isx.workai.com.cn";
13 15
... ... @@ -68,12 +70,14 @@ module.exports = (vm) => {
68 70
69 71 // 响应拦截
70 72 uni.$u.http.interceptors.response.use((response) => {
  73 +
71 74 /* 对响应成功做点什么 可使用async await 做异步操作*/
72 75 const data = response.data
73 76
74 77 // 自定义参数
75 78 const custom = response.config?.custom
76 79 if (data.code !== 200) {
  80 +
77 81 // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
78 82 if (custom.toast !== false) {
79 83 uni.$u.toast(data.message)
... ... @@ -88,8 +92,22 @@ module.exports = (vm) => {
88 92 }
89 93 }
90 94 return data.data === undefined ? {} : data.data
  95 +
91 96 }, (response) => {
92 97 // 对响应错误做点什么 (statusCode !== 200)
  98 + console.log(response)
  99 +
  100 + // if (response.statusCode == 401) {
  101 + // // 假设401为token失效,这里跳转登录
  102 + // vm.$u.toast('未登录,请重新登录!');
  103 + // setTimeout(() => {
  104 + // // 此为uView的方法,详见路由相关文档
  105 + // vm.$u.route('/pages/main/my/login/login')
  106 + // }, 1500)
  107 + // return false;
  108 +
  109 + // }
  110 +
93 111 return Promise.reject(response)
94 112 })
95 113 }
... ...
1 1 {
2   - "name" : "job-sharing",
  2 + "name" : "yxly-teacher",
3 3 "appid" : "__UNI__C6035C1",
4 4 "description" : "多平台快速开发的UI框架",
5 5 "versionName" : "1.8.5",
... ... @@ -102,7 +102,7 @@
102 102 },
103 103 "quickapp" : {},
104 104 "mp-weixin" : {
105   - "appid" : "wx84b71301436652ce",
  105 + "appid" : "wx6cd2152282abd34c",
106 106 "setting" : {
107 107 "urlCheck" : false,
108 108 "es6" : true,
... ...
... ... @@ -7,14 +7,14 @@
7 7 "current": 0, //当前激活的模式(list 的索引项)
8 8 "list": [{
9 9 "name": "defult", //模式名称
10   - "path": "pages/main/my/mobileLogin/mobileLogin",
11   - "query": ""
  10 + "path": "pages/main/internship/traineeDetail/traineeDetail",
  11 + "query": "studentId=1519965286978138113"
12 12 }]
13 13 },
14 14 "pages": [{
15 15 "path": "pages/tabBar/home/home",
16 16 "style": {
17   - "navigationBarTitleText": "人人推",
  17 + "navigationBarTitleText": "校职通",
18 18 "navigationBarTextStyle": "black",
19 19 "enablePullDownRefresh": false
20 20 }
... ... @@ -22,8 +22,9 @@
22 22 {
23 23 "path": "pages/tabBar/internship/internship",
24 24 "style": {
25   - "navigationStyle": "custom",
26   - "navigationBarTitleText": ""
  25 + "navigationBarTitleText": "我的实习生",
  26 + "navigationBarTextStyle": "black",
  27 + "enablePullDownRefresh": false
27 28 }
28 29 },
29 30 {
... ... @@ -34,26 +35,259 @@
34 35 }
35 36 }
36 37 ],
  38 +
37 39 "subPackages": [{
38   - "root": "pages/main/my",
39   - "pages": [{
40   - "path": "login/login",
  40 + "root": "pages/main/home",
  41 + "pages": [
  42 +
  43 + {
  44 + "path": "registrationReview/registrationReview",
  45 + "style": {
  46 + "navigationBarTitleText": "报名审核",
  47 + "enablePullDownRefresh": false
  48 + }
  49 +
  50 + }, {
  51 + "path": "registrationDetail/registrationDetail",
  52 + "style": {
  53 + "navigationBarTitleText": "报名详情",
  54 + "enablePullDownRefresh": false
  55 + }
  56 +
  57 + }, {
  58 + "path": "studentSignIn/studentSignIn",
  59 + "style": {
  60 + "navigationBarTitleText": "学生签到",
  61 + "enablePullDownRefresh": false
  62 + }
  63 +
  64 + }, {
  65 + "path": "logReview/logReview",
  66 + "style": {
  67 + "navigationBarTitleText": "日志批阅",
  68 + "enablePullDownRefresh": false
  69 + }
  70 +
  71 + }, {
  72 + "path": "logDetail/logDetail",
  73 + "style": {
  74 + "navigationBarTitleText": "日志详情",
  75 + "enablePullDownRefresh": false
  76 + }
  77 +
  78 + }, {
  79 + "path": "reportReview/reportReview",
  80 + "style": {
  81 + "navigationBarTitleText": "报告批阅",
  82 + "enablePullDownRefresh": false
  83 + }
  84 +
  85 + }, {
  86 + "path": "reportDetail/reportDetail",
  87 + "style": {
  88 + "navigationBarTitleText": "报告详情",
  89 + "enablePullDownRefresh": false
  90 + }
  91 +
  92 + }, {
  93 + "path": "approvalRecord/approvalRecord",
  94 + "style": {
  95 + "navigationBarTitleText": "审批记录",
  96 + "enablePullDownRefresh": false
  97 + }
  98 +
  99 + }, {
  100 + "path": "achievementAppraisal/achievementAppraisal",
  101 + "style": {
  102 + "navigationBarTitleText": "成绩鉴定",
  103 + "enablePullDownRefresh": false
  104 + }
  105 +
  106 + }, {
  107 + "path": "achievementDetail/achievementDetail",
  108 + "style": {
  109 + "navigationBarTitleText": "鉴定详情",
  110 + "enablePullDownRefresh": false
  111 + }
  112 +
  113 + }
  114 + ]
  115 + },
  116 + {
  117 + "root": "pages/main/internship",
  118 + "pages": [{
  119 + "path": "studentList/studentList",
41 120 "style": {
42   - "navigationBarTitleText": "登录",
  121 + "navigationBarTitleText": "实习生列表",
43 122 "enablePullDownRefresh": false
44 123 }
45 124
46   - },
47   - {
48   - "path": "mobileLogin/mobileLogin",
  125 + }, {
  126 + "path": "traineeDetail/traineeDetail",
49 127 "style": {
50   - "navigationBarTitleText": "手机登录",
  128 + "navigationBarTitleText": "学生信息",
51 129 "enablePullDownRefresh": false
52 130 }
53 131
54   - }
55   - ]
56   - }],
  132 + } ,{
  133 + "path" : "agreementList/agreementList",
  134 + "style" :
  135 + {
  136 + "navigationBarTitleText": "三方协议",
  137 + "enablePullDownRefresh": false
  138 + }
  139 +
  140 + }
  141 + ,{
  142 + "path" : "agreementDetail/agreementDetail",
  143 + "style" :
  144 + {
  145 + "navigationBarTitleText": "协议详情",
  146 + "enablePullDownRefresh": false
  147 + }
  148 +
  149 + }
  150 + ,{
  151 + "path" : "signInList/signInList",
  152 + "style" :
  153 + {
  154 + "navigationBarTitleText": "签到",
  155 + "enablePullDownRefresh": false
  156 + }
  157 +
  158 + }
  159 + ,{
  160 + "path" : "intershipInfo/intershipInfo",
  161 + "style" :
  162 + {
  163 + "navigationBarTitleText": "实习单详情",
  164 + "enablePullDownRefresh": false
  165 + }
  166 +
  167 + }
  168 + ,{
  169 + "path" : "achievementDetail/achievementDetail",
  170 + "style" :
  171 + {
  172 + "navigationBarTitleText": "成绩详情",
  173 + "enablePullDownRefresh": false
  174 + }
  175 +
  176 + }
  177 + ]
  178 + },
  179 + {
  180 + "root": "pages/main/my",
  181 + "pages": [{
  182 + "path": "login/login",
  183 + "style": {
  184 + "navigationBarTitleText": "登录",
  185 + "enablePullDownRefresh": false
  186 + }
  187 +
  188 + },
  189 + {
  190 + "path": "mobileLogin/mobileLogin",
  191 + "style": {
  192 + "navigationBarTitleText": "手机登录",
  193 + "enablePullDownRefresh": false
  194 + }
  195 +
  196 + }, {
  197 + "path": "accountSafe/accountSafe",
  198 + "style": {
  199 + "navigationBarTitleText": "账号与安全",
  200 + "enablePullDownRefresh": false
  201 + }
  202 +
  203 + }, {
  204 + "path": "editAccount/editAccount",
  205 + "style": {
  206 + "navigationBarTitleText": "修改账号",
  207 + "enablePullDownRefresh": false
  208 + }
  209 +
  210 + }, {
  211 + "path": "editMobile/editMobile",
  212 + "style": {
  213 + "navigationBarTitleText": "修改手机号",
  214 + "enablePullDownRefresh": false
  215 + }
  216 +
  217 + }, {
  218 + "path": "editPassword/editPassword",
  219 + "style": {
  220 + "navigationBarTitleText": "修改密码",
  221 + "enablePullDownRefresh": false
  222 + }
  223 +
  224 + }, {
  225 + "path": "removeAccount/removeAccount",
  226 + "style": {
  227 + "navigationBarTitleText": "注销账户",
  228 + "enablePullDownRefresh": false
  229 + }
  230 +
  231 + }, {
  232 + "path": "againRemove/againRemove",
  233 + "style": {
  234 + "navigationBarTitleText": "注销账户",
  235 + "enablePullDownRefresh": false
  236 + }
  237 +
  238 + }, {
  239 + "path": "freezing/freezing",
  240 + "style": {
  241 + "navigationBarTitleText": "",
  242 + "enablePullDownRefresh": false
  243 + }
  244 +
  245 + }, {
  246 + "path": "writtenOff/writtenOff",
  247 + "style": {
  248 + "navigationBarTitleText": "",
  249 + "enablePullDownRefresh": false
  250 + }
  251 +
  252 + }, {
  253 + "path": "policiesAgreement/policiesAgreement",
  254 + "style": {
  255 + "navigationBarTitleText": "政策与协议",
  256 + "enablePullDownRefresh": false
  257 + }
  258 +
  259 + }, {
  260 + "path": "agreement/agreement",
  261 + "style": {
  262 + "navigationBarTitleText": "隐私协议",
  263 + "enablePullDownRefresh": false
  264 + }
  265 +
  266 + }, {
  267 + "path": "userPolicy/userPolicy",
  268 + "style": {
  269 + "navigationBarTitleText": "用户政策",
  270 + "enablePullDownRefresh": false
  271 + }
  272 +
  273 + }, {
  274 + "path": "versionInfo/versionInfo",
  275 + "style": {
  276 + "navigationBarTitleText": "版本信息",
  277 + "enablePullDownRefresh": false
  278 + }
  279 +
  280 + }, {
  281 + "path": "personInfo/personInfo",
  282 + "style": {
  283 + "navigationBarTitleText": "个人信息",
  284 + "enablePullDownRefresh": false
  285 + }
  286 +
  287 + }
  288 + ]
  289 + }
  290 + ],
57 291
58 292 "preloadRule": {
59 293
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 + <view class="search_box">
  4 + <view class="top">
  5 + <view class="check">
  6 + <u-checkbox-group v-model="checkboxValue" placement="column" @change="checkboxChange">
  7 + <u-checkbox :customStyle="{marginBottom: '8px'}" shape="circle"
  8 + v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"
  9 + activeColor="#06B079" size="28rpx" labelSize="28rpx" labelColor="#202131">
  10 + </u-checkbox>
  11 + </u-checkbox-group>
  12 + </view>
  13 +
  14 + <view class="search">
  15 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  16 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  17 + </u-search>
  18 + </view>
  19 +
  20 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  21 + </view>
  22 + </view>
  23 +
  24 + <view class="list_box" v-if="list.length > 0">
  25 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  26 +
  27 + <view class="bg_image" v-if="item.appraisalStatus == 'no_appraisal'">
  28 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  29 + <text>待鉴定</text>
  30 + </view>
  31 +
  32 + <view class="bg_image" v-else>
  33 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  34 + <text>已鉴定</text>
  35 + </view>
  36 +
  37 + <view class="info">
  38 + <view class="avatar">{{getNameLastTwo(item.studentName)}}</view>
  39 + <view class="name">{{overflowHide(item.studentName, 6)}}</view>
  40 + <view class="number">NO.{{item.studentNumber}}</view>
  41 + </view>
  42 + <view class="company">
  43 + <text>实习单号</text>
  44 + <text>{{item.number || '--'}}</text>
  45 + </view>
  46 + <view class="company position">
  47 + <text>实习项目</text>
  48 + <text>{{item.projectName|| '--'}}</text>
  49 + </view>
  50 +
  51 + <view class="statistics">
  52 + <view>
  53 + <text>{{item.uploadCount|| 0}}</text>
  54 + <text>三方协议</text>
  55 + </view>
  56 + <view class="line"></view>
  57 + <view>
  58 + <text>{{item.weekLogCount|| 0}}</text>
  59 + <text>周日志</text>
  60 + </view>
  61 + <view class="line"></view>
  62 + <view>
  63 + <text>{{item.internshipReportCount|| 0}}</text>
  64 + <text>实习报告</text>
  65 + </view>
  66 + <view class="line"></view>
  67 + <view>
  68 + <text>{{item.attendanceCount|| 0}}</text>
  69 + <text>签到</text>
  70 + </view>
  71 + </view>
  72 +
  73 + </view>
  74 + <c-loading :loading="loading"></c-loading>
  75 + </view>
  76 + <view v-else class="no_data">
  77 + <c-no-data></c-no-data>
  78 + </view>
  79 +
  80 + <u-popup :show="show" mode="right" @close="close" @open="open">
  81 + <view class="popup_search">
  82 + <view class="content">
  83 + <view class="title">按项目筛选</view>
  84 + <scroll-view class="scroll" scroll-y="true">
  85 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  86 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  87 + <text>{{item.name}}</text>
  88 + </view>
  89 + <view v-else>
  90 + <text>{{item.name}}</text>
  91 + </view>
  92 + </view>
  93 + </scroll-view>
  94 + <view class="switch">
  95 + <text>待鉴定</text>
  96 + <u-switch v-model="switchValue" size="48" activeColor="#06B079" @change="handelChange">
  97 + </u-switch>
  98 + </view>
  99 + </view>
  100 +
  101 + <view class="footer">
  102 + <view class="left_btn">
  103 + <c-button type="cancel" text="重置" @click="handelCancel">
  104 + </c-button>
  105 + </view>
  106 + <view class="right_btn">
  107 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  108 + </c-button>
  109 + </view>
  110 + </view>
  111 +
  112 + </view>
  113 + </u-popup>
  114 +
  115 + </view>
  116 +</template>
  117 +
  118 +<script>
  119 + import {
  120 + mapGetters,
  121 + mapState,
  122 + mapActions
  123 + } from 'vuex'
  124 + import listMixin from "@/common/mixins/list-mixin.js";
  125 +
  126 + import {
  127 + getAchievementAppraisalListApi,
  128 + getProjectListApi,
  129 + } from '@/config/api.js';
  130 +
  131 + export default {
  132 + mixins: [listMixin],
  133 + data() {
  134 +
  135 + const d = new Date();
  136 + const year = d.getFullYear();
  137 + let month = d.getMonth() + 1;
  138 + month = month < 10 ? `0${month}` : month;
  139 + const date = d.getDate();
  140 +
  141 + return {
  142 + checkboxValue: [],
  143 + // 基本案列数据
  144 + checkboxList: [{
  145 + name: '待鉴定',
  146 + disabled: false
  147 + }],
  148 + keyword: '',
  149 + show: false,
  150 + search: {
  151 + //搜索对象必须为key search的对象
  152 + keySearch: "",
  153 + appraisalStatus: '',
  154 +
  155 + },
  156 + showTime: false,
  157 + timeValue: `${year}-${month}-${date}`,
  158 + defaultDateMultiple: [`${year}-${month}-${date}`],
  159 + list: [], //列表必须为key list的数组
  160 + projectId: '',
  161 + switchValue: false,
  162 +
  163 + }
  164 + },
  165 +
  166 + onLoad() {},
  167 +
  168 + onShow() {
  169 +
  170 + this.$store.dispatch(`home/getProjectList`, {
  171 + pageSize: -1,
  172 + })
  173 +
  174 + this.search.keySearch = '';
  175 +
  176 + this.finished = false;
  177 + this.loading = "loadmore";
  178 + this.page = 0;
  179 + this.list = [];
  180 + this._getList();
  181 + },
  182 +
  183 + computed: {
  184 + ...mapState('home', {
  185 + // 箭头函数可使代码更简练
  186 + projectList: 'projectList',
  187 +
  188 + }),
  189 +
  190 + },
  191 +
  192 + methods: {
  193 +
  194 + getNameLastTwo(value) {
  195 + if (value && value.length > 3) {
  196 + return value.substring(value.length - 3)
  197 + } else {
  198 + return value;
  199 + }
  200 + },
  201 +
  202 + overflowHide(value, num = 4) {
  203 + if (value && value.length > num) {
  204 + return `${value.slice(0, num)}...`
  205 + } else {
  206 + return value;
  207 + }
  208 + },
  209 +
  210 + confirm(e) {
  211 + this.timeValue = e[0];
  212 + this.showTime = false;
  213 + },
  214 +
  215 + handelDetail(record) {
  216 + this.$u.route({
  217 + url: `pages/main/home/achievementDetail/achievementDetail?&id=${record.id}`
  218 + })
  219 + },
  220 +
  221 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  222 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  223 + },
  224 +
  225 + checkboxChange(n) {
  226 + console.log('change', n);
  227 +
  228 + this.search.appraisalStatus = n.length > 0 ? 'no_appraisal' : '';
  229 +
  230 + this.switchValue = n.length > 0 ? true : false;
  231 +
  232 + this.finished = false;
  233 + this.loading = "loadmore";
  234 + this.page = 0;
  235 + this.list = [];
  236 + this._getList();
  237 + },
  238 +
  239 + handelSearch(value) {
  240 + this.finished = false;
  241 + this.loading = "loadmore";
  242 + this.page = 0;
  243 + this.list = [];
  244 + this._getList();
  245 + },
  246 +
  247 + open() {
  248 + // console.log('open');
  249 + },
  250 + close() {
  251 + this.show = false
  252 + // console.log('close');
  253 + },
  254 + // scroll-view到底部加载更多
  255 + onreachBottom() {},
  256 + // 搜索
  257 + searchSubmit() {
  258 + // 调用混合搜索
  259 + this._searchData();
  260 + },
  261 + // 模拟后端分页
  262 + async getData(requestParams) {
  263 + const {
  264 + search = {}
  265 + } = requestParams;
  266 +
  267 + let params = {};
  268 + params.pageNumber = requestParams.page + 1;
  269 + params.pageSize = 5;
  270 +
  271 + if (search.appraisalStatus) {
  272 + params.appraisalStatus = search.appraisalStatus;
  273 + }
  274 +
  275 + if (this.keyword) {
  276 + params.keySearch = this.keyword
  277 + }
  278 +
  279 + if (this.projectId) {
  280 + params.projectId = this.projectId
  281 + }
  282 +
  283 + return await getAchievementAppraisalListApi(params);
  284 + },
  285 + // 数据请求(没错就是这么少的代码)
  286 + async _getList() {
  287 + if (this.page == 0) {
  288 + this.list = [];
  289 + }
  290 +
  291 + // 根据实际情况修改自己修改key
  292 + let result = await this.getData({
  293 + page: this.page, // 传入页码
  294 + size: this.size, // 传入每页条数
  295 + search: this.search, // 传入搜索的对象
  296 + });
  297 +
  298 + this.total = result.total;
  299 +
  300 + if (this.list.length == 0 && result.records.length == 0) {
  301 + this.shownoData = false
  302 + } else {
  303 + this.shownoData = true
  304 + }
  305 +
  306 + this.list = this.list.concat(result.records)
  307 + },
  308 +
  309 + handelClick(values) {
  310 + console.log(values);
  311 + this.projectId = values.id;
  312 + },
  313 +
  314 + handelChange(e) {
  315 + console.log(e)
  316 + this.checkboxValue = e ? ['待鉴定'] : [];
  317 + this.search.appraisalStatus = e ? 'no_appraisal' : '';
  318 +
  319 + },
  320 +
  321 + handelCancel() {
  322 + this.switchValue = false;
  323 + this.projectId = '';
  324 + },
  325 +
  326 + hancelSubmit() {
  327 + this.finished = false;
  328 + this.loading = "loadmore";
  329 + this.page = 0;
  330 + this.list = [];
  331 + this._getList();
  332 +
  333 + this.show = false;
  334 + },
  335 +
  336 + }
  337 + }
  338 +</script>
  339 +
  340 +<style lang="scss" scoped>
  341 + .registration_review {
  342 + width: 100%;
  343 + min-height: 100%;
  344 + height: auto;
  345 + background-color: #F7F7F7;
  346 +
  347 + .search_box {
  348 + padding: 36rpx 30rpx 0;
  349 + background-color: #FFFFFF;
  350 +
  351 + .top {
  352 + display: flex;
  353 + flex-flow: row nowrap;
  354 + justify-content: space-between;
  355 + padding: 0 0 30rpx 0;
  356 +
  357 + .check {
  358 + padding: 20rpx 0 0 0;
  359 + }
  360 +
  361 + .search {
  362 + width: 468rpx;
  363 + }
  364 + }
  365 +
  366 + .bottom {
  367 + .time {
  368 + padding: 30rpx 0 30rpx 40rpx;
  369 + }
  370 + }
  371 +
  372 +
  373 + }
  374 +
  375 + .list_box {
  376 + padding: 0 0 50rpx 0;
  377 +
  378 + .item {
  379 + position: relative;
  380 + width: 630rpx;
  381 + margin: 30rpx auto;
  382 + padding: 30rpx;
  383 + border-radius: 12rpx;
  384 + background-color: #FFFFFF;
  385 +
  386 + .bg_image {
  387 + position: absolute;
  388 + top: 0;
  389 + right: 0;
  390 +
  391 + text {
  392 + position: absolute;
  393 + top: 12rpx;
  394 + right: 30rpx;
  395 + font-size: 24rpx;
  396 + line-height: 24rpx;
  397 + color: #FFFFFF;
  398 + }
  399 + }
  400 +
  401 + .info {
  402 + display: flex;
  403 + flex-flow: row nowrap;
  404 + align-items: center;
  405 + margin: 0 0 30rpx 0;
  406 +
  407 + .avatar {
  408 + width: 94rpx;
  409 + height: 94rpx;
  410 + padding: 0 8rpx;
  411 + border-radius: 4rpx;
  412 + background-color: #06B079;
  413 + font-size: 24rpx;
  414 + line-height: 94rpx;
  415 + color: #FFFFFF;
  416 + text-align: center;
  417 + }
  418 +
  419 + .name {
  420 + font-size: 32rpx;
  421 + line-height: 44rpx;
  422 + color: #202131;
  423 + font-weight: 500;
  424 + margin: 0 20rpx;
  425 + }
  426 +
  427 + .number {
  428 + font-size: 28rpx;
  429 + line-height: 32rpx;
  430 + color: #909097;
  431 + }
  432 + }
  433 +
  434 + .company {
  435 + display: flex;
  436 + flex-flow: row nowrap;
  437 + margin: 0 0 30rpx 0;
  438 +
  439 + text {
  440 + font-size: 28rpx;
  441 + line-height: 32rpx;
  442 + color: #909097;
  443 + margin: 0 0 0 16rpx;
  444 + }
  445 +
  446 + text:last-child {
  447 + color: #202131;
  448 + margin: 0 0 0 30rpx;
  449 + }
  450 + }
  451 +
  452 + .statistics {
  453 + border-top: 2rpx solid #E2E2E8;
  454 + padding: 28rpx 0 0 0;
  455 + display: flex;
  456 + flex-flow: row nowrap;
  457 + justify-content: space-around;
  458 +
  459 + view {
  460 + text-align: center;
  461 +
  462 + text {
  463 + font-size: 32rpx;
  464 + line-height: 32rpx;
  465 + color: #06B079;
  466 + }
  467 +
  468 + text:last-child {
  469 + display: block;
  470 + font-size: 24rpx;
  471 + color: #909097;
  472 + margin: 16rpx 0 0 0;
  473 + }
  474 + }
  475 +
  476 + .line {
  477 + height: 32rpx;
  478 + border-right: 2rpx solid #E2E2E8;
  479 + position: relative;
  480 + top: 30rpx;
  481 + }
  482 +
  483 +
  484 + }
  485 + }
  486 + }
  487 +
  488 + .popup_search {
  489 + width: 640rpx;
  490 + position: relative;
  491 +
  492 + .content {
  493 + padding: 0 40rpx;
  494 +
  495 + .title {
  496 + padding: 24rpx 0;
  497 + font-size: 28rpx;
  498 + line-height: 36rpx;
  499 + color: #202131;
  500 + }
  501 +
  502 + .scroll {
  503 + max-height: 60vh;
  504 +
  505 + .item {
  506 + width: 540rpx;
  507 + height: 96rpx;
  508 + border-radius: 4rpx;
  509 + border: 2rpx solid #C1C1C9;
  510 + margin: 0 10rpx 20rpx;
  511 + font-size: 24rpx;
  512 + line-height: 32rpx;
  513 + color: #C0C0C9;
  514 + display: flex;
  515 + flex-flow: row wrap;
  516 + align-items: center;
  517 +
  518 + text {
  519 + display: inline-block;
  520 + width: 500rpx;
  521 + height: 64rpx;
  522 + padding: 16rpx 20rpx;
  523 + }
  524 +
  525 +
  526 + }
  527 + }
  528 +
  529 + .time {
  530 + padding: 40rpx 0 0 0;
  531 + }
  532 +
  533 + .switch {
  534 + display: flex;
  535 + flex-flow: row nowrap;
  536 + justify-content: space-between;
  537 + padding: 40rpx 0 0 0;
  538 +
  539 + text {
  540 + font-size: 28rpx;
  541 + line-height: 36rpx;
  542 + color: #202131;
  543 + }
  544 + }
  545 +
  546 +
  547 + }
  548 +
  549 + .footer {
  550 + width: 560rpx;
  551 + height: 96rpx;
  552 + padding: 28rpx 40rpx;
  553 + background: #FFFFFF;
  554 + position: fixed;
  555 + bottom: 0;
  556 + right: 0;
  557 + z-index: 99;
  558 + border-top: 2rpx solid #E2E2E8;
  559 +
  560 + view {
  561 + display: inline-block;
  562 + }
  563 +
  564 + .left_btn {
  565 + width: 194rpx;
  566 + margin: 0 20rpx 0 0;
  567 + }
  568 +
  569 + .right_btn {
  570 + width: 346rpx;
  571 + }
  572 + }
  573 + }
  574 + }
  575 +</style>
... ...
  1 +<template>
  2 + <view class="report_detail">
  3 + <view class="box form_info">
  4 + <view class="info">
  5 + <view class="avatar">{{getNameLastTwo(detail.studentName)}}</view>
  6 + <view class="name">{{overflowHide(detail.studentName, 6)}}</view>
  7 + <view class="number">NO.{{detail.studentNumber}}</view>
  8 + </view>
  9 + <view class="company">
  10 + <text>实习单号</text>
  11 + <text>{{detail.number || '--'}}</text>
  12 + </view>
  13 + <view class="company">
  14 + <text>实习项目</text>
  15 + <text>{{detail.projectName|| '--'}}</text>
  16 + </view>
  17 + </view>
  18 +
  19 + <view class="box attendance">
  20 + <view class="title">考勤</view>
  21 + <view class="item_icon">
  22 + <text>考勤天数</text>
  23 + <view @click="handelRecord('daily')">
  24 + <text>38天</text>
  25 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  26 + </view>
  27 + </view>
  28 + </view>
  29 +
  30 + <view class="box attendance">
  31 + <view class="title">提交材料</view>
  32 + <view class="item_icon">
  33 + <text>三方协议</text>
  34 + <view @click="handelRecord('aggrent')">
  35 + <text>查看</text>
  36 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  37 + </view>
  38 + </view>
  39 + <view class="item_icon">
  40 + <text>日志</text>
  41 + <view @click="handelRecord('daily')">
  42 + <text>{{detail.dailyLogCount || 0}}篇</text>
  43 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  44 + </view>
  45 + </view>
  46 + <view class="item_icon">
  47 + <text>周志</text>
  48 + <view @click="handelRecord('weekly')">
  49 + <text>{{detail.weekLogCount || 0}}篇</text>
  50 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  51 + </view>
  52 + </view>
  53 + <view class="item_icon">
  54 + <text>月志</text>
  55 + <view @click="handelRecord('monthly')">
  56 + <text>{{detail.monthlyLogCount || 0}}篇</text>
  57 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  58 + </view>
  59 + </view>
  60 + <view class="item_icon">
  61 + <text>实习报告</text>
  62 + <view @click="handelRecord('report')">
  63 + <text>{{detail.internshipReportCount || 0}}次</text>
  64 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  65 + </view>
  66 + </view>
  67 + </view>
  68 +
  69 + <view class="footer" v-if="detail.appraisalStatus == 'no_appraisal'">
  70 + <view class="right_btn">
  71 + <c-button type="confirm" text="成绩鉴定" @click="showModal = true">
  72 + </c-button>
  73 + </view>
  74 + </view>
  75 +
  76 + <u-overlay :show="showModal">
  77 + <view class="modal" v-show="showModal">
  78 + <view class="title">成绩鉴定</view>
  79 + <u-form labelPosition="top" :model="form" :rules="rules" :error-type="errorType" ref="uForm">
  80 +
  81 + <u-form-item label="成绩" labelWidth="100rpx" borderBottom prop="score"
  82 + v-if="detail.markWay == 'centesimal'">
  83 + <u-input v-model="form.score" border="none" type="number" :placeholderStyle="{color: 'C1C1C9'}"
  84 + placeholder="请输入" />
  85 + </u-form-item>
  86 +
  87 + <u-form-item label="成绩" @click="showSex = true" labelWidth="100rpx" borderBottom prop="level"
  88 + v-else>
  89 + <u-radio-group v-model="form.level" placement="row">
  90 + <u-radio :customStyle="{marginRight: '24rpx'}" size="28rpx" labelSize="28rpx"
  91 + v-for="(item, index) in radiolist" :key="index" :label="item.name" :name="item.name"
  92 + activeColor="#06B079">
  93 + </u-radio>
  94 + </u-radio-group>
  95 +
  96 +
  97 + </u-form-item>
  98 +
  99 + <u-form-item label="学分" labelWidth="100rpx" borderBottom prop="credit">
  100 + <u-input v-model="form.credit" type="number" border="none" :placeholderStyle="{color: 'C1C1C9'}"
  101 + placeholder="请输入" />
  102 + </u-form-item>
  103 +
  104 + <u-form-item label="评价" labelWidth="100rpx" borderBottom prop="teacherView">
  105 + <u-textarea v-model="form.teacherView" count border="none" :placeholderStyle="{color: 'C1C1C9'}"
  106 + placeholder="请输入评价"></u-textarea>
  107 + </u-form-item>
  108 +
  109 + </u-form>
  110 +
  111 + <view class="moda_footer">
  112 + <view class="left_btn">
  113 + <c-button type="cancel" text="取消" @click="handelCancel">
  114 + </c-button>
  115 + </view>
  116 + <view class="right_btn">
  117 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  118 + </c-button>
  119 + </view>
  120 + </view>
  121 +
  122 +
  123 + </view>
  124 + </u-overlay>
  125 +
  126 + </view>
  127 +</template>
  128 +
  129 +<script>
  130 + import {
  131 + mapGetters,
  132 + mapState,
  133 + mapActions
  134 + } from 'vuex'
  135 + import listMixin from "@/common/mixins/list-mixin.js";
  136 +
  137 + import {
  138 + getAchievementDetailApi,
  139 + putAchievementAppraisalApi,
  140 + } from '@/config/api.js';
  141 +
  142 + export default {
  143 + data() {
  144 + return {
  145 + id: '',
  146 + detail: {},
  147 + showModal: false,
  148 + errorType: ['toast'],
  149 + radiolist: [{
  150 + name: '优秀',
  151 + disabled: false
  152 + },
  153 + {
  154 + name: '良好',
  155 + disabled: false
  156 + },
  157 + {
  158 + name: '及格',
  159 + disabled: false
  160 + }, {
  161 + name: '不及格',
  162 + disabled: false
  163 + }
  164 + ],
  165 + form: {
  166 + score: '',
  167 + level: '',
  168 + credit: '',
  169 + teacherView: '',
  170 +
  171 + },
  172 + rules: {
  173 + score: [{
  174 + required: true,
  175 + message: '请输入成绩',
  176 + trigger: ['blur', 'change'],
  177 + }, {
  178 + validator: (rule, value, callback) => {
  179 + return this.$u.test.range(value, [0, 100]);
  180 + },
  181 + message: '手机号码不正确',
  182 + trigger: ['change', 'blur'],
  183 + }],
  184 + level: [{
  185 + required: true,
  186 + message: '请选择成绩',
  187 + trigger: ['blur', 'change'],
  188 + }, ],
  189 + credit: [{
  190 + required: true,
  191 + message: '请输入学分',
  192 + trigger: ['blur', 'change'],
  193 + }],
  194 + teacherView: [],
  195 + },
  196 + }
  197 + },
  198 +
  199 + onLoad(option) {
  200 + this.id = option.id;
  201 + getAchievementDetailApi(option.id).then(data => {
  202 + if (data) {
  203 + this.detail = data;
  204 + this.form.credit = String(data.credit);
  205 + }
  206 + })
  207 + },
  208 +
  209 + onReady() {
  210 + this.$refs.uForm.setRules(this.rules);
  211 + },
  212 +
  213 + methods: {
  214 +
  215 + getNameLastTwo(value) {
  216 + if (value && value.length > 3) {
  217 + return value.substring(value.length - 3)
  218 + } else {
  219 + return value;
  220 + }
  221 + },
  222 +
  223 + overflowHide(value, num = 4) {
  224 + if (value && value.length > num) {
  225 + return `${value.slice(0, num)}...`
  226 + } else {
  227 + return value;
  228 + }
  229 + },
  230 +
  231 + handelRecord(type) {
  232 +
  233 + switch (type) {
  234 + case 'aggrent':
  235 + this.$u.route({
  236 + url: `pages/main/home/approvalRecord/approvalRecord?formId=${this.detail.id}`
  237 + })
  238 + break;
  239 +
  240 + case 'daily':
  241 + this.$u.route({
  242 + url: `pages/main/home/logReview/logReview?cagegory=daily`
  243 + })
  244 + break;
  245 +
  246 + case 'weekly':
  247 + this.$u.route({
  248 + url: `pages/main/home/logReview/logReview?cagegory=weekly`
  249 + })
  250 + break;
  251 +
  252 + case 'monthly':
  253 + this.$u.route({
  254 + url: `pages/main/home/logReview/logReview?cagegory=monthly`
  255 + })
  256 + break;
  257 +
  258 + case 'report':
  259 + this.$u.route({
  260 + url: `pages/main/home/logDetail/logDetail?id=${this.detail.reportId}`
  261 + })
  262 + break;
  263 + }
  264 +
  265 + },
  266 +
  267 + handelCancel() {
  268 + this.showModal = false;
  269 + },
  270 +
  271 + hancelSubmit() {
  272 + let {
  273 + credit = ''
  274 + } = this.form;
  275 +
  276 + console.log(this.form)
  277 +
  278 + if (String(credit) && credit > this.detail.credit) {
  279 + this.$u.toast('学分不正确');
  280 + return;
  281 + }
  282 +
  283 + this.$refs.uForm.validate().then(res => {
  284 + uni.$u.toast('校验通过');
  285 +
  286 + putAchievementAppraisalApi({
  287 + items: [{
  288 + id: this.detail.id,
  289 + ...this.form
  290 + }]
  291 + }).then(data => {
  292 + if (data) {
  293 + this.showModal = false;
  294 +
  295 + this.$u.route({
  296 + url: `pages/main/home/achievementAppraisal/achievementAppraisal`
  297 + })
  298 + }
  299 + })
  300 +
  301 +
  302 + }).catch(errors => {
  303 + console.log(errors)
  304 + uni.$u.toast('校验失败')
  305 + })
  306 +
  307 + },
  308 + }
  309 + }
  310 +</script>
  311 +
  312 +<style lang="scss" scoped>
  313 + .report_detail {
  314 + width: 100%;
  315 + min-height: 100%;
  316 + height: auto;
  317 + background-color: #F7F7F7;
  318 + padding: 20rpx 0 0 0;
  319 +
  320 + .box {
  321 + width: 630rpx;
  322 + margin: 20rpx auto;
  323 + padding: 30rpx 30rpx 12rpx 30rpx;
  324 + border-radius: 12rpx;
  325 + background-color: #FFFFFF;
  326 +
  327 + .title {
  328 + font-size: 32rpx;
  329 + line-height: 32rpx;
  330 + color: #202131;
  331 + margin: 0 0 30rpx 0;
  332 + }
  333 +
  334 + .title::before {
  335 + content: "";
  336 + display: inline-block;
  337 + width: 6rpx;
  338 + height: 32rpx;
  339 + background-color: #06B079;
  340 + margin: 0 12rpx 0 0;
  341 + position: relative;
  342 + top: 4rpx;
  343 + border-radius: 8rpx;
  344 + }
  345 +
  346 + .item {
  347 + margin: 0 0 24rpx 0;
  348 +
  349 + text:first-child {
  350 + display: inline-block;
  351 + width: 112rpx;
  352 + text-align: justify;
  353 + text-align-last: justify;
  354 + font-size: 28rpx;
  355 + line-height: 48rpx;
  356 + color: #909097;
  357 + vertical-align: top;
  358 + }
  359 +
  360 + text:last-child {
  361 + display: inline-block;
  362 + width: 440rpx;
  363 + font-size: 28rpx;
  364 + line-height: 48rpx;
  365 + color: #202131;
  366 + margin: 0 0 0 78rpx;
  367 + }
  368 + }
  369 +
  370 + .item_icon {
  371 + margin: 0 0 24rpx 0;
  372 + display: flex;
  373 + flex-flow: row nowrap;
  374 + justify-content: space-between;
  375 +
  376 + text {
  377 + display: inline-block;
  378 + width: 112rpx;
  379 + text-align: justify;
  380 + text-align-last: justify;
  381 + font-size: 28rpx;
  382 + line-height: 48rpx;
  383 + color: #909097;
  384 + vertical-align: top;
  385 + }
  386 +
  387 + view {
  388 + display: flex;
  389 + flex-flow: row nowrap;
  390 +
  391 + text {
  392 + display: inline-block;
  393 + width: auto;
  394 + font-size: 28rpx;
  395 + line-height: 48rpx;
  396 + color: #202131;
  397 + margin: 0 0 0 78rpx;
  398 + }
  399 + }
  400 + }
  401 + }
  402 +
  403 + .form_info {
  404 + .info {
  405 + display: flex;
  406 + flex-flow: row nowrap;
  407 + align-items: center;
  408 + margin: 0 0 30rpx 0;
  409 +
  410 + .avatar {
  411 + width: 94rpx;
  412 + height: 94rpx;
  413 + padding: 0 8rpx;
  414 + border-radius: 4rpx;
  415 + background-color: #06B079;
  416 + font-size: 24rpx;
  417 + line-height: 94rpx;
  418 + color: #FFFFFF;
  419 + text-align: center;
  420 + }
  421 +
  422 + .name {
  423 + font-size: 32rpx;
  424 + line-height: 44rpx;
  425 + color: #202131;
  426 + font-weight: 500;
  427 + margin: 0 20rpx;
  428 + }
  429 +
  430 + .number {
  431 + font-size: 28rpx;
  432 + line-height: 32rpx;
  433 + color: #909097;
  434 + }
  435 + }
  436 +
  437 + .company {
  438 + display: flex;
  439 + flex-flow: row nowrap;
  440 + margin: 0 0 30rpx 0;
  441 +
  442 + text {
  443 + font-size: 28rpx;
  444 + line-height: 32rpx;
  445 + color: #909097;
  446 + margin: 0 0 0 16rpx;
  447 + }
  448 +
  449 + text:last-child {
  450 + color: #202131;
  451 + margin: 0 0 0 30rpx;
  452 + }
  453 + }
  454 + }
  455 +
  456 + .footer {
  457 + width: 100%;
  458 + height: 96rpx;
  459 + padding: 28rpx 30rpx;
  460 + background: #FFFFFF;
  461 + position: fixed;
  462 + bottom: 0;
  463 + left: 0;
  464 + z-index: 99;
  465 + border-top: 2rpx solid #E2E2E8;
  466 +
  467 + view {
  468 + display: inline-block;
  469 + }
  470 +
  471 + .right_btn {
  472 + width: 690rpx;
  473 + }
  474 + }
  475 +
  476 + .modal {
  477 + width: 570rpx;
  478 + position: relative;
  479 + display: flex;
  480 + flex-direction: column;
  481 + margin: 200rpx auto;
  482 + padding: 40rpx;
  483 + border-radius: 20rpx;
  484 + background-color: #fff;
  485 +
  486 + .title {
  487 + text-align: center;
  488 + font-size: 36rpx;
  489 + line-height: 48rpx;
  490 + color: #202131;
  491 + margin: 0 0 66rpx 0;
  492 + }
  493 +
  494 + .moda_footer {
  495 + width: 590rpx;
  496 + height: 96rpx;
  497 + padding: 40rpx 0 0 0;
  498 +
  499 + view {
  500 + display: inline-block;
  501 + width: 260rpx;
  502 + }
  503 +
  504 + .left_btn {
  505 + margin: 0 48rpx 0 0;
  506 + }
  507 +
  508 + .right_btn {}
  509 + }
  510 +
  511 +
  512 + }
  513 + }
  514 +</style>
... ...
  1 +<template>
  2 + <view class="report_detail">
  3 + <view class="list_box" v-if="list.length > 0">
  4 + <view class="item" v-for="(item, i) in list" :key="i">
  5 +
  6 + <view class="bg_image" v-if="item.status == 'adopt'">
  7 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  8 + <text>已批阅</text>
  9 + </view>
  10 +
  11 + <view class="bg_image" v-else>
  12 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  13 + <text>待批阅</text>
  14 + </view>
  15 +
  16 + <view class="info">
  17 + <u-image src="/static/img/home/报告@2x.png" width="94rpx" height="94rpx" />
  18 + <view class="title_name">
  19 + <view class="title">
  20 + {{item.title}}
  21 + </view>
  22 + <view class="time">
  23 +
  24 + <text>创建时间</text>
  25 + <text>
  26 + {{timeFormat(item.createdTime, 'yyyy-mm-dd hh:MM')}}
  27 + </text>
  28 + </view>
  29 + </view>
  30 + </view>
  31 +
  32 + </view>
  33 + <c-loading :loading="loading"></c-loading>
  34 + </view>
  35 + <view v-else class="no_data">
  36 + <c-no-data></c-no-data>
  37 + </view>
  38 +
  39 + <view class="report_info">
  40 +
  41 +
  42 + </view>
  43 + </view>
  44 +</template>
  45 +
  46 +<script>
  47 + import {
  48 + mapGetters,
  49 + mapState,
  50 + mapActions
  51 + } from 'vuex'
  52 + import listMixin from "@/common/mixins/list-mixin.js";
  53 +
  54 + import {
  55 + getReportApprovalListApi,
  56 + } from '@/config/api.js';
  57 +
  58 + export default {
  59 + data() {
  60 + return {
  61 + formId: '',
  62 + list: [],
  63 + }
  64 + },
  65 +
  66 + onLoad(option) {
  67 + this.formId = option.formId;
  68 + getReportApprovalListApi(option.formId).then(data => {
  69 + if (data) {
  70 + this.list = data
  71 + }
  72 + })
  73 + },
  74 +
  75 + methods: {
  76 +
  77 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  78 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  79 + },
  80 +
  81 + }
  82 + }
  83 +</script>
  84 +
  85 +<style lang="scss" scoped>
  86 + .report_detail {
  87 + width: 100%;
  88 + min-height: 100%;
  89 + height: auto;
  90 + background-color: #F7F7F7;
  91 + padding: 20rpx 0 0 0;
  92 +
  93 + .list_box {
  94 + padding: 0 0 50rpx 0;
  95 +
  96 + .item {
  97 + position: relative;
  98 + width: 630rpx;
  99 + margin: 30rpx auto;
  100 + padding: 30rpx;
  101 + border-radius: 12rpx;
  102 + background-color: #FFFFFF;
  103 +
  104 + .bg_image {
  105 + position: absolute;
  106 + top: 0;
  107 + right: 0;
  108 +
  109 + text {
  110 + position: absolute;
  111 + top: 12rpx;
  112 + right: 30rpx;
  113 + font-size: 24rpx;
  114 + line-height: 24rpx;
  115 + color: #FFFFFF;
  116 + }
  117 + }
  118 +
  119 + .info {
  120 + display: flex;
  121 + flex-flow: row nowrap;
  122 + align-items: center;
  123 + margin: 0 0 30rpx 0;
  124 +
  125 + .title_name {
  126 + .title {
  127 + font-size: 32rpx;
  128 + line-height: 44rpx;
  129 + color: #202131;
  130 + font-weight: 500;
  131 + margin: 0 20rpx;
  132 + }
  133 +
  134 + .time {
  135 + padding: 8rpx 0 0 20rpx;
  136 + font-size: 28rpx;
  137 + line-height: 32rpx;
  138 + color: #909097;
  139 +
  140 + text:last-child {
  141 + padding: 0 0 0 30rpx;
  142 + }
  143 + }
  144 + }
  145 + }
  146 + }
  147 + }
  148 + }
  149 +</style>
... ...
  1 +<template>
  2 + <view class=".log_detail">
  3 +
  4 + <view class="header_box">
  5 + <view class="header">
  6 + <view class="avatar">{{getNameLastTwo(detail.studentName)}}</view>
  7 + <view class="form_name">
  8 + <view class="name">{{overflowHide(detail.studentName, 4)}}</view>
  9 + <view class="week">
  10 + <text>{{timeFormat(detail.logTime, 'yyyy年')}}</text>
  11 + <text>{{getWeek(detail.logTime)}}</text>
  12 + </view>
  13 + </view>
  14 + <view class="status" v-if="detail.status == 'read'">
  15 + <text>已阅</text>
  16 + </view>
  17 +
  18 + <view class="status" v-else>
  19 + <text>未阅</text>
  20 + </view>
  21 + </view>
  22 + </view>
  23 +
  24 + <view class="content">
  25 + <view class="name_time">
  26 + <view class="title">{{detail.title}}</view>
  27 + <view class="time">创建时间:{{timeFormat(detail.createdTime)}}</view>
  28 + </view>
  29 +
  30 + <view class="u-parse">
  31 + <u-parse :content="detail.content"></u-parse>
  32 + </view>
  33 +
  34 + <view v-if="commentList.length>0" class="reply">
  35 + <view class="title">评论</view>
  36 + <view v-for="(item,index) in commentList" :key="index">
  37 + <view v-if="index!=0" class="divide_line_padding"></view>
  38 + <view class="list">
  39 + <view style="margin-top: 8rpx;" class="userInfo">
  40 + <text> {{item.name?item.name:"佚名"}}</text>
  41 + <text>({{userType[item.userType]}})</text>
  42 + </view>
  43 + <view class="replyTime" style="margin-top: 8rpx;">{{timeFormat(item.createdTime)}}</view>
  44 + <view class="describe" style="margin-top: 8rpx;">{{item.content}}</view>
  45 + <view v-if="false" class="" v-for="(item1,index) in item.replies">
  46 + <view class="reply_bg">
  47 + {{item1}}
  48 + </view>
  49 + </view>
  50 + </view>
  51 + </view>
  52 + </view>
  53 +
  54 + </view>
  55 +
  56 +
  57 + <view class="footer">
  58 + <view class="divide_line"></view>
  59 + <input class="uni-input" placeholder="这么精彩,不说点什么吗?" :value="reply" confirm-type="send" @confirm="goReply" />
  60 + </view>
  61 + </view>
  62 +</template>
  63 +
  64 +<script>
  65 + import {
  66 + mapGetters,
  67 + mapState,
  68 + mapActions
  69 + } from 'vuex'
  70 +
  71 + import {
  72 + getLogDetailApi,
  73 + getLogReplyListApi,
  74 + postLogReplyApi,
  75 + } from '@/config/api.js';
  76 + export default {
  77 + data() {
  78 + return {
  79 + id: "",
  80 + formLogId: "",
  81 + show: false,
  82 + reply: '',
  83 + content: "",
  84 + style: {
  85 + // 字符串的形式
  86 + p: 'color: red;font-size:32rpx',
  87 + span: 'font-size: 30rpx'
  88 + },
  89 + detail: {},
  90 + userType: {
  91 + "student": "学生",
  92 + "teacher": "学校",
  93 + "company": "企业"
  94 + },
  95 + commentList: [],
  96 + }
  97 + },
  98 +
  99 + onLoad(option) {
  100 +
  101 + this.id = option.id;
  102 + getLogDetailApi(option.id).then(data => {
  103 + if (data) {
  104 + this.detail = data
  105 + }
  106 + })
  107 +
  108 + this.getCommentList()
  109 +
  110 + },
  111 +
  112 + methods: {
  113 + getWeek(dt) {
  114 + if (dt && dt > 0) {
  115 + let d1 = new Date(dt);
  116 + let d2 = new Date(dt);
  117 + d2.setMonth(0);
  118 + d2.setDate(1);
  119 + let rq = d1 - d2;
  120 + let days = Math.ceil(rq / (24 * 60 * 60 * 1000));
  121 + let num = Math.ceil(days / 7);
  122 + return `第${num}周`;
  123 + } else {
  124 + return '';
  125 + }
  126 + },
  127 +
  128 + getNameLastTwo(value) {
  129 +
  130 + if (value && value.length > 3) {
  131 + return value.substring(value.length - 3)
  132 + } else {
  133 + return value;
  134 + }
  135 + },
  136 +
  137 + overflowHide(value, num = 4) {
  138 + if (value && value.length > num) {
  139 + return `${value.slice(0, num)}...`
  140 + } else {
  141 + return value;
  142 + }
  143 + },
  144 +
  145 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  146 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  147 + },
  148 +
  149 + getCommentList() {
  150 + getLogReplyListApi({
  151 + formLogId: this.id
  152 + }).then(data => {
  153 + console.log(data)
  154 + if (data) {
  155 + this.commentList = data.records;
  156 + }
  157 + })
  158 + },
  159 +
  160 + getCreatedTime(e) {
  161 + return this.$u.timeFormat(e / 1000, 'yyyy/mm/dd');
  162 + },
  163 +
  164 + goReply(e) { //回复评论
  165 + console.log(e)
  166 + this.reply = e.target.value
  167 + postLogReplyApi({
  168 + formLogId: this.id,
  169 + content: e.target.value
  170 + }).then(data => {
  171 + this.reply = ''
  172 + this.getCommentList()
  173 + })
  174 + }
  175 + }
  176 + }
  177 +</script>
  178 +
  179 +<style lang="scss" scoped>
  180 + .log_detail {
  181 + width: 100%;
  182 + min-height: 100%;
  183 + height: auto;
  184 + background-color: #F7F7F7;
  185 +
  186 + .header_box {
  187 + background-color: #FFFFFF;
  188 +
  189 + .header {
  190 + display: flex;
  191 + flex-flow: row nowrap;
  192 + align-items: center;
  193 + padding: 52rpx 0;
  194 + margin: 0 30rpx;
  195 + position: relative;
  196 + border-bottom: 2rpx solid #E2E2E8;
  197 + background-color: #FFFFFF;
  198 +
  199 + .avatar {
  200 + width: 94rpx;
  201 + height: 94rpx;
  202 + border-radius: 4rpx;
  203 + background-color: #06B079;
  204 + font-size: 24rpx;
  205 + line-height: 94rpx;
  206 + color: #FFFFFF;
  207 + text-align: center;
  208 + }
  209 +
  210 + .form_name {
  211 + .name {
  212 + font-size: 32rpx;
  213 + line-height: 44rpx;
  214 + color: #202131;
  215 + font-weight: 500;
  216 + margin: 0 20rpx;
  217 + }
  218 +
  219 + .week {
  220 + padding: 8rpx 0 0 0;
  221 + font-size: 24rpx;
  222 + line-height: 32rpx;
  223 + color: #909097;
  224 +
  225 + text {
  226 + padding: 8rpx 0 0 20rpx;
  227 + }
  228 + }
  229 + }
  230 +
  231 + .status {
  232 + font-size: 24rpx;
  233 + line-height: 34rpx;
  234 + color: #FFFFFF;
  235 + width: 112rpx;
  236 + height: 48rpx;
  237 + line-height: 48rpx;
  238 + text-align: center;
  239 + border-radius: 200rpx;
  240 + background-color: #06B079;
  241 + position: absolute;
  242 + top: 74rpx;
  243 + right: 0;
  244 + }
  245 + }
  246 + }
  247 +
  248 + .content {
  249 +
  250 + padding: 16rpx 0 150rpx;
  251 +
  252 + .name_time {
  253 + background-color: #FFFFFF;
  254 + padding: 26rpx 30rpx;
  255 + .title {
  256 + font-size: 36rpx;
  257 + line-height: 50rpx;
  258 + color: #06B079;
  259 + }
  260 +
  261 + .time {
  262 + padding: 6rpx 0 0 0;
  263 + font-size: 24rpx;
  264 + line-height: 32rpx;
  265 + color: #909097;
  266 + padding: 0 0 26rpx 0;
  267 + }
  268 + }
  269 +
  270 + .u-parse {
  271 + background-color: #FFFFFF;
  272 + padding: 0 30rpx 50rpx;
  273 + font-size: 28rpx;
  274 + line-height: 36rpx;
  275 + color: #4A4A53;
  276 + }
  277 +
  278 + .reply {
  279 + background-color: #fff;
  280 + padding: 50rpx 30rpx 150rpx;
  281 + margin: 16rpx 0 0 0;
  282 +
  283 + .title {
  284 + font-size: 34rpx;
  285 + line-height: 48rpx;
  286 + color: #202131;
  287 + }
  288 +
  289 + .list {
  290 + padding: 32rpx;
  291 + border-bottom: 2rpx solid #E2E2E8;
  292 +
  293 + .userInfo {
  294 + color: rgba(0, 0, 0, 0.4500);
  295 + font-size: 28rpx;
  296 + line-height: 40rpx;
  297 + }
  298 +
  299 + .replyTime {
  300 + color: rgba(0, 0, 0, 0.4500);
  301 + font-size: 26rpx;
  302 + line-height: 36rpx;
  303 + }
  304 +
  305 +
  306 + }
  307 +
  308 + .reply_bg {
  309 + background: rgba(0, 0, 0, 0.03);
  310 + border-radius: 8rpx;
  311 + padding: 20rpx 32rpx;
  312 + margin-top: 16rpx;
  313 + }
  314 + }
  315 + }
  316 +
  317 + }
  318 +
  319 + .footer {
  320 + width: 100%;
  321 + height: 130rpx;
  322 + background: #fff;
  323 + position: fixed;
  324 + bottom: 0;
  325 + left: 0;
  326 + z-index: 99;
  327 +
  328 + .uni-input {
  329 + height: 96rpx;
  330 + background: rgba(0, 0, 0, 0.04);
  331 + border-radius: 8rpx;
  332 + margin: 10rpx 32rpx 32rpx 32rpx;
  333 + padding: 0 20rpx;
  334 + }
  335 + }
  336 +</style>
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 + <view class="search_box">
  4 + <view class="check">
  5 + <u-checkbox-group v-model="checkboxValue" placement="column" @change="checkboxChange">
  6 + <u-checkbox :customStyle="{marginBottom: '8px'}" shape="circle"
  7 + v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"
  8 + activeColor="#06B079" size="28rpx" labelSize="28rpx" labelColor="#202131">
  9 + </u-checkbox>
  10 + </u-checkbox-group>
  11 + </view>
  12 +
  13 + <view class="search">
  14 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  15 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  16 + </u-search>
  17 + </view>
  18 +
  19 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  20 + </view>
  21 +
  22 + <u-sticky bgColor="#fff">
  23 + <u-tabs :list="tabs" :scrollable="false" lineWidth="30rpx" lineHeight="4rpx" lineColor="#06B079"
  24 + :inactiveStyle="{fontSize:'28rpx', color:'#4A4A53'}" :activeStyle="{fontSize:'36rpx', color:'#06B079'}"
  25 + @change="handelTab" :current="current">
  26 + </u-tabs>
  27 + </u-sticky>
  28 +
  29 + <view class="list_box" v-if="list.length > 0">
  30 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  31 +
  32 + <view class="bg_image" v-if="item.status == 'read'">
  33 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  34 + <text>已阅</text>
  35 + </view>
  36 +
  37 + <view class="bg_image" v-else>
  38 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  39 + <text>未阅</text>
  40 + </view>
  41 +
  42 + <view class="info">
  43 + <view class="avatar">{{getNameLastTwo(item.studentName)}}</view>
  44 + <view class="form_name">
  45 + <view class="name">{{overflowHide(item.projectName, 10)}}</view>
  46 + <view class="week">
  47 + <text>{{timeFormat(item.logTime, 'yyyy年')}}</text>
  48 + <text>{{getWeek(item.logTime)}}</text>
  49 + </view>
  50 + </view>
  51 + </view>
  52 + <view class="u-content">
  53 + <u-parse :content="item.content"></u-parse>
  54 + </view>
  55 + <view class="name_time">
  56 + <view class="name">
  57 + <text>学生姓名</text>
  58 + <text>{{item.studentName}}</text>
  59 + </view>
  60 + <view class="time">{{timeFormat(item.createdTime)}}</view>
  61 + </view>
  62 +
  63 + </view>
  64 + <c-loading :loading="loading"></c-loading>
  65 + </view>
  66 + <view v-else class="no_data">
  67 + <c-no-data></c-no-data>
  68 + </view>
  69 +
  70 + <u-popup :show="show" mode="right" @close="close" @open="open">
  71 + <view class="popup_search">
  72 + <view class="content">
  73 + <view class="title">按项目筛选</view>
  74 + <scroll-view class="scroll" scroll-y="true">
  75 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  76 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  77 + <text>{{item.name}}</text>
  78 + </view>
  79 + <view v-else>
  80 + <text>{{item.name}}</text>
  81 + </view>
  82 + </view>
  83 + </scroll-view>
  84 + <view class="switch">
  85 + <text>未阅</text>
  86 + <u-switch v-model="switchValue" size="48" activeColor="#06B079" @change="handelChange">
  87 + </u-switch>
  88 + </view>
  89 + </view>
  90 +
  91 + <view class="footer">
  92 + <view class="left_btn">
  93 + <c-button type="cancel" text="重置" @click="handelCancel">
  94 + </c-button>
  95 + </view>
  96 + <view class="right_btn">
  97 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  98 + </c-button>
  99 + </view>
  100 + </view>
  101 + </view>
  102 + </u-popup>
  103 + </view>
  104 +</template>
  105 +
  106 +<script>
  107 + import {
  108 + mapGetters,
  109 + mapState,
  110 + mapActions
  111 + } from 'vuex'
  112 + import listMixin from "@/common/mixins/list-mixin.js";
  113 +
  114 + import {
  115 + getLogReviewListApi,
  116 + getProjectListApi,
  117 + } from '@/config/api.js';
  118 +
  119 + export default {
  120 + mixins: [listMixin],
  121 + data() {
  122 + return {
  123 + checkboxValue: [],
  124 + checkboxList: [{
  125 + name: '未阅',
  126 + disabled: false
  127 + }],
  128 + keyword: '',
  129 + search: {
  130 + //搜索对象必须为key search的对象
  131 + keySearch: "",
  132 + status: '',
  133 + cagegory: 'daily',
  134 +
  135 + },
  136 + show: false, //筛选
  137 + current: 0,
  138 + tabs: [{
  139 + name: '日志',
  140 + }, {
  141 + name: '周志',
  142 + }, {
  143 + name: '月志'
  144 + }],
  145 +
  146 + list: [], //列表必须为key list的数组
  147 +
  148 + projectId: '',
  149 + showTime: false,
  150 + timeValue: '',
  151 + switchValue: false,
  152 +
  153 + }
  154 + },
  155 +
  156 + onLoad(option) {
  157 + console.log(option)
  158 +
  159 + this.$store.dispatch(`home/getProjectList`, {
  160 + pageSize: -1,
  161 + })
  162 +
  163 + this.search.keySearch = '';
  164 +
  165 + if (option && option.cagegory) {
  166 + this.search.cagegory = option.cagegory;
  167 + this.current =
  168 + option.cagegory == 'daily' ? 0 :
  169 + option.cagegory == 'weekly' ? 1 :
  170 + option.cagegory == 'monthly' ? 2 :
  171 + '';
  172 + }
  173 +
  174 + this.finished = false;
  175 + this.loading = "loadmore";
  176 + this.page = 0;
  177 + this.list = [];
  178 + this._getList();
  179 + },
  180 +
  181 + onShow(option) {
  182 +
  183 + console.log(option)
  184 +
  185 + },
  186 +
  187 + computed: {
  188 + ...mapState('home', {
  189 + // 箭头函数可使代码更简练
  190 + projectList: 'projectList',
  191 + }),
  192 + },
  193 +
  194 + methods: {
  195 +
  196 + getWeek(dt) {
  197 + if (dt > 0) {
  198 + let d1 = new Date(dt);
  199 + let d2 = new Date(dt);
  200 + d2.setMonth(0);
  201 + d2.setDate(1);
  202 + let rq = d1 - d2;
  203 + let days = Math.ceil(rq / (24 * 60 * 60 * 1000));
  204 + let num = Math.ceil(days / 7);
  205 + return `第${num}周`;
  206 + } else {
  207 + return '';
  208 + }
  209 + },
  210 +
  211 + getNameLastTwo(value) {
  212 + if (value && value.length > 3) {
  213 + return value.substring(value.length - 3)
  214 + } else {
  215 + return value;
  216 + }
  217 + },
  218 +
  219 + overflowHide(value, num = 4) {
  220 + if (value && value.length > num) {
  221 + return `${value.slice(0, num)}...`
  222 + } else {
  223 + return value;
  224 + }
  225 + },
  226 +
  227 + handelTab(item) {
  228 + let cagegory = item.index === 0 ? 'daily' : item.index === 1 ? 'weekly' : item.index === 2 ? 'monthly' :
  229 + '';
  230 +
  231 + this.search.cagegory = cagegory;
  232 +
  233 + this.finished = false;
  234 + this.loading = "loadmore";
  235 + this.page = 0;
  236 + this.list = [];
  237 + this._getList();
  238 +
  239 + },
  240 +
  241 + handelDetail(record) {
  242 + this.$u.route({
  243 + url: `pages/main/home/logDetail/logDetail?id=${record.id}&formId=${record.formId}`
  244 + })
  245 + },
  246 +
  247 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  248 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  249 + },
  250 +
  251 + checkboxChange(n) {
  252 + console.log('change', n);
  253 +
  254 + this.search.status = n.length > 0 ? 'unread' : '';
  255 +
  256 + this.switchValue = n.length > 0 ? true : false;
  257 +
  258 + this.finished = false;
  259 + this.loading = "loadmore";
  260 + this.page = 0;
  261 + this.list = [];
  262 + this._getList();
  263 + },
  264 +
  265 + handelSearch(value) {
  266 + this.finished = false;
  267 + this.loading = "loadmore";
  268 + this.page = 0;
  269 + this.list = [];
  270 + this._getList();
  271 + },
  272 +
  273 + open() {
  274 +
  275 + },
  276 +
  277 + close() {
  278 + this.show = false
  279 + },
  280 +
  281 + // scroll-view到底部加载更多
  282 + onreachBottom() {},
  283 + // 搜索
  284 + searchSubmit() {
  285 + // 调用混合搜索
  286 + this._searchData();
  287 + },
  288 + // 模拟后端分页
  289 + async getData(requestParams) {
  290 + const {
  291 + search = {}
  292 + } = requestParams;
  293 +
  294 + let params = {};
  295 + params.pageNumber = requestParams.page + 1;
  296 + params.pageSize = 5;
  297 +
  298 + if (search.status) {
  299 + params.status = search.status;
  300 + }
  301 +
  302 + if (search.cagegory) {
  303 + params.cagegory = search.cagegory;
  304 + }
  305 +
  306 + if (this.keyword) {
  307 + params.keySearch = this.keyword
  308 + }
  309 +
  310 + if (this.projectId) {
  311 + params.projectId = this.projectId
  312 + }
  313 +
  314 + return await getLogReviewListApi(params);
  315 + },
  316 + // 数据请求(没错就是这么少的代码)
  317 + async _getList() {
  318 + if (this.page == 0) {
  319 + this.list = [];
  320 + }
  321 +
  322 + // 根据实际情况修改自己修改key
  323 + let result = await this.getData({
  324 + page: this.page, // 传入页码
  325 + size: this.size, // 传入每页条数
  326 + search: this.search, // 传入搜索的对象
  327 + });
  328 +
  329 + this.total = result.total;
  330 +
  331 + if (this.list.length == 0 && result.records.length == 0) {
  332 + this.shownoData = false
  333 + } else {
  334 + this.shownoData = true
  335 + }
  336 +
  337 + this.list = this.list.concat(result.records)
  338 + },
  339 +
  340 + handelClick(values) {
  341 + this.projectId = values.id;
  342 + },
  343 +
  344 + handelChange(e) {
  345 + this.checkboxValue = e ? ['未阅'] : [];
  346 + this.search.status = e ? 'unread' : '';
  347 +
  348 + },
  349 +
  350 + handelCancel() {
  351 + this.switchValue = false;
  352 + this.projectId = '';
  353 + },
  354 +
  355 + hancelSubmit() {
  356 + this.finished = false;
  357 + this.loading = "loadmore";
  358 + this.page = 0;
  359 + this.list = [];
  360 + this._getList();
  361 +
  362 + this.show = false;
  363 + },
  364 +
  365 + }
  366 + }
  367 +</script>
  368 +
  369 +<style lang="scss" scoped>
  370 + .registration_review {
  371 + width: 100%;
  372 + min-height: 100%;
  373 + height: auto;
  374 + background-color: #F7F7F7;
  375 +
  376 + .search_box {
  377 + padding: 36rpx 30rpx 12rpx;
  378 + background-color: #FFFFFF;
  379 + display: flex;
  380 + flex-flow: row nowrap;
  381 + justify-content: space-between;
  382 +
  383 + .check {
  384 + padding: 20rpx 0 0 0;
  385 + }
  386 +
  387 + .search {
  388 + width: 468rpx;
  389 + }
  390 + }
  391 +
  392 + .list_box {
  393 + padding: 0 0 50rpx 0;
  394 +
  395 + .item {
  396 + position: relative;
  397 + width: 630rpx;
  398 + margin: 30rpx auto;
  399 + padding: 30rpx;
  400 + border-radius: 12rpx;
  401 + background-color: #FFFFFF;
  402 +
  403 + .bg_image {
  404 + position: absolute;
  405 + top: 0;
  406 + right: 0;
  407 +
  408 + text {
  409 + position: absolute;
  410 + top: 12rpx;
  411 + right: 30rpx;
  412 + font-size: 24rpx;
  413 + line-height: 24rpx;
  414 + color: #FFFFFF;
  415 + }
  416 + }
  417 +
  418 + .info {
  419 + display: flex;
  420 + flex-flow: row nowrap;
  421 + align-items: center;
  422 + margin: 0 0 30rpx 0;
  423 +
  424 + .avatar {
  425 + width: 94rpx;
  426 + height: 94rpx;
  427 + border-radius: 4rpx;
  428 + background-color: #06B079;
  429 + font-size: 24rpx;
  430 + line-height: 94rpx;
  431 + color: #FFFFFF;
  432 + text-align: center;
  433 + }
  434 +
  435 + .form_name {
  436 + .name {
  437 + font-size: 32rpx;
  438 + line-height: 44rpx;
  439 + color: #202131;
  440 + font-weight: 500;
  441 + margin: 0 20rpx;
  442 + }
  443 +
  444 + .week {
  445 + padding: 8rpx 0 0 0;
  446 + font-size: 20rpx;
  447 + line-height: 32rpx;
  448 + color: #909097;
  449 +
  450 + // padding: 0 0 0 20rpx;
  451 + text {
  452 + padding: 8rpx 0 0 20rpx;
  453 + }
  454 + }
  455 + }
  456 + }
  457 +
  458 + .u-content {
  459 + font-size: 24rpx;
  460 + line-height: 32rpx;
  461 + color: #909097;
  462 + margin: 32rpx 0 30rpx 0;
  463 + }
  464 +
  465 + .name_time {
  466 + border-top: 2rpx solid #E2E2E8;
  467 + padding: 28rpx 0 0 0;
  468 + display: flex;
  469 + flex-flow: row nowrap;
  470 + justify-content: space-between;
  471 +
  472 +
  473 + .name {
  474 + text {
  475 + font-size: 28rpx;
  476 + line-height: 32rpx;
  477 + color: #909097;
  478 + }
  479 +
  480 + text:last-child {
  481 + color: #202131;
  482 + margin: 0 0 0 30rpx;
  483 + }
  484 + }
  485 +
  486 + .time {
  487 + font-size: 28rpx;
  488 + line-height: 32rpx;
  489 + color: #909097;
  490 + }
  491 + }
  492 + }
  493 + }
  494 +
  495 + .popup_search {
  496 + width: 640rpx;
  497 + position: relative;
  498 +
  499 + .content {
  500 + padding: 0 40rpx;
  501 +
  502 + .title {
  503 + padding: 24rpx 0;
  504 + font-size: 28rpx;
  505 + line-height: 36rpx;
  506 + color: #202131;
  507 + }
  508 +
  509 + .scroll {
  510 + max-height: 60vh;
  511 +
  512 + .item {
  513 + width: 540rpx;
  514 + height: 96rpx;
  515 + border-radius: 4rpx;
  516 + border: 2rpx solid #C1C1C9;
  517 + margin: 0 10rpx 20rpx;
  518 + font-size: 24rpx;
  519 + line-height: 32rpx;
  520 + color: #C0C0C9;
  521 + display: flex;
  522 + flex-flow: row wrap;
  523 + align-items: center;
  524 +
  525 + text {
  526 + display: inline-block;
  527 + width: 500rpx;
  528 + height: 64rpx;
  529 + padding: 16rpx 20rpx;
  530 + }
  531 +
  532 +
  533 + }
  534 + }
  535 +
  536 + .time {
  537 + padding: 40rpx 0 0 0;
  538 + }
  539 +
  540 + .switch {
  541 + display: flex;
  542 + flex-flow: row nowrap;
  543 + justify-content: space-between;
  544 + padding: 40rpx 0 0 0;
  545 +
  546 + text {
  547 + font-size: 28rpx;
  548 + line-height: 36rpx;
  549 + color: #202131;
  550 + }
  551 + }
  552 +
  553 +
  554 + }
  555 +
  556 + .footer {
  557 + width: 560rpx;
  558 + height: 96rpx;
  559 + padding: 28rpx 40rpx;
  560 + background: #FFFFFF;
  561 + position: fixed;
  562 + bottom: 0;
  563 + right: 0;
  564 + z-index: 99;
  565 + border-top: 2rpx solid #E2E2E8;
  566 +
  567 + view {
  568 + display: inline-block;
  569 + }
  570 +
  571 + .left_btn {
  572 + width: 194rpx;
  573 + margin: 0 20rpx 0 0;
  574 + }
  575 +
  576 + .right_btn {
  577 + width: 346rpx;
  578 + }
  579 + }
  580 + }
  581 + }
  582 +</style>
... ...
  1 +<template>
  2 + <view class="registration_detail">
  3 +
  4 + <view class="box student_info">
  5 + <view class="title">学生信息</view>
  6 + <view class="item">
  7 + <text>学生姓名</text>
  8 + <text>{{registrationDetail.studentName}}</text>
  9 + </view>
  10 + <view class="item">
  11 + <text>手机号</text>
  12 + <text>{{registrationDetail.studentPhone}}</text>
  13 + </view>
  14 + <view class="item">
  15 + <text>学号</text>
  16 + <text>{{registrationDetail.studentNumber}}</text>
  17 + </view>
  18 + <view class="item">
  19 + <text>班级</text>
  20 + <text>{{registrationDetail.classInfo}}</text>
  21 + </view>
  22 +
  23 + <view class="icon_item">
  24 + <u-icon size="32rpx" label="实习项目" labelSize="28rpx" labelColor="#909097"
  25 + name="/static/img/home/实习项目icon@2x.png"></u-icon>
  26 + <text>{{registrationDetail.projectName}}</text>
  27 + </view>
  28 +
  29 + <view class="border_top item">
  30 + <text>申请时间</text>
  31 + <text>{{timeFormat(registrationDetail.applyTime, 'yyyy-mm-dd hh:MM')}}</text>
  32 + </view>
  33 + </view>
  34 +
  35 + <view class="box company_info">
  36 + <view class="title">单位信息</view>
  37 + <view class="icon_item">
  38 + <u-icon size="32rpx" label="实习单位" labelSize="28rpx" labelColor="#909097"
  39 + name="/static/img/home/实习项目icon@2x.png"></u-icon>
  40 + <text>{{registrationDetail.companyName}}</text>
  41 + </view>
  42 + <view class="icon_item">
  43 + <u-icon size="32rpx" label="实习岗位" labelSize="28rpx" labelColor="#909097"
  44 + name="/static/img/home/实习项目icon@2x.png"></u-icon>
  45 + <text>{{registrationDetail.jobName}}</text>
  46 + </view>
  47 + <view class="border_top item">
  48 + <text>联系人</text>
  49 + <text>{{jobDetail.contactName}}</text>
  50 + </view>
  51 + <view class="item">
  52 + <text>联系电话</text>
  53 + <text>{{jobDetail.contactPhone}}</text>
  54 + </view>
  55 + <view class="item">
  56 + <text>所在地区</text>
  57 + <text>{{address}}</text>
  58 + </view>
  59 + <view class="item">
  60 + <text>详细地址</text>
  61 + <text>{{jobDetail.workSite}}</text>
  62 + </view>
  63 + </view>
  64 +
  65 + <view class="box status">
  66 + <view class="title">状态</view>
  67 + <view class="item">
  68 + <text>审核状态</text>
  69 + <text>{{reviewStatus}}</text>
  70 + </view>
  71 + <view class="item">
  72 + <text>审核人</text>
  73 + <text>{{registrationDetail.auditTeacherName}}</text>
  74 + </view>
  75 + </view>
  76 +
  77 + <view class="footer">
  78 + <view class="left_btn">
  79 + <c-button type="cancel" text="审核拒绝" @click="handelCancel">
  80 + </c-button>
  81 + </view>
  82 + <view class="right_btn">
  83 + <c-button type="confirm" text="审核通过" @click="hancelSubmit">
  84 + </c-button>
  85 + </view>
  86 + </view>
  87 + </view>
  88 +</template>
  89 +
  90 +<script>
  91 + import {
  92 + getRegistrationDetailApi,
  93 + putRegistrationReviewApi,
  94 + } from '@/config/api.js';
  95 +
  96 + export default {
  97 + data() {
  98 + return {
  99 + registrationDetail: {},
  100 + }
  101 + },
  102 +
  103 + onLoad(option) {
  104 + getRegistrationDetailApi(option.id).then(data => {
  105 + if (data) {
  106 + console.log(data)
  107 + this.registrationDetail = data
  108 + }
  109 + })
  110 +
  111 + },
  112 +
  113 + onShow(options) {
  114 +
  115 + },
  116 +
  117 + computed: {
  118 + jobDetail: function() {
  119 + let {
  120 + jobDetail = {}
  121 + } = this.registrationDetail
  122 + return jobDetail;
  123 + },
  124 +
  125 + address: function() {
  126 + return this.jobDetail && this.jobDetail.province ?
  127 + `${this.jobDetail.province}/${this.jobDetail.city}/${this.jobDetail.district}` : '';
  128 +
  129 + },
  130 +
  131 + reviewStatus: function() {
  132 + return this.registrationDetail == 'apply' ? '待报名' :
  133 + this.registrationDetail == 'wait' ? '待审核' :
  134 + this.registrationDetail == 'pass' ? '已审核' :
  135 + this.registrationDetail == 'reject' ? '已拒绝' : '';
  136 + }
  137 + },
  138 +
  139 + methods: {
  140 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  141 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  142 + },
  143 +
  144 + handelCancel() {
  145 + putRegistrationReviewApi({
  146 + formIds: [this.registrationDetail.id],
  147 + schoolAuditStatus: 'reject',
  148 + }).then(data => {
  149 + if (data) {
  150 + this.$u.route({
  151 + url: `pages/main/home/registrationReview/registrationReview`
  152 + })
  153 + }
  154 + })
  155 + },
  156 +
  157 + hancelSubmit() {
  158 + putRegistrationReviewApi({
  159 + formIds: [this.registrationDetail.id],
  160 + schoolAuditStatus: 'pass',
  161 + }).then(data => {
  162 + if (data) {
  163 + this.$u.route({
  164 + url: `pages/main/home/registrationReview/registrationReview`
  165 + })
  166 + }
  167 + })
  168 + },
  169 + }
  170 + }
  171 +</script>
  172 +
  173 +<style lang="scss" scoped>
  174 + .registration_detail {
  175 + width: 100%;
  176 + min-height: 100%;
  177 + height: auto;
  178 + padding: 20rpx 0 194rpx 0;
  179 + background-color: #F7F7F7;
  180 +
  181 + .box {
  182 + width: 630rpx;
  183 + margin: 0 auto 20rpx;
  184 + padding: 30rpx 30rpx 12rpx 30rpx;
  185 + border-radius: 12rpx;
  186 + background-color: #FFFFFF;
  187 +
  188 + .title {
  189 + font-size: 32rpx;
  190 + line-height: 32rpx;
  191 + color: #202131;
  192 + margin: 0 0 30rpx 0;
  193 + }
  194 +
  195 + .title::before {
  196 + content: "";
  197 + display: inline-block;
  198 + width: 6rpx;
  199 + height: 32rpx;
  200 + background-color: #06B079;
  201 + margin: 0 12rpx 0 0;
  202 + position: relative;
  203 + top: 4rpx;
  204 + border-radius: 8rpx;
  205 + }
  206 +
  207 + .icon_item {
  208 + display: flex;
  209 + flex-flow: row nowrap;
  210 + margin: 0 0 24rpx 0;
  211 +
  212 + text {
  213 + display: inline-block;
  214 + width: 460rpx;
  215 + font-size: 28rpx;
  216 + line-height: 48rpx;
  217 + color: #202131;
  218 + margin: 0 0 0 40rpx;
  219 + }
  220 + }
  221 +
  222 + .item {
  223 + margin: 0 0 24rpx 0;
  224 +
  225 + text:first-child {
  226 + display: inline-block;
  227 + width: 112rpx;
  228 + text-align: justify;
  229 + text-align-last: justify;
  230 + font-size: 28rpx;
  231 + line-height: 48rpx;
  232 + color: #909097;
  233 + vertical-align: top;
  234 + }
  235 +
  236 + text:last-child {
  237 + display: inline-block;
  238 + width: 440rpx;
  239 + font-size: 28rpx;
  240 + line-height: 48rpx;
  241 + color: #202131;
  242 + margin: 0 0 0 78rpx;
  243 + }
  244 + }
  245 +
  246 + .border_top {
  247 + border-top: 2rpx solid #E2E2E8;
  248 + padding: 28rpx 0 0 0;
  249 + }
  250 + }
  251 +
  252 + .footer {
  253 + width: 100%;
  254 + height: 96rpx;
  255 + padding: 28rpx 30rpx;
  256 + background: #FFFFFF;
  257 + position: fixed;
  258 + bottom: 0;
  259 + left: 0;
  260 + z-index: 99;
  261 + border-top: 2rpx solid #E2E2E8;
  262 +
  263 + view {
  264 + display: inline-block;
  265 + }
  266 +
  267 + .left_btn {
  268 + width: 330rpx;
  269 + margin: 0 30rpx 0 0;
  270 + }
  271 +
  272 + .right_btn {
  273 + width: 330rpx;
  274 + }
  275 + }
  276 +
  277 + }
  278 +</style>
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 + <view class="search_box">
  4 + <view class="check">
  5 + <u-checkbox-group v-model="checkboxValue" placement="column" @change="checkboxChange">
  6 + <u-checkbox :customStyle="{marginBottom: '8px'}" shape="circle"
  7 + v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"
  8 + activeColor="#06B079" size="28rpx" labelSize="28rpx" labelColor="#202131">
  9 + </u-checkbox>
  10 + </u-checkbox-group>
  11 + </view>
  12 +
  13 + <view class="search">
  14 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  15 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch"></u-search>
  16 + </view>
  17 +
  18 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  19 + </view>
  20 +
  21 + <view class="list_box" v-if="list.length > 0">
  22 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  23 +
  24 + <view class="bg_image" v-if="item.status == 'wait'">
  25 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  26 + <text>待审核</text>
  27 + </view>
  28 +
  29 + <view class="bg_image" v-else>
  30 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  31 + <text>已通过</text>
  32 + </view>
  33 +
  34 + <view class="name">{{item.name}}</view>
  35 + <view class="company">
  36 + <u-icon size="32rpx" name="/static/img/home/实习单位icon@2x.png"></u-icon>
  37 + <text>实习单位</text>
  38 + <text>{{item.companyName || '--'}}</text>
  39 + </view>
  40 + <view class="company position">
  41 + <u-icon size="32rpx" name="/static/img/home/实习岗位icon@2x.png"></u-icon>
  42 + <text>实习岗位</text>
  43 + <text>{{item.jobName|| '--'}}</text>
  44 + </view>
  45 +
  46 + <view class="time">
  47 + <text>申请时间</text>
  48 + <text>{{timeFormat(item.applyTime, 'yyyy-mm-dd hh:MM')}}</text>
  49 + </view>
  50 +
  51 + </view>
  52 + <c-loading :loading="loading"></c-loading>
  53 + </view>
  54 + <view v-else class="no_data">
  55 + <c-no-data></c-no-data>
  56 + </view>
  57 +
  58 + <u-popup :show="show" mode="right" @close="close" @open="open">
  59 + <view class="popup_search">
  60 + <view class="content">
  61 + <view class="title">按项目筛选</view>
  62 + <scroll-view class="scroll" scroll-y="true">
  63 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  64 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  65 + <text>{{item.name}}</text>
  66 + </view>
  67 + <view v-else>
  68 + <text>{{item.name}}</text>
  69 + </view>
  70 + </view>
  71 + </scroll-view>
  72 + <view class="switch">
  73 + <text>未审核</text>
  74 + <u-switch v-model="switchValue" size="48" activeColor="#06B079" @change="handelChange">
  75 + </u-switch>
  76 + </view>
  77 + </view>
  78 +
  79 + <view class="footer">
  80 + <view class="left_btn">
  81 + <c-button type="cancel" text="重置" @click="handelCancel">
  82 + </c-button>
  83 + </view>
  84 + <view class="right_btn">
  85 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  86 + </c-button>
  87 + </view>
  88 + </view>
  89 +
  90 + </view>
  91 + </u-popup>
  92 +
  93 + </view>
  94 +</template>
  95 +
  96 +<script>
  97 + import {
  98 + mapGetters,
  99 + mapState,
  100 + mapActions
  101 + } from 'vuex'
  102 + import listMixin from "@/common/mixins/list-mixin.js";
  103 +
  104 + import {
  105 + getRegistrationReviewApi,
  106 + getProjectListApi,
  107 + } from '@/config/api.js';
  108 +
  109 + export default {
  110 + mixins: [listMixin],
  111 + data() {
  112 + return {
  113 + checkboxValue: [],
  114 + // 基本案列数据
  115 + checkboxList: [{
  116 + name: '待审核',
  117 + disabled: false
  118 + }],
  119 + keyword: '',
  120 + show: false,
  121 + list: [], //列表必须为key list的数组
  122 + search: {
  123 + //搜索对象必须为key search的对象
  124 + keySearch: "",
  125 + status: 'wait,pass,reject',
  126 +
  127 + },
  128 + projectId: '',
  129 + switchValue: false,
  130 + }
  131 + },
  132 +
  133 + onLoad() {},
  134 +
  135 + onShow() {
  136 +
  137 + this.$store.dispatch(`home/getProjectList`, {
  138 + pageSize: -1,
  139 + })
  140 +
  141 + this.search.keySearch = '';
  142 +
  143 + this.finished = false;
  144 + this.loading = "loadmore";
  145 + this.page = 0;
  146 + this.list = [];
  147 + this._getList();
  148 + },
  149 +
  150 + computed: {
  151 + ...mapState('home', {
  152 + // 箭头函数可使代码更简练
  153 + projectList: 'projectList',
  154 +
  155 + }),
  156 +
  157 + },
  158 +
  159 + methods: {
  160 +
  161 + handelDetail(record) {
  162 + this.$u.route({
  163 + url: `pages/main/home/registrationDetail/registrationDetail?&id=${record.id}`
  164 + })
  165 + },
  166 +
  167 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  168 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  169 + },
  170 +
  171 + checkboxChange(n) {
  172 + console.log('change', n);
  173 +
  174 + this.search.status = n.length > 0 ? 'wait' : 'wait,pass,reject';
  175 +
  176 + this.switchValue = n.length > 0 ? true : false;
  177 +
  178 + this.finished = false;
  179 + this.loading = "loadmore";
  180 + this.page = 0;
  181 + this.list = [];
  182 + this._getList();
  183 + },
  184 +
  185 + handelSearch(value) {
  186 + this.finished = false;
  187 + this.loading = "loadmore";
  188 + this.page = 0;
  189 + this.list = [];
  190 + this._getList();
  191 + },
  192 +
  193 + open() {
  194 + // console.log('open');
  195 + },
  196 + close() {
  197 + this.show = false
  198 + // console.log('close');
  199 + },
  200 + // scroll-view到底部加载更多
  201 + onreachBottom() {},
  202 + // 搜索
  203 + searchSubmit() {
  204 + // 调用混合搜索
  205 + this._searchData();
  206 + },
  207 + // 模拟后端分页
  208 + async getData(requestParams) {
  209 + const {
  210 + search = {}
  211 + } = requestParams;
  212 +
  213 + let params = {};
  214 + params.pageNumber = requestParams.page + 1;
  215 + params.pageSize = 5;
  216 +
  217 + if (search.status) {
  218 + params.status = search.status;
  219 + }
  220 +
  221 + if (this.keyword) {
  222 + params.keySearch = this.keyword
  223 + }
  224 +
  225 + if (this.projectId) {
  226 + params.projectId = this.projectId
  227 + }
  228 +
  229 + return await getRegistrationReviewApi(params);
  230 + },
  231 + // 数据请求(没错就是这么少的代码)
  232 + async _getList() {
  233 + if (this.page == 0) {
  234 + this.list = [];
  235 + }
  236 +
  237 + // 根据实际情况修改自己修改key
  238 + let result = await this.getData({
  239 + page: this.page, // 传入页码
  240 + size: this.size, // 传入每页条数
  241 + search: this.search, // 传入搜索的对象
  242 + });
  243 +
  244 + this.total = result.total;
  245 +
  246 + if (this.list.length == 0 && result.records.length == 0) {
  247 + this.shownoData = false
  248 + } else {
  249 + this.shownoData = true
  250 + }
  251 +
  252 + this.list = this.list.concat(result.records)
  253 + },
  254 +
  255 + handelClick(values) {
  256 + console.log(values);
  257 + this.projectId = values.id;
  258 + },
  259 +
  260 + handelChange(e) {
  261 + console.log(e)
  262 + this.checkboxValue = e ? ['待审核'] : [];
  263 + this.search.status = e ? 'wait' : 'wait,pass,reject';
  264 +
  265 + },
  266 +
  267 + handelCancel() {
  268 + this.switchValue = false;
  269 + this.projectId = '';
  270 + },
  271 +
  272 + hancelSubmit() {
  273 + this.finished = false;
  274 + this.loading = "loadmore";
  275 + this.page = 0;
  276 + this.list = [];
  277 + this._getList();
  278 +
  279 + this.show = false;
  280 + },
  281 +
  282 + }
  283 + }
  284 +</script>
  285 +
  286 +<style lang="scss" scoped>
  287 + .registration_review {
  288 + width: 100%;
  289 + min-height: 100%;
  290 + height: auto;
  291 + background-color: #F7F7F7;
  292 +
  293 + .search_box {
  294 + padding: 36rpx 30rpx 12rpx;
  295 + background-color: #FFFFFF;
  296 + display: flex;
  297 + flex-flow: row nowrap;
  298 + justify-content: space-between;
  299 +
  300 + .check {
  301 + padding: 20rpx 0 0 0;
  302 + }
  303 +
  304 + .search {
  305 + width: 468rpx;
  306 + }
  307 + }
  308 +
  309 + .list_box {
  310 + padding: 0 0 50rpx 0;
  311 +
  312 + .item {
  313 + position: relative;
  314 + width: 630rpx;
  315 + margin: 30rpx auto;
  316 + padding: 30rpx;
  317 + border-radius: 12rpx;
  318 + background-color: #FFFFFF;
  319 +
  320 + .bg_image {
  321 + position: absolute;
  322 + top: 0;
  323 + right: 0;
  324 +
  325 + text {
  326 + position: absolute;
  327 + top: 12rpx;
  328 + right: 30rpx;
  329 + font-size: 24rpx;
  330 + line-height: 24rpx;
  331 + color: #FFFFFF;
  332 + }
  333 + }
  334 +
  335 + .name {
  336 + font-size: 32rpx;
  337 + line-height: 44rpx;
  338 + color: #202131;
  339 + font-weight: 500;
  340 + margin: 0 0 30rpx 0;
  341 + }
  342 +
  343 + .company {
  344 + display: flex;
  345 + flex-flow: row nowrap;
  346 + margin: 0 0 30rpx 0;
  347 +
  348 + text {
  349 + font-size: 28rpx;
  350 + line-height: 32rpx;
  351 + color: #909097;
  352 + margin: 0 0 0 16rpx;
  353 + }
  354 +
  355 + text:last-child {
  356 + color: #202131;
  357 + margin: 0 0 0 30rpx;
  358 + }
  359 + }
  360 +
  361 + .time {
  362 + border-top: 2rpx solid #E2E2E8;
  363 + padding: 28rpx 0 0 0;
  364 +
  365 + text {
  366 + font-size: 28rpx;
  367 + line-height: 32rpx;
  368 + color: #909097;
  369 + }
  370 +
  371 + text:last-child {
  372 + color: #202131;
  373 + margin: 0 0 0 78rpx;
  374 + }
  375 + }
  376 + }
  377 + }
  378 +
  379 + .popup_search {
  380 + width: 640rpx;
  381 + position: relative;
  382 +
  383 + .content {
  384 + padding: 0 40rpx;
  385 +
  386 + .title {
  387 + padding: 24rpx 0;
  388 + font-size: 28rpx;
  389 + line-height: 36rpx;
  390 + color: #202131;
  391 + }
  392 +
  393 + .scroll {
  394 + max-height: 60vh;
  395 +
  396 + .item {
  397 + width: 540rpx;
  398 + height: 96rpx;
  399 + border-radius: 4rpx;
  400 + border: 2rpx solid #C1C1C9;
  401 + margin: 0 10rpx 20rpx;
  402 + font-size: 24rpx;
  403 + line-height: 32rpx;
  404 + color: #C0C0C9;
  405 + display: flex;
  406 + flex-flow: row wrap;
  407 + align-items: center;
  408 +
  409 + text {
  410 + display: inline-block;
  411 + width: 500rpx;
  412 + height: 64rpx;
  413 + padding: 16rpx 20rpx;
  414 + }
  415 +
  416 +
  417 + }
  418 + }
  419 +
  420 + .switch {
  421 + display: flex;
  422 + flex-flow: row nowrap;
  423 + justify-content: space-between;
  424 + padding: 40rpx 0 0 0;
  425 +
  426 + text {
  427 + font-size: 28rpx;
  428 + line-height: 36rpx;
  429 + color: #202131;
  430 + }
  431 + }
  432 +
  433 +
  434 + }
  435 +
  436 + .footer {
  437 + width: 560rpx;
  438 + height: 96rpx;
  439 + padding: 28rpx 40rpx;
  440 + background: #FFFFFF;
  441 + position: fixed;
  442 + bottom: 0;
  443 + right: 0;
  444 + z-index: 99;
  445 + border-top: 2rpx solid #E2E2E8;
  446 +
  447 + view {
  448 + display: inline-block;
  449 + }
  450 +
  451 + .left_btn {
  452 + width: 194rpx;
  453 + margin: 0 20rpx 0 0;
  454 + }
  455 +
  456 + .right_btn {
  457 + width: 346rpx;
  458 + }
  459 + }
  460 + }
  461 + }
  462 +</style>
... ...
  1 +<template>
  2 + <view class="report_detail">
  3 + <view class="report_info">
  4 +
  5 + <view class="bg_image" v-if="detail.status == 'stay_examine'">
  6 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  7 + <text>待审核</text>
  8 + </view>
  9 +
  10 + <view class="bg_image" v-else-if="detail.status == 'adopt'">
  11 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  12 + <text>已通过</text>
  13 + </view>
  14 +
  15 + <view class="bg_image" v-else>
  16 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  17 + <text>已退回</text>
  18 + </view>
  19 +
  20 + <view class="info">
  21 + <view class="avatar">{{getNameLastTwo(detail.studentName)}}</view>
  22 + <view class="title_name">
  23 + <view class="title">{{detail.title}}</view>
  24 + <view class="name">
  25 + <text>学生姓名</text>
  26 + <text>{{detail.studentName}}</text>
  27 + </view>
  28 + </view>
  29 + </view>
  30 +
  31 + <view class="time_record">
  32 + <text>
  33 + {{timeFormat(detail.createdTime, 'yyyy-mm-dd hh:MM')}}
  34 + </text>
  35 + <view class="record" @click="handelRecord">
  36 + <text>审批记录</text>
  37 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#06B079" size="28"></u-icon>
  38 + </view>
  39 + </view>
  40 + </view>
  41 +
  42 + <view class="box">
  43 + <view class="title">附件</view>
  44 + <view class="item" v-for="(item,index) in reportAttachments">
  45 + <text>报告附件</text>
  46 + <text :style="{color:'#06B079'}" @click="openLink(item)">{{item.filename}}</text>
  47 + </view>
  48 + </view>
  49 +
  50 + <view class="box file">
  51 + <view class="title">反馈附件</view>
  52 + <view class="icon_item" v-for="(item,index) in attachments" @click="deletePic(index)">
  53 + <text>{{item.filename}}</text>
  54 + <u-icon name="close" width="28rpx" color="red" size="28"></u-icon>
  55 + </view>
  56 + <view class="icon_box" @click="handelFile">
  57 + <u-icon name="plus" width="28rpx" label="添加" labelPos="bottom" labelColor="#06B079" color="#06B079"
  58 + size="28"></u-icon>
  59 + </view>
  60 +
  61 + </view>
  62 +
  63 + <view class="box" :style="{padding:'30rpx'}">
  64 + <view class="title">反馈信息</view>
  65 + <u-textarea v-model="textarea" placeholder="请输入内容" count></u-textarea>
  66 + </view>
  67 +
  68 + <view class="footer" v-if="detail.status == 'stay_examine'">
  69 + <view class="left_btn">
  70 + <c-button type="cancel" text="退回" @click="handelCancel">
  71 + </c-button>
  72 + </view>
  73 + <view class="right_btn">
  74 + <c-button type="confirm" text="通过" @click="hancelSubmit">
  75 + </c-button>
  76 + </view>
  77 + </view>
  78 +
  79 + </view>
  80 +</template>
  81 +
  82 +<script>
  83 + import {
  84 + mapGetters,
  85 + mapState,
  86 + mapActions
  87 + } from 'vuex'
  88 + import listMixin from "@/common/mixins/list-mixin.js";
  89 +
  90 + import {
  91 + getOssInitApi,
  92 + getImgUrlApi,
  93 + getReportDetailApi,
  94 + putReportReviewApi,
  95 + } from '@/config/api.js';
  96 +
  97 + export default {
  98 + data() {
  99 + return {
  100 + id: '',
  101 + formId: '',
  102 + detail: {},
  103 + reportAttachments: [],
  104 + ossInit: {},
  105 + mFileDir: "yxly",
  106 + mFileType: ".doc",
  107 + fileList: [],
  108 + attachments: [],
  109 + show: false,
  110 + selector: ["上传微信文件", "上传电脑文件"],
  111 + maxCount: 9,
  112 + textarea: '',
  113 + }
  114 + },
  115 +
  116 + onLoad(option) {
  117 + this.id = option.id;
  118 + this.formId = option.formId;
  119 +
  120 + getOssInitApi({
  121 + "uploadFileType": "report"
  122 + }).then(res => {
  123 + this.ossInit = res
  124 + })
  125 +
  126 + getReportDetailApi(option.id).then(data => {
  127 + if (data) {
  128 + this.detail = data;
  129 + if (data.reportAttachments) {
  130 + this.reportAttachments = JSON.parse(data.reportAttachments)
  131 + }
  132 + }
  133 + })
  134 + },
  135 +
  136 + methods: {
  137 + getNameLastTwo(value) {
  138 + if (value && value.length > 3) {
  139 + return value.substring(value.length - 3)
  140 + } else {
  141 + return value;
  142 + }
  143 + },
  144 +
  145 + overflowHide(value) {
  146 + if (value && value.length > 4) {
  147 + return `${value.slice(0, 4)}...`
  148 + } else {
  149 + return value;
  150 + }
  151 + },
  152 +
  153 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  154 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  155 + },
  156 +
  157 + handelRecord() {
  158 + this.$u.route({
  159 + url: `pages/main/home/approvalRecord/approvalRecord?formId=${this.detail.formId}`
  160 + })
  161 + },
  162 +
  163 + openLink(e) {
  164 + var _this = this
  165 + this.mFileDir = e.filename.substring(0, e.filename.lastIndexOf('.'))
  166 + this.mFileType = e.filename.substring(e.filename.lastIndexOf('.'), e.filename.length)
  167 + getImgUrlApi({
  168 + bucket: e.bucket,
  169 + filePath: e.object
  170 + }).then(data => {
  171 + console.log("data...", data)
  172 + if (e.mime_type.indexOf("image") != -1) {
  173 + _this.openImage(data.url)
  174 + } else {
  175 + uni.downloadFile({
  176 + url: data.url,
  177 + filePath: wx.env.USER_DATA_PATH + '/' + _this.mFileDir + this.mFileType,
  178 + success: (res) => {
  179 + if (res.statusCode === 200) {
  180 + uni.showLoading();
  181 + console.log('download succ', res)
  182 + let fileMgr = wx.getFileSystemManager();
  183 + let filePath = res.filePath
  184 + uni.saveFile({
  185 + tempFilePath: filePath,
  186 + success: function(res) {
  187 + var savedFilePath = res.savedFilePath;
  188 + /* 删除缓存 */
  189 + fileMgr.unlink({
  190 + filePath: wx.env.USER_DATA_PATH +
  191 + '/' +
  192 + _this.mFileDir + _this
  193 + .mFileType,
  194 + success: function(res) {
  195 + console.log(
  196 + 'unlink success:',
  197 + res);
  198 + }
  199 + })
  200 + _this.openDoc()
  201 + },
  202 + fail: function(res) {
  203 + console.log('save fail', res);
  204 + _this.createFile()
  205 + }
  206 + })
  207 + }
  208 + }
  209 + });
  210 + }
  211 + })
  212 + },
  213 +
  214 + createFile() {
  215 + let fileMgr = wx.getFileSystemManager();
  216 + var _this = this
  217 + //利用access方法判断文件是否可用
  218 + fileMgr.access({
  219 + path: wx.env.USER_DATA_PATH + '/' + _this.mFileDir,
  220 + success: (res) => {
  221 + console.log('check success:', res);
  222 + _this.openDoc()
  223 + },
  224 + fail: (res) => {
  225 + console.log('check fail.', res);
  226 + fileMgr.mkdir({
  227 + dirPath: wx.env.USER_DATA_PATH + '/' + _this.mFileDir,
  228 + success: (res) => {
  229 + console.log('mk dir success:', res);
  230 + _this.openDoc()
  231 + },
  232 + fail: (res) => {
  233 + console.log('mk dir fail:', res);
  234 + uni.hideLoading();
  235 + }
  236 + });
  237 + }
  238 + });
  239 + },
  240 +
  241 + openDoc() {
  242 + uni.openDocument({
  243 + filePath: wx.env.USER_DATA_PATH + '/' + this.mFileDir + this.mFileType,
  244 + showMenu: true,
  245 + success: function(res) {
  246 + uni.hideLoading();
  247 + console.log('openDoc succ');
  248 + }
  249 + });
  250 + },
  251 +
  252 + openImage(imgPath) {
  253 + let array = new Array(1).fill(imgPath);
  254 + uni.previewImage({
  255 + urls: array,
  256 + success(res) {
  257 + console.log('openImage success');
  258 + },
  259 + fail(res) {
  260 + console.log('openImage fail:', res);
  261 + }
  262 + });
  263 + },
  264 +
  265 + deletePic(index) {
  266 + this.attachments.splice(index, 1)
  267 + },
  268 +
  269 + handelFile() {
  270 + let _this = this;
  271 +
  272 + wx.chooseMessageFile({
  273 + count: 9,
  274 + extension: ['.doc', '.pdf', '.docx', '.png', 'jpg', 'xlsx', 'xls', '.pptx'],
  275 + success(res) {
  276 + console.log(res.tempFiles);
  277 +
  278 + let files = res.tempFiles;
  279 +
  280 + for (var i = 0; i < files.length; i++) {
  281 + uni.uploadFile({
  282 + url: _this.vuex_ossUrl,
  283 + filePath: files[i].path,
  284 + name: "file",
  285 + formData: {
  286 + 'key': `${_this.ossInit.dir}${new Date().getTime()}/` + files[i].name,
  287 + 'action': `${_this.ossInit.host}`,
  288 + 'OSSAccessKeyId': _this.ossInit.accessId,
  289 + 'policy': _this.ossInit.policy,
  290 + 'signature': _this.ossInit.signature,
  291 + 'callback': _this.ossInit.callback,
  292 + },
  293 + success: (uploadFileRes) => {
  294 + console.log('uploadFileRes...', uploadFileRes)
  295 + _this.attachments.push(JSON.parse(uploadFileRes.data))
  296 +
  297 + },
  298 + complete: (res) => {
  299 + console.log('res...', res)
  300 + }
  301 + });
  302 + }
  303 +
  304 +
  305 + }
  306 + });
  307 + },
  308 +
  309 + handelCancel() {
  310 + putReportReviewApi(this.id, {
  311 + status: 'return',
  312 + reviewAttachments: JSON.stringify(this.attachments),
  313 + review: this.textarea,
  314 + }).then(data => {
  315 + if (data) {
  316 + this.$u.route({
  317 + url: `pages/main/home/reportReview/reportReview`
  318 + })
  319 + }
  320 + })
  321 + },
  322 +
  323 + hancelSubmit() {
  324 + putReportReviewApi(this.id, {
  325 + status: 'adopt',
  326 + reviewAttachments: JSON.stringify(this.attachments),
  327 + review: this.textarea,
  328 + }).then(data => {
  329 + if (data) {
  330 + this.$u.route({
  331 + url: `pages/main/home/reportReview/reportReview`
  332 + })
  333 + }
  334 + })
  335 + },
  336 + }
  337 + }
  338 +</script>
  339 +
  340 +<style lang="scss" scoped>
  341 + .report_detail {
  342 + width: 100%;
  343 + min-height: 100%;
  344 + height: auto;
  345 + background-color: #F7F7F7;
  346 + padding: 20rpx 0 150rpx 0;
  347 +
  348 + .report_info {
  349 + position: relative;
  350 + width: 630rpx;
  351 + margin: 0 auto;
  352 + padding: 30rpx;
  353 + border-radius: 12rpx;
  354 + background-color: #FFFFFF;
  355 +
  356 + .bg_image {
  357 + position: absolute;
  358 + top: 0;
  359 + right: 0;
  360 +
  361 + text {
  362 + position: absolute;
  363 + top: 12rpx;
  364 + right: 30rpx;
  365 + font-size: 24rpx;
  366 + line-height: 24rpx;
  367 + color: #FFFFFF;
  368 + }
  369 + }
  370 +
  371 + .info {
  372 + display: flex;
  373 + flex-flow: row nowrap;
  374 + align-items: center;
  375 + margin: 0 0 30rpx 0;
  376 +
  377 + .avatar {
  378 + width: 78rpx;
  379 + height: 94rpx;
  380 + padding: 0 8rpx;
  381 + border-radius: 4rpx;
  382 + background-color: #06B079;
  383 + font-size: 24rpx;
  384 + line-height: 94rpx;
  385 + color: #FFFFFF;
  386 + text-align: center;
  387 + }
  388 +
  389 + .title_name {
  390 + .title {
  391 + font-size: 32rpx;
  392 + line-height: 44rpx;
  393 + color: #202131;
  394 + font-weight: 500;
  395 + margin: 0 20rpx;
  396 + }
  397 +
  398 + .name {
  399 + padding: 8rpx 0 0 20rpx;
  400 + font-size: 28rpx;
  401 + line-height: 32rpx;
  402 + color: #909097;
  403 +
  404 + text:last-child {
  405 + padding: 0 0 0 30rpx;
  406 + color: #202131;
  407 + }
  408 + }
  409 + }
  410 +
  411 + }
  412 +
  413 + .time_record {
  414 + border-top: 2rpx solid #E2E2E8;
  415 + padding: 28rpx 0 0 0;
  416 + display: flex;
  417 + flex-flow: row nowrap;
  418 + justify-content: space-between;
  419 +
  420 + text {
  421 + font-size: 28rpx;
  422 + line-height: 32rpx;
  423 + color: #909097;
  424 + }
  425 +
  426 + .record {
  427 + display: flex;
  428 + flex-flow: row nowrap;
  429 +
  430 + text {
  431 + font-size: 24rpx;
  432 + line-height: 32rpx;
  433 + color: #06B079;
  434 + }
  435 + }
  436 + }
  437 + }
  438 +
  439 + .box {
  440 + width: 630rpx;
  441 + margin: 20rpx auto;
  442 + padding: 30rpx 30rpx 12rpx 30rpx;
  443 + border-radius: 12rpx;
  444 + background-color: #FFFFFF;
  445 +
  446 + .title {
  447 + font-size: 32rpx;
  448 + line-height: 32rpx;
  449 + color: #202131;
  450 + margin: 0 0 30rpx 0;
  451 + }
  452 +
  453 + .title::before {
  454 + content: "";
  455 + display: inline-block;
  456 + width: 6rpx;
  457 + height: 32rpx;
  458 + background-color: #06B079;
  459 + margin: 0 12rpx 0 0;
  460 + position: relative;
  461 + top: 4rpx;
  462 + border-radius: 8rpx;
  463 + }
  464 +
  465 +
  466 +
  467 + .item {
  468 + margin: 0 0 24rpx 0;
  469 +
  470 + text:first-child {
  471 + display: inline-block;
  472 + width: 112rpx;
  473 + text-align: justify;
  474 + text-align-last: justify;
  475 + font-size: 28rpx;
  476 + line-height: 48rpx;
  477 + color: #909097;
  478 + vertical-align: top;
  479 + }
  480 +
  481 + text:last-child {
  482 + display: inline-block;
  483 + width: 440rpx;
  484 + word-break: break-word;
  485 + font-size: 28rpx;
  486 + line-height: 48rpx;
  487 + color: #202131;
  488 + margin: 0 0 0 78rpx;
  489 + }
  490 + }
  491 +
  492 + .border_top {
  493 + border-top: 2rpx solid #E2E2E8;
  494 + padding: 28rpx 0 0 0;
  495 + }
  496 + }
  497 +
  498 + .file {
  499 +
  500 + .icon_item {
  501 + display: flex;
  502 + flex-flow: row wrap;
  503 + margin: 0 0 24rpx 0;
  504 +
  505 + text {
  506 + display: inline-block;
  507 + font-size: 28rpx;
  508 + line-height: 36rpx;
  509 + margin: 0 8rpx 12rpx 0;
  510 + color: #06B079;
  511 + }
  512 +
  513 + }
  514 +
  515 + .icon_box {
  516 + width: 70rpx;
  517 + border: 2rpx solid #06B079;
  518 + text-align: center;
  519 + margin: 0 auto 20rpx;
  520 + padding: 20rpx;
  521 +
  522 + text {
  523 + font-size: 34rpx;
  524 +
  525 + }
  526 + }
  527 + }
  528 +
  529 + .footer {
  530 + width: 100%;
  531 + height: 96rpx;
  532 + padding: 28rpx 30rpx;
  533 + background: #FFFFFF;
  534 + position: fixed;
  535 + bottom: 0;
  536 + left: 0;
  537 + z-index: 99;
  538 + border-top: 2rpx solid #E2E2E8;
  539 +
  540 + view {
  541 + display: inline-block;
  542 + }
  543 +
  544 + .left_btn {
  545 + width: 330rpx;
  546 + margin: 0 30rpx 0 0;
  547 + }
  548 +
  549 + .right_btn {
  550 + width: 330rpx;
  551 + }
  552 + }
  553 + }
  554 +</style>
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 + <view class="search_box" v-if="!studentId">
  4 + <view class="top">
  5 + <view class="check">
  6 + <u-checkbox-group v-model="checkboxValue" placement="column" @change="checkboxChange">
  7 + <u-checkbox :customStyle="{marginBottom: '8px'}" shape="circle"
  8 + v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"
  9 + activeColor="#06B079" size="28rpx" labelSize="28rpx" labelColor="#202131">
  10 + </u-checkbox>
  11 + </u-checkbox-group>
  12 + </view>
  13 +
  14 + <view class="search">
  15 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  16 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  17 + </u-search>
  18 + </view>
  19 +
  20 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  21 + </view>
  22 + </view>
  23 +
  24 + <view class="list_box" v-if="list.length > 0">
  25 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  26 +
  27 + <view class="bg_image" v-if="item.status == 'stay_examine'">
  28 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  29 + <text>待审核</text>
  30 + </view>
  31 +
  32 + <view class="bg_image" v-else-if="item.status == 'adopt'">
  33 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  34 + <text>已通过</text>
  35 + </view>
  36 +
  37 + <view class="bg_image" v-else>
  38 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  39 + <text>已退回</text>
  40 + </view>
  41 +
  42 + <view class="info">
  43 + <view class="avatar">{{getNameLastTwo(item.form.studentName)}}</view>
  44 + <view class="title_name">
  45 + <view class="title">{{item.title}}</view>
  46 + <view class="name">
  47 + <text>学生姓名</text>
  48 + <text>{{item.form.studentName}}</text>
  49 + </view>
  50 + </view>
  51 + </view>
  52 +
  53 + <view class="time">
  54 + <text>{{timeFormat(item.createdTime, 'yyyy-mm-dd hh:MM')}}</text>
  55 + </view>
  56 +
  57 + </view>
  58 + <c-loading :loading="loading"></c-loading>
  59 + </view>
  60 + <view v-else class="no_data">
  61 + <c-no-data></c-no-data>
  62 + </view>
  63 +
  64 + <u-popup :show="show" mode="right" @close="close" @open="open">
  65 + <view class="popup_search">
  66 + <view class="content">
  67 + <view class="title">按项目筛选</view>
  68 + <scroll-view class="scroll" scroll-y="true">
  69 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  70 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  71 + <text>{{item.name}}</text>
  72 + </view>
  73 + <view v-else>
  74 + <text>{{item.name}}</text>
  75 + </view>
  76 + </view>
  77 + </scroll-view>
  78 + <view class="switch">
  79 + <text>待批阅</text>
  80 + <u-switch v-model="switchValue" size="48" activeColor="#06B079" @change="handelChange">
  81 + </u-switch>
  82 + </view>
  83 + </view>
  84 +
  85 + <view class="footer">
  86 + <view class="left_btn">
  87 + <c-button type="cancel" text="重置" @click="handelCancel">
  88 + </c-button>
  89 + </view>
  90 + <view class="right_btn">
  91 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  92 + </c-button>
  93 + </view>
  94 + </view>
  95 +
  96 + </view>
  97 + </u-popup>
  98 +
  99 + </view>
  100 +</template>
  101 +
  102 +<script>
  103 + import {
  104 + mapGetters,
  105 + mapState,
  106 + mapActions
  107 + } from 'vuex'
  108 + import listMixin from "@/common/mixins/list-mixin.js";
  109 +
  110 + import {
  111 + getReportReviewListApi,
  112 + getProjectListApi,
  113 + } from '@/config/api.js';
  114 +
  115 + export default {
  116 + mixins: [listMixin],
  117 + data() {
  118 +
  119 + const d = new Date();
  120 + const year = d.getFullYear();
  121 + let month = d.getMonth() + 1;
  122 + month = month < 10 ? `0${month}` : month;
  123 + const date = d.getDate();
  124 +
  125 + return {
  126 + studentId: '',
  127 + checkboxValue: [],
  128 + // 基本案列数据
  129 + checkboxList: [{
  130 + name: '待批阅',
  131 + disabled: false
  132 + }],
  133 + keyword: '',
  134 + show: false,
  135 + search: {
  136 + //搜索对象必须为key search的对象
  137 + keySearch: "",
  138 + status: '',
  139 +
  140 + },
  141 + showTime: false,
  142 + timeValue: `${year}-${month}-${date}`,
  143 + defaultDateMultiple: [`${year}-${month}-${date}`],
  144 + list: [], //列表必须为key list的数组
  145 + projectId: '',
  146 + switchValue: false,
  147 +
  148 + }
  149 + },
  150 +
  151 + onLoad(option) {
  152 + console.log(option)
  153 + this.studentId = option.studentId;
  154 + this.projectId = option.projectId;
  155 +
  156 + this.$store.dispatch(`home/getProjectList`, {
  157 + pageSize: -1,
  158 + })
  159 +
  160 + this.search.keySearch = '';
  161 +
  162 + this.finished = false;
  163 + this.loading = "loadmore";
  164 + this.page = 0;
  165 + this.list = [];
  166 + this._getList();
  167 + },
  168 +
  169 + onShow() {
  170 +
  171 + },
  172 +
  173 + computed: {
  174 + ...mapState('home', {
  175 + // 箭头函数可使代码更简练
  176 + projectList: 'projectList',
  177 +
  178 + }),
  179 +
  180 + },
  181 +
  182 + methods: {
  183 + getNameLastTwo(value) {
  184 + if (value && value.length > 3) {
  185 + return value.substring(value.length - 3)
  186 + } else {
  187 + return value;
  188 + }
  189 + },
  190 +
  191 + overflowHide(value) {
  192 + if (value && value.length > 4) {
  193 + return `${value.slice(0, 4)}...`
  194 + } else {
  195 + return value;
  196 + }
  197 + },
  198 +
  199 + confirm(e) {
  200 + this.timeValue = e[0];
  201 + this.showTime = false;
  202 + },
  203 +
  204 + handelDetail(record) {
  205 + this.$u.route({
  206 + url: `pages/main/home/reportDetail/reportDetail?id=${record.id}&formId=${record.formId}`
  207 + })
  208 + },
  209 +
  210 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  211 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  212 + },
  213 +
  214 + checkboxChange(n) {
  215 + console.log('change', n);
  216 +
  217 + this.search.status = n.length > 0 ? 'stay_examine' : '';
  218 +
  219 + this.switchValue = n.length > 0 ? true : false;
  220 +
  221 + this.finished = false;
  222 + this.loading = "loadmore";
  223 + this.page = 0;
  224 + this.list = [];
  225 + this._getList();
  226 + },
  227 +
  228 + handelSearch(value) {
  229 + this.finished = false;
  230 + this.loading = "loadmore";
  231 + this.page = 0;
  232 + this.list = [];
  233 + this._getList();
  234 + },
  235 +
  236 + open() {
  237 + // console.log('open');
  238 + },
  239 + close() {
  240 + this.show = false
  241 + // console.log('close');
  242 + },
  243 + // scroll-view到底部加载更多
  244 + onreachBottom() {},
  245 + // 搜索
  246 + searchSubmit() {
  247 + // 调用混合搜索
  248 + this._searchData();
  249 + },
  250 + // 模拟后端分页
  251 + async getData(requestParams) {
  252 + const {
  253 + search = {}
  254 + } = requestParams;
  255 +
  256 + let params = {};
  257 + params.pageNumber = requestParams.page + 1;
  258 + params.pageSize = 5;
  259 +
  260 + if (search.status) {
  261 + params.status = search.status;
  262 + }
  263 +
  264 + if (this.keyword) {
  265 + params.keySearch = this.keyword
  266 + }
  267 +
  268 + if (this.studentId) {
  269 + params.studentId = this.studentId
  270 + }
  271 +
  272 + if (this.projectId) {
  273 + params.projectId = this.projectId
  274 + }
  275 +
  276 + return await getReportReviewListApi(params);
  277 + },
  278 + // 数据请求(没错就是这么少的代码)
  279 + async _getList() {
  280 + if (this.page == 0) {
  281 + this.list = [];
  282 + }
  283 +
  284 + // 根据实际情况修改自己修改key
  285 + let result = await this.getData({
  286 + page: this.page, // 传入页码
  287 + size: this.size, // 传入每页条数
  288 + search: this.search, // 传入搜索的对象
  289 + });
  290 +
  291 + this.total = result.total;
  292 +
  293 + if (this.list.length == 0 && result.records.length == 0) {
  294 + this.shownoData = false
  295 + } else {
  296 + this.shownoData = true
  297 + }
  298 +
  299 + this.list = this.list.concat(result.records)
  300 + },
  301 +
  302 + handelClick(values) {
  303 + console.log(values);
  304 + this.projectId = values.id;
  305 + },
  306 +
  307 + handelChange(e) {
  308 + console.log(e)
  309 + this.checkboxValue = e ? ['待批阅'] : [];
  310 + this.search.status = e ? 'stay_examine' : '';
  311 +
  312 + },
  313 +
  314 + handelCancel() {
  315 + this.switchValue = false;
  316 + this.projectId = '';
  317 + },
  318 +
  319 + hancelSubmit() {
  320 + this.finished = false;
  321 + this.loading = "loadmore";
  322 + this.page = 0;
  323 + this.list = [];
  324 + this._getList();
  325 +
  326 + this.show = false;
  327 + },
  328 +
  329 + }
  330 + }
  331 +</script>
  332 +
  333 +<style lang="scss" scoped>
  334 + .registration_review {
  335 + width: 100%;
  336 + min-height: 100%;
  337 + height: auto;
  338 + background-color: #F7F7F7;
  339 +
  340 + .search_box {
  341 + padding: 36rpx 30rpx 0;
  342 + background-color: #FFFFFF;
  343 +
  344 + .top {
  345 + display: flex;
  346 + flex-flow: row nowrap;
  347 + justify-content: space-between;
  348 + padding: 30rpx;
  349 +
  350 + .check {
  351 + padding: 20rpx 0 0 0;
  352 + }
  353 +
  354 + .search {
  355 + width: 468rpx;
  356 + }
  357 + }
  358 +
  359 + .bottom {
  360 + .time {
  361 + padding: 30rpx 0 30rpx 40rpx;
  362 + }
  363 + }
  364 +
  365 +
  366 + }
  367 +
  368 + .list_box {
  369 + padding: 30rpx 0 50rpx 0;
  370 +
  371 + .item {
  372 + position: relative;
  373 + width: 630rpx;
  374 + margin: 0 auto 30rpx;
  375 + padding: 30rpx;
  376 + border-radius: 12rpx;
  377 + background-color: #FFFFFF;
  378 +
  379 + .bg_image {
  380 + position: absolute;
  381 + top: 0;
  382 + right: 0;
  383 +
  384 + text {
  385 + position: absolute;
  386 + top: 12rpx;
  387 + right: 30rpx;
  388 + font-size: 24rpx;
  389 + line-height: 24rpx;
  390 + color: #FFFFFF;
  391 + }
  392 + }
  393 +
  394 + .info {
  395 + display: flex;
  396 + flex-flow: row nowrap;
  397 + align-items: center;
  398 + margin: 0 0 30rpx 0;
  399 +
  400 + .avatar {
  401 + width: 78rpx;
  402 + height: 94rpx;
  403 + padding: 0 8rpx;
  404 + border-radius: 4rpx;
  405 + background-color: #06B079;
  406 + font-size: 24rpx;
  407 + line-height: 94rpx;
  408 + color: #FFFFFF;
  409 + text-align: center;
  410 + }
  411 +
  412 + .title_name {
  413 + .title {
  414 + font-size: 32rpx;
  415 + line-height: 44rpx;
  416 + color: #202131;
  417 + font-weight: 500;
  418 + margin: 0 20rpx;
  419 + }
  420 +
  421 + .name {
  422 + padding: 8rpx 0 0 20rpx;
  423 + font-size: 28rpx;
  424 + line-height: 32rpx;
  425 + color: #909097;
  426 +
  427 + text:last-child {
  428 + padding: 0 0 0 30rpx;
  429 + color: #202131;
  430 + }
  431 + }
  432 + }
  433 +
  434 + }
  435 +
  436 + .time {
  437 + border-top: 2rpx solid #E2E2E8;
  438 + padding: 28rpx 0 0 0;
  439 +
  440 + text {
  441 + font-size: 28rpx;
  442 + line-height: 32rpx;
  443 + color: #909097;
  444 + }
  445 + }
  446 + }
  447 + }
  448 +
  449 + .popup_search {
  450 + width: 640rpx;
  451 + position: relative;
  452 +
  453 + .content {
  454 + padding: 0 40rpx;
  455 +
  456 + .title {
  457 + padding: 24rpx 0;
  458 + font-size: 28rpx;
  459 + line-height: 36rpx;
  460 + color: #202131;
  461 + }
  462 +
  463 + .scroll {
  464 + max-height: 60vh;
  465 +
  466 + .item {
  467 + width: 540rpx;
  468 + height: 96rpx;
  469 + border-radius: 4rpx;
  470 + border: 2rpx solid #C1C1C9;
  471 + margin: 0 10rpx 20rpx;
  472 + font-size: 24rpx;
  473 + line-height: 32rpx;
  474 + color: #C0C0C9;
  475 + display: flex;
  476 + flex-flow: row wrap;
  477 + align-items: center;
  478 +
  479 + text {
  480 + display: inline-block;
  481 + width: 500rpx;
  482 + height: 64rpx;
  483 + padding: 16rpx 20rpx;
  484 + }
  485 +
  486 +
  487 + }
  488 + }
  489 +
  490 + .time {
  491 + padding: 40rpx 0 0 0;
  492 + }
  493 +
  494 + .switch {
  495 + display: flex;
  496 + flex-flow: row nowrap;
  497 + justify-content: space-between;
  498 + padding: 40rpx 0 0 0;
  499 +
  500 + text {
  501 + font-size: 28rpx;
  502 + line-height: 36rpx;
  503 + color: #202131;
  504 + }
  505 + }
  506 +
  507 +
  508 + }
  509 +
  510 + .footer {
  511 + width: 560rpx;
  512 + height: 96rpx;
  513 + padding: 28rpx 40rpx;
  514 + background: #FFFFFF;
  515 + position: fixed;
  516 + bottom: 0;
  517 + right: 0;
  518 + z-index: 99;
  519 + border-top: 2rpx solid #E2E2E8;
  520 +
  521 + view {
  522 + display: inline-block;
  523 + }
  524 +
  525 + .left_btn {
  526 + width: 194rpx;
  527 + margin: 0 20rpx 0 0;
  528 + }
  529 +
  530 + .right_btn {
  531 + width: 346rpx;
  532 + }
  533 + }
  534 + }
  535 + }
  536 +</style>
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 + <view class="search_box">
  4 + <view class="top">
  5 + <view class="check">
  6 + <u-checkbox-group v-model="checkboxValue" placement="column" @change="checkboxChange">
  7 + <u-checkbox :customStyle="{marginBottom: '8px'}" shape="circle"
  8 + v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"
  9 + activeColor="#06B079" size="28rpx" labelSize="28rpx" labelColor="#202131">
  10 + </u-checkbox>
  11 + </u-checkbox-group>
  12 + </view>
  13 +
  14 + <view class="search">
  15 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  16 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  17 + </u-search>
  18 + </view>
  19 +
  20 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  21 + </view>
  22 + <view class="bottom">
  23 + <u-calendar :show="showTime" :defaultDate="defaultDateMultiple" @close="showTime = false"
  24 + :showSubtitle="false" color="#06B079" @confirm="confirm">
  25 + </u-calendar>
  26 + <view class="time" @click="showTime = true">{{timeValue}}</view>
  27 + </view>
  28 + </view>
  29 +
  30 + <view class="list_box" v-if="list.length > 0">
  31 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  32 +
  33 + <view class="bg_image" v-if="item.waitAttendance == 'attendance'">
  34 + <u-image src="/static/img/home/标签背景-绿@2x.png" width="142rpx" height="48rpx"></u-image>
  35 + <text>已签到</text>
  36 + </view>
  37 +
  38 + <view class="bg_image" v-else>
  39 + <u-image src="/static/img/home/标签背景-灰@2x.png" width="142rpx" height="48rpx"></u-image>
  40 + <text>未签到</text>
  41 + </view>
  42 +
  43 + <view class="info">
  44 + <view class="avatar">{{getNameLastTwo(item.studentName)}}</view>
  45 + <view class="name">{{overflowHide(item.studentName)}}</view>
  46 + <view class="number">{{item.id}}</view>
  47 + </view>
  48 + <view class="company">
  49 + <text>班级</text>
  50 + <text>{{item.className || '--'}}</text>
  51 + </view>
  52 + <view class="company position">
  53 + <text>手机号</text>
  54 + <text>{{item.studentPhone|| '--'}}</text>
  55 + </view>
  56 +
  57 + <view class="time">
  58 + <text>签到时间</text>
  59 + <text>{{timeFormat(item.signIn, 'yyyy-mm-dd hh:MM')}}</text>
  60 + </view>
  61 +
  62 + </view>
  63 + <c-loading :loading="loading"></c-loading>
  64 + </view>
  65 + <view v-else class="no_data">
  66 + <c-no-data></c-no-data>
  67 + </view>
  68 +
  69 + <u-popup :show="show" mode="right" @close="close" @open="open">
  70 + <view class="popup_search">
  71 + <view class="content">
  72 + <view class="title">按项目筛选</view>
  73 + <scroll-view class="scroll" scroll-y="true">
  74 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  75 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  76 + <text>{{item.name}}</text>
  77 + </view>
  78 + <view v-else>
  79 + <text>{{item.name}}</text>
  80 + </view>
  81 + </view>
  82 + </scroll-view>
  83 + <view class="switch">
  84 + <text>未签到</text>
  85 + <u-switch v-model="switchValue" size="48" activeColor="#06B079" @change="handelChange">
  86 + </u-switch>
  87 + </view>
  88 + </view>
  89 +
  90 + <view class="footer">
  91 + <view class="left_btn">
  92 + <c-button type="cancel" text="重置" @click="handelCancel">
  93 + </c-button>
  94 + </view>
  95 + <view class="right_btn">
  96 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  97 + </c-button>
  98 + </view>
  99 + </view>
  100 +
  101 + </view>
  102 + </u-popup>
  103 +
  104 + </view>
  105 +</template>
  106 +
  107 +<script>
  108 + import {
  109 + mapGetters,
  110 + mapState,
  111 + mapActions
  112 + } from 'vuex'
  113 + import listMixin from "@/common/mixins/list-mixin.js";
  114 +
  115 + import {
  116 + getStudentSignInListApi,
  117 + getProjectListApi,
  118 + } from '@/config/api.js';
  119 +
  120 + export default {
  121 + mixins: [listMixin],
  122 + data() {
  123 +
  124 + const d = new Date();
  125 + const year = d.getFullYear();
  126 + let month = d.getMonth() + 1;
  127 + month = month < 10 ? `0${month}` : month;
  128 + const date = d.getDate();
  129 +
  130 + return {
  131 + checkboxValue: [],
  132 + // 基本案列数据
  133 + checkboxList: [{
  134 + name: '未签到',
  135 + disabled: false
  136 + }],
  137 + keyword: '',
  138 + show: false,
  139 + search: {
  140 + //搜索对象必须为key search的对象
  141 + keySearch: "",
  142 + waitAttendance: '',
  143 +
  144 + },
  145 + showTime: false,
  146 + timeValue: `${year}-${month}-${date}`,
  147 + defaultDateMultiple: [`${year}-${month}-${date}`],
  148 + list: [], //列表必须为key list的数组
  149 + projectId: '',
  150 + switchValue: false,
  151 +
  152 + }
  153 + },
  154 +
  155 + onLoad() {},
  156 +
  157 + onShow() {
  158 +
  159 + this.$store.dispatch(`home/getProjectList`, {
  160 + pageSize: -1,
  161 + })
  162 +
  163 + this.search.keySearch = '';
  164 +
  165 + this.finished = false;
  166 + this.loading = "loadmore";
  167 + this.page = 0;
  168 + this.list = [];
  169 + this._getList();
  170 + },
  171 +
  172 + computed: {
  173 + ...mapState('home', {
  174 + // 箭头函数可使代码更简练
  175 + projectList: 'projectList',
  176 +
  177 + }),
  178 +
  179 + },
  180 +
  181 + methods: {
  182 +
  183 + getNameLastTwo(value) {
  184 + if (value && value.length > 3) {
  185 + return value.substring(value.length - 3)
  186 + } else {
  187 + return value;
  188 + }
  189 + },
  190 +
  191 + overflowHide(value, num = 4) {
  192 + if (value && value.length > num) {
  193 + return `${value.slice(0, num)}...`
  194 + } else {
  195 + return value;
  196 + }
  197 + },
  198 +
  199 + confirm(e) {
  200 + this.timeValue = e[0];
  201 + this.showTime = false;
  202 + },
  203 +
  204 + handelDetail(record) {
  205 + this.$u.route({
  206 + url: `pages/main/home/registrationDetail/registrationDetail?&id=${record.id}`
  207 + })
  208 + },
  209 +
  210 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  211 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  212 + },
  213 +
  214 + checkboxChange(n) {
  215 + console.log('change', n);
  216 +
  217 + this.search.waitAttendance = n.length > 0 ? 'not_attendance' : '';
  218 +
  219 + this.switchValue = n.length > 0 ? true : false;
  220 +
  221 + this.finished = false;
  222 + this.loading = "loadmore";
  223 + this.page = 0;
  224 + this.list = [];
  225 + this._getList();
  226 + },
  227 +
  228 + handelSearch(value) {
  229 + this.finished = false;
  230 + this.loading = "loadmore";
  231 + this.page = 0;
  232 + this.list = [];
  233 + this._getList();
  234 + },
  235 +
  236 + open() {
  237 + // console.log('open');
  238 + },
  239 + close() {
  240 + this.show = false
  241 + // console.log('close');
  242 + },
  243 + // scroll-view到底部加载更多
  244 + onreachBottom() {},
  245 + // 搜索
  246 + searchSubmit() {
  247 + // 调用混合搜索
  248 + this._searchData();
  249 + },
  250 + // 模拟后端分页
  251 + async getData(requestParams) {
  252 + const {
  253 + search = {}
  254 + } = requestParams;
  255 +
  256 + let params = {};
  257 + params.pageNumber = requestParams.page + 1;
  258 + params.pageSize = 5;
  259 +
  260 + if (search.waitAttendance) {
  261 + params.waitAttendance = search.waitAttendance;
  262 + }
  263 +
  264 + if (this.keyword) {
  265 + params.keySearch = this.keyword
  266 + }
  267 +
  268 + if (this.projectId) {
  269 + params.projectId = this.projectId
  270 + }
  271 +
  272 + return await getStudentSignInListApi(params);
  273 + },
  274 + // 数据请求(没错就是这么少的代码)
  275 + async _getList() {
  276 + if (this.page == 0) {
  277 + this.list = [];
  278 + }
  279 +
  280 + // 根据实际情况修改自己修改key
  281 + let result = await this.getData({
  282 + page: this.page, // 传入页码
  283 + size: this.size, // 传入每页条数
  284 + search: this.search, // 传入搜索的对象
  285 + });
  286 +
  287 + this.total = result.total;
  288 +
  289 + if (this.list.length == 0 && result.records.length == 0) {
  290 + this.shownoData = false
  291 + } else {
  292 + this.shownoData = true
  293 + }
  294 +
  295 + this.list = this.list.concat(result.records)
  296 + },
  297 +
  298 + handelClick(values) {
  299 + console.log(values);
  300 + this.projectId = values.id;
  301 + },
  302 +
  303 + handelChange(e) {
  304 + console.log(e)
  305 + this.checkboxValue = e ? ['待审核'] : [];
  306 + this.search.waitAttendance = e ? 'wait' : 'wait,pass,reject';
  307 +
  308 + },
  309 +
  310 + handelCancel() {
  311 + this.switchValue = false;
  312 + this.projectId = '';
  313 + },
  314 +
  315 + hancelSubmit() {
  316 + this.finished = false;
  317 + this.loading = "loadmore";
  318 + this.page = 0;
  319 + this.list = [];
  320 + this._getList();
  321 +
  322 + this.show = false;
  323 + },
  324 +
  325 + }
  326 + }
  327 +</script>
  328 +
  329 +<style lang="scss" scoped>
  330 + .registration_review {
  331 + width: 100%;
  332 + min-height: 100%;
  333 + height: auto;
  334 + background-color: #F7F7F7;
  335 +
  336 + .search_box {
  337 + padding: 36rpx 30rpx 0;
  338 + background-color: #FFFFFF;
  339 +
  340 + .top {
  341 + display: flex;
  342 + flex-flow: row nowrap;
  343 + justify-content: space-between;
  344 +
  345 + .check {
  346 + padding: 20rpx 0 0 0;
  347 + }
  348 +
  349 + .search {
  350 + width: 468rpx;
  351 + }
  352 + }
  353 +
  354 + .bottom {
  355 + .time {
  356 + padding: 30rpx 0 30rpx 40rpx;
  357 + }
  358 + }
  359 +
  360 +
  361 + }
  362 +
  363 + .list_box {
  364 + padding: 0 0 50rpx 0;
  365 +
  366 + .item {
  367 + position: relative;
  368 + width: 630rpx;
  369 + margin: 30rpx auto;
  370 + padding: 30rpx;
  371 + border-radius: 12rpx;
  372 + background-color: #FFFFFF;
  373 +
  374 + .bg_image {
  375 + position: absolute;
  376 + top: 0;
  377 + right: 0;
  378 +
  379 + text {
  380 + position: absolute;
  381 + top: 12rpx;
  382 + right: 30rpx;
  383 + font-size: 24rpx;
  384 + line-height: 24rpx;
  385 + color: #FFFFFF;
  386 + }
  387 + }
  388 +
  389 + .info {
  390 + display: flex;
  391 + flex-flow: row nowrap;
  392 + align-items: center;
  393 + margin: 0 0 30rpx 0;
  394 +
  395 + .avatar {
  396 + width: 78rpx;
  397 + height: 94rpx;
  398 + padding: 0 8rpx;
  399 + border-radius: 4rpx;
  400 + background-color: #06B079;
  401 + font-size: 24rpx;
  402 + line-height: 94rpx;
  403 + color: #FFFFFF;
  404 + text-align: center;
  405 + }
  406 +
  407 + .name {
  408 + font-size: 32rpx;
  409 + line-height: 44rpx;
  410 + color: #202131;
  411 + font-weight: 500;
  412 + margin: 0 20rpx;
  413 + }
  414 +
  415 + .number {
  416 + font-size: 28rpx;
  417 + line-height: 32rpx;
  418 + color: #909097;
  419 + }
  420 + }
  421 +
  422 + .company {
  423 + display: flex;
  424 + flex-flow: row nowrap;
  425 + margin: 0 0 30rpx 0;
  426 +
  427 + text {
  428 + font-size: 28rpx;
  429 + line-height: 32rpx;
  430 + color: #909097;
  431 + margin: 0 0 0 16rpx;
  432 + }
  433 +
  434 + text:last-child {
  435 + color: #202131;
  436 + margin: 0 0 0 30rpx;
  437 + }
  438 + }
  439 +
  440 + .time {
  441 + border-top: 2rpx solid #E2E2E8;
  442 + padding: 28rpx 0 0 0;
  443 +
  444 + text {
  445 + font-size: 28rpx;
  446 + line-height: 32rpx;
  447 + color: #909097;
  448 + }
  449 +
  450 + text:last-child {
  451 + color: #202131;
  452 + margin: 0 0 0 78rpx;
  453 + }
  454 + }
  455 + }
  456 + }
  457 +
  458 + .popup_search {
  459 + width: 640rpx;
  460 + position: relative;
  461 +
  462 + .content {
  463 + padding: 0 40rpx;
  464 +
  465 + .title {
  466 + padding: 24rpx 0;
  467 + font-size: 28rpx;
  468 + line-height: 36rpx;
  469 + color: #202131;
  470 + }
  471 +
  472 + .scroll {
  473 + max-height: 60vh;
  474 +
  475 + .item {
  476 + width: 540rpx;
  477 + height: 96rpx;
  478 + border-radius: 4rpx;
  479 + border: 2rpx solid #C1C1C9;
  480 + margin: 0 10rpx 20rpx;
  481 + font-size: 24rpx;
  482 + line-height: 32rpx;
  483 + color: #C0C0C9;
  484 + display: flex;
  485 + flex-flow: row wrap;
  486 + align-items: center;
  487 +
  488 + text {
  489 + display: inline-block;
  490 + width: 500rpx;
  491 + height: 64rpx;
  492 + padding: 16rpx 20rpx;
  493 + }
  494 +
  495 +
  496 + }
  497 + }
  498 +
  499 + .time {
  500 + padding: 40rpx 0 0 0;
  501 + }
  502 +
  503 + .switch {
  504 + display: flex;
  505 + flex-flow: row nowrap;
  506 + justify-content: space-between;
  507 + padding: 40rpx 0 0 0;
  508 +
  509 + text {
  510 + font-size: 28rpx;
  511 + line-height: 36rpx;
  512 + color: #202131;
  513 + }
  514 + }
  515 +
  516 +
  517 + }
  518 +
  519 + .footer {
  520 + width: 560rpx;
  521 + height: 96rpx;
  522 + padding: 28rpx 40rpx;
  523 + background: #FFFFFF;
  524 + position: fixed;
  525 + bottom: 0;
  526 + right: 0;
  527 + z-index: 99;
  528 + border-top: 2rpx solid #E2E2E8;
  529 +
  530 + view {
  531 + display: inline-block;
  532 + }
  533 +
  534 + .left_btn {
  535 + width: 194rpx;
  536 + margin: 0 20rpx 0 0;
  537 + }
  538 +
  539 + .right_btn {
  540 + width: 346rpx;
  541 + }
  542 + }
  543 + }
  544 + }
  545 +</style>
... ...
  1 +<template>
  2 + <view class="info">
  3 + <view style="display: flex;">
  4 + <image class="header_bg" :src="vuex_baseImgUrl+'/intership_header_bg.png'"></image>
  5 + <view style="position: absolute;display: flex;">
  6 + <image class="header_img" src="/static/img/internship/intership_header.png" mode=""></image>
  7 + <text class="text_white">成绩详情</text>
  8 + </view>
  9 + </view>
  10 + <view class="content">
  11 + <view class="content_box">
  12 + <view>
  13 + <text>成绩</text>
  14 + <text class="value_type">{{interDetail.level ? interDetail.level : interDetail.score}}</text>
  15 + </view>
  16 + <view style="margin-top: 32rpx;">
  17 + <text>学分</text>
  18 + <text class="value_type">{{interDetail.credit}}</text>
  19 + </view>
  20 + <view style="margin-top: 32rpx;">
  21 + <text>考评人</text>
  22 + <text class="value_type">{{interDetail.assessorName}}</text>
  23 + </view>
  24 +
  25 + <view style="margin-top: 32rpx;">
  26 + <text>评价</text>
  27 + <text class="value_type">{{interDetail.teacherView}}</text>
  28 + </view>
  29 +
  30 + </view>
  31 + </view>
  32 + </view>
  33 +</template>
  34 +
  35 +<script>
  36 + import {
  37 + getInternshipDetailApi,
  38 + } from '@/config/api.js';
  39 +
  40 + export default {
  41 + data() {
  42 + return {
  43 + id: '',
  44 + interDetail: {},
  45 + projectDetail: {},
  46 + jobDetail: {},
  47 + levels: {
  48 + 'excellence': '优秀',
  49 + 'good': '良好',
  50 + 'pass': '及格',
  51 + 'fail': '不及格'
  52 + },
  53 + grades: '',
  54 + }
  55 + },
  56 + onLoad(e) {
  57 + this.id = e.id;
  58 +
  59 + getInternshipDetailApi(this.id).then(res => {
  60 + this.interDetail = res;
  61 + this.projectDetail = res.projectDetail;
  62 + this.jobDetail = res.jobDetail;
  63 + this.grades = (res.markWay == "hierarchy" ? (res.level ? this.levels[res.level] : "--") : res
  64 + .score + 0 + "/100")
  65 + })
  66 + },
  67 + methods: {
  68 +
  69 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  70 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  71 + },
  72 + }
  73 + }
  74 +</script>
  75 +
  76 +<style lang="scss" scoped>
  77 + .info {
  78 + width: 690rpx;
  79 + background-color: #F7F7F7;
  80 + display: flex;
  81 + flex-direction: column;
  82 + padding: 30rpx;
  83 + height: 100%;
  84 + }
  85 +
  86 + .header_bg {
  87 + width: 100%;
  88 + height: 100rpx;
  89 + }
  90 +
  91 + .header_img {
  92 + width: 36rpx;
  93 + height: 36rpx;
  94 + margin-left: 32rpx;
  95 + margin-right: 10rpx;
  96 + margin-top: 26rpx;
  97 + }
  98 +
  99 + .text_white {
  100 + font-size: 32rpx;
  101 + font-family: PingFangSC-Medium, PingFang SC;
  102 + font-weight: 500;
  103 + color: #FFFFFF;
  104 + line-height: 84rpx;
  105 + }
  106 +
  107 + .content {
  108 + width: 100%;
  109 + background-color: #fff;
  110 + border-bottom-left-radius: 12rpx;
  111 + border-bottom-right-radius: 12rpx;
  112 +
  113 + .text_title {
  114 + font-size: 32rpx;
  115 + font-family: PingFangSC-Medium, PingFang SC;
  116 + font-weight: 500;
  117 + color: #000000;
  118 + margin: 32rpx;
  119 + }
  120 +
  121 + .divide_line {
  122 + height: 1px;
  123 + border: 1px solid rgba(0, 0, 0, 0.06);
  124 + margin-top: 30rpx;
  125 + }
  126 +
  127 + .content_box {
  128 + padding: 32rpx;
  129 + margin-bottom: 48rpx;
  130 + }
  131 +
  132 + .value_type {
  133 + font-size: 28rpx;
  134 + font-family: PingFangSC-Regular, PingFang SC;
  135 + font-weight: 400;
  136 + float: right;
  137 + color: #000000;
  138 + text-align: right;
  139 + width: 400rpx;
  140 + }
  141 + }
  142 +</style>
... ...
  1 +<template>
  2 + <view class="agreemen_detail">
  3 + <view class="box">
  4 + <view class="title">{{detail.title}}</view>
  5 + <view class="item">
  6 + <text>创建时间</text>
  7 + <text>{{timeFormat(detail.createdTime)}}</text>
  8 + </view>
  9 + </view>
  10 +
  11 + <view class="list_box">
  12 + <view class="item">
  13 + <view class="company">
  14 + <text>实习单号</text>
  15 + <text :style="{color:'#06B079'}">{{detail.formNumber || '--'}}</text>
  16 + </view>
  17 + <view class="company">
  18 + <text>学生姓名</text>
  19 + <text>{{detail.studentName|| '--'}}</text>
  20 + </view>
  21 + <view class="company">
  22 + <text>项目名称</text>
  23 + <text>{{detail.projectName|| '--'}}</text>
  24 + </view>
  25 + <view class="company">
  26 + <text>三方协议</text>
  27 + <view class="item_box">
  28 + <text :style="{color:'#06B079'}" v-for="(item,index) in attachments" :key="index"
  29 + @click="openLink(item)">{{item.filename}}</text>
  30 + </view>
  31 +
  32 + </view>
  33 +
  34 + </view>
  35 + </view>
  36 +
  37 + </view>
  38 +</template>
  39 +
  40 +<script>
  41 + import {
  42 + mapGetters,
  43 + mapState,
  44 + mapActions
  45 + } from 'vuex'
  46 + import listMixin from "@/common/mixins/list-mixin.js";
  47 +
  48 + import {
  49 + getImgUrlApi,
  50 + getAgreementDetailApi,
  51 + } from '@/config/api.js';
  52 +
  53 + export default {
  54 + data() {
  55 + return {
  56 + id: '',
  57 + detail: {},
  58 + attachments: [],
  59 + }
  60 + },
  61 +
  62 + onLoad(option) {
  63 +
  64 + this.id = option.id;
  65 + getAgreementDetailApi(option.id).then(data => {
  66 + if (data) {
  67 + this.detail = data;
  68 + this.attachments = data.attachments ? JSON.parse(data.attachments) : [];
  69 + }
  70 + })
  71 + },
  72 +
  73 + methods: {
  74 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  75 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  76 + },
  77 +
  78 + openLink(e) {
  79 + var _this = this
  80 + this.mFileDir = e.filename.substring(0, e.filename.lastIndexOf('.'))
  81 + this.mFileType = e.filename.substring(e.filename.lastIndexOf('.'), e.filename.length)
  82 + getImgUrlApi({
  83 + bucket: e.bucket,
  84 + filePath: e.object
  85 + }).then(data => {
  86 + console.log("data...", data)
  87 + if (e.mime_type.indexOf("image") != -1) {
  88 + _this.openImage(data.url)
  89 + } else {
  90 + uni.downloadFile({
  91 + url: data.url,
  92 + filePath: wx.env.USER_DATA_PATH + '/' + _this.mFileDir + this.mFileType,
  93 + success: (res) => {
  94 + if (res.statusCode === 200) {
  95 + uni.showLoading();
  96 + console.log('download succ', res)
  97 + let fileMgr = wx.getFileSystemManager();
  98 + let filePath = res.filePath
  99 + uni.saveFile({
  100 + tempFilePath: filePath,
  101 + success: function(res) {
  102 + var savedFilePath = res.savedFilePath;
  103 + /* 删除缓存 */
  104 + fileMgr.unlink({
  105 + filePath: wx.env.USER_DATA_PATH +
  106 + '/' +
  107 + _this.mFileDir + _this
  108 + .mFileType,
  109 + success: function(res) {
  110 + console.log(
  111 + 'unlink success:',
  112 + res);
  113 + }
  114 + })
  115 + _this.openDoc()
  116 + },
  117 + fail: function(res) {
  118 + console.log('save fail', res);
  119 + _this.createFile()
  120 + }
  121 + })
  122 + }
  123 + }
  124 + });
  125 + }
  126 + })
  127 + },
  128 +
  129 + createFile() {
  130 + let fileMgr = wx.getFileSystemManager();
  131 + var _this = this
  132 + //利用access方法判断文件是否可用
  133 + fileMgr.access({
  134 + path: wx.env.USER_DATA_PATH + '/' + _this.mFileDir,
  135 + success: (res) => {
  136 + console.log('check success:', res);
  137 + _this.openDoc()
  138 + },
  139 + fail: (res) => {
  140 + console.log('check fail.', res);
  141 + fileMgr.mkdir({
  142 + dirPath: wx.env.USER_DATA_PATH + '/' + _this.mFileDir,
  143 + success: (res) => {
  144 + console.log('mk dir success:', res);
  145 + _this.openDoc()
  146 + },
  147 + fail: (res) => {
  148 + console.log('mk dir fail:', res);
  149 + uni.hideLoading();
  150 + }
  151 + });
  152 + }
  153 + });
  154 + },
  155 +
  156 + openDoc() {
  157 + uni.openDocument({
  158 + filePath: wx.env.USER_DATA_PATH + '/' + this.mFileDir + this.mFileType,
  159 + showMenu: true,
  160 + success: function(res) {
  161 + uni.hideLoading();
  162 + console.log('openDoc succ');
  163 + }
  164 + });
  165 + },
  166 +
  167 + openImage(imgPath) {
  168 + let array = new Array(1).fill(imgPath);
  169 + uni.previewImage({
  170 + urls: array,
  171 + success(res) {
  172 + console.log('openImage success');
  173 + },
  174 + fail(res) {
  175 + console.log('openImage fail:', res);
  176 + }
  177 + });
  178 + },
  179 +
  180 + }
  181 + }
  182 +</script>
  183 +
  184 +<style lang="scss" scoped>
  185 + .agreemen_detail {
  186 + width: 100%;
  187 + min-height: 100%;
  188 + height: auto;
  189 + background-color: #F7F7F7;
  190 + padding: 20rpx 0 0 0;
  191 +
  192 + .box {
  193 + width: 630rpx;
  194 + margin: 0 auto 20rpx;
  195 + padding: 30rpx 30rpx 12rpx 30rpx;
  196 + border-radius: 12rpx;
  197 + background-color: #FFFFFF;
  198 +
  199 + .title {
  200 + font-size: 32rpx;
  201 + line-height: 32rpx;
  202 + color: #202131;
  203 + margin: 0 0 30rpx 0;
  204 + }
  205 +
  206 + .title::before {
  207 + content: "";
  208 + display: inline-block;
  209 + width: 6rpx;
  210 + height: 32rpx;
  211 + background-color: #06B079;
  212 + margin: 0 12rpx 0 0;
  213 + position: relative;
  214 + top: 4rpx;
  215 + border-radius: 8rpx;
  216 + }
  217 +
  218 +
  219 +
  220 + .item {
  221 + margin: 0 0 24rpx 0;
  222 +
  223 + text:first-child {
  224 + display: inline-block;
  225 + width: 112rpx;
  226 + text-align: justify;
  227 + text-align-last: justify;
  228 + font-size: 28rpx;
  229 + line-height: 48rpx;
  230 + color: #909097;
  231 + vertical-align: top;
  232 + }
  233 +
  234 + text:last-child {
  235 + display: inline-block;
  236 + width: 440rpx;
  237 + word-break: break-word;
  238 + font-size: 28rpx;
  239 + line-height: 48rpx;
  240 + color: #202131;
  241 + margin: 0 0 0 30rpx;
  242 + }
  243 + }
  244 + }
  245 +
  246 + .list_box {
  247 + padding: 0 0 50rpx 0;
  248 +
  249 + .item {
  250 + position: relative;
  251 + width: 630rpx;
  252 + margin: 30rpx auto;
  253 + padding: 30rpx;
  254 + border-radius: 12rpx;
  255 + background-color: #FFFFFF;
  256 +
  257 + .company {
  258 + display: flex;
  259 + flex-flow: row nowrap;
  260 + margin: 0 0 30rpx 0;
  261 +
  262 + text {
  263 + width: 120rpx;
  264 + font-size: 28rpx;
  265 + line-height: 32rpx;
  266 + color: #909097;
  267 + margin: 0 0 0 16rpx;
  268 + }
  269 +
  270 + text:last-child {
  271 + width: 450rpx;
  272 + color: #202131;
  273 + margin: 0 0 0 30rpx;
  274 + }
  275 +
  276 + .item_box {
  277 + text {
  278 + display: inline-block;
  279 + width: 450rpx;
  280 + overflow: hidden;
  281 + white-space: nowrap;
  282 + text-overflow: ellipsis;
  283 +
  284 + }
  285 + }
  286 + }
  287 +
  288 + }
  289 + }
  290 + }
  291 +</style>
... ...
  1 +<template>
  2 + <view class="registration_review">
  3 +
  4 + <view class="list_box" v-if="list.length > 0">
  5 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  6 +
  7 + <view class="company">
  8 + <text>实践课程</text>
  9 + <text>{{item.courseName || '--'}}</text>
  10 + </view>
  11 + <view class="company">
  12 + <text>实习计划</text>
  13 + <text>{{item.planName|| '--'}}</text>
  14 + </view>
  15 + <view class="company">
  16 + <text>实习项目</text>
  17 + <text>{{item.projectName|| '--'}}</text>
  18 + </view>
  19 + <view class="company">
  20 + <text>学生名称</text>
  21 + <text>{{item.studentName|| '--'}}</text>
  22 + </view>
  23 +
  24 + <view class="time">
  25 + <text>申请时间</text>
  26 + <text>{{timeFormat(item.createdTime, 'yyyy-mm-dd hh:MM')}}</text>
  27 + </view>
  28 +
  29 + </view>
  30 + <c-loading :loading="loading"></c-loading>
  31 + </view>
  32 + <view v-else class="no_data">
  33 + <c-no-data></c-no-data>
  34 + </view>
  35 +
  36 + </view>
  37 +</template>
  38 +
  39 +<script>
  40 + import {
  41 + mapGetters,
  42 + mapState,
  43 + mapActions
  44 + } from 'vuex'
  45 + import listMixin from "@/common/mixins/list-mixin.js";
  46 +
  47 + import {
  48 + getAgreementListApi,
  49 + } from '@/config/api.js';
  50 +
  51 + export default {
  52 + mixins: [listMixin],
  53 + data() {
  54 + return {
  55 +
  56 + list: [], //列表必须为key list的数组
  57 + search: {
  58 + //搜索对象必须为key search的对象
  59 + status: 'wait,pass,reject',
  60 +
  61 + },
  62 + }
  63 + },
  64 +
  65 + onLoad(option) {
  66 + this.studentId = option.studentId;
  67 +
  68 + this.finished = false;
  69 + this.loading = "loadmore";
  70 + this.page = 0;
  71 + this.list = [];
  72 + this._getList();
  73 + },
  74 +
  75 + onShow() {
  76 +
  77 + },
  78 +
  79 + computed: {
  80 +
  81 +
  82 + },
  83 +
  84 + methods: {
  85 +
  86 + handelDetail(record) {
  87 + this.$u.route({
  88 + url: `pages/main/internship/agreementDetail/agreementDetail?&id=${record.id}`
  89 + })
  90 + },
  91 +
  92 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  93 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  94 + },
  95 +
  96 + // scroll-view到底部加载更多
  97 + onreachBottom() {},
  98 + // 搜索
  99 + searchSubmit() {
  100 + // 调用混合搜索
  101 + this._searchData();
  102 + },
  103 + // 模拟后端分页
  104 + async getData(requestParams) {
  105 + const {
  106 + search = {}
  107 + } = requestParams;
  108 +
  109 + let params = {};
  110 + params.pageNumber = requestParams.page + 1;
  111 + params.pageSize = 5;
  112 +
  113 + if (this.studentId) {
  114 + params.studentId = this.studentId
  115 + }
  116 +
  117 + return await getAgreementListApi(params);
  118 + },
  119 + // 数据请求(没错就是这么少的代码)
  120 + async _getList() {
  121 + if (this.page == 0) {
  122 + this.list = [];
  123 + }
  124 +
  125 + // 根据实际情况修改自己修改key
  126 + let result = await this.getData({
  127 + page: this.page, // 传入页码
  128 + size: this.size, // 传入每页条数
  129 + search: this.search, // 传入搜索的对象
  130 + });
  131 +
  132 + this.total = result.total;
  133 +
  134 + if (this.list.length == 0 && result.records.length == 0) {
  135 + this.shownoData = false
  136 + } else {
  137 + this.shownoData = true
  138 + }
  139 +
  140 + this.list = this.list.concat(result.records)
  141 + },
  142 +
  143 + }
  144 + }
  145 +</script>
  146 +
  147 +<style lang="scss" scoped>
  148 + .registration_review {
  149 + width: 100%;
  150 + min-height: 100%;
  151 + height: auto;
  152 + background-color: #F7F7F7;
  153 +
  154 + .list_box {
  155 + padding: 30rpx 0 50rpx 0;
  156 +
  157 + .item {
  158 + position: relative;
  159 + width: 630rpx;
  160 + margin: 0 auto 30rpx ;
  161 + padding: 30rpx;
  162 + border-radius: 12rpx;
  163 + background-color: #FFFFFF;
  164 +
  165 + .company {
  166 + display: flex;
  167 + flex-flow: row nowrap;
  168 + margin: 0 0 30rpx 0;
  169 +
  170 + text {
  171 + width: 120rpx;
  172 + font-size: 28rpx;
  173 + line-height: 32rpx;
  174 + color: #909097;
  175 + margin: 0 0 0 16rpx;
  176 + }
  177 +
  178 + text:last-child {
  179 + width: 450rpx;
  180 + color: #202131;
  181 + margin: 0 0 0 30rpx;
  182 + }
  183 + }
  184 +
  185 + .time {
  186 + border-top: 2rpx solid #E2E2E8;
  187 + padding: 28rpx 0 0 0;
  188 +
  189 + text {
  190 + width: 120rpx;
  191 + font-size: 28rpx;
  192 + line-height: 32rpx;
  193 + color: #909097;
  194 + }
  195 +
  196 + text:last-child {
  197 + width: 450rpx;
  198 + color: #202131;
  199 + margin: 0 0 0 78rpx;
  200 + }
  201 + }
  202 + }
  203 + }
  204 +
  205 + }
  206 +</style>
... ...
  1 +<template>
  2 + <view class="info">
  3 + <view style="display: flex;">
  4 + <image class="header_bg" :src="vuex_baseImgUrl+'/intership_header_bg.png'"></image>
  5 + <view style="position: absolute;display: flex;">
  6 + <image class="header_img" src="/static/img/internship/intership_header.png" mode=""></image>
  7 + <text class="text_white">实习单详情</text>
  8 + </view>
  9 + </view>
  10 + <view class="content">
  11 + <!-- 基本信息 -->
  12 + <text class="text_title">基本信息</text>
  13 + <view class="divide_line"></view>
  14 + <view class="content_box">
  15 + <view>
  16 + <text>实习单号</text>
  17 + <text class="value_type">{{interDetail.number}}</text>
  18 + </view>
  19 + <view style="margin-top: 32rpx;">
  20 + <text>状态</text>
  21 + <text v-if="interDetail.status == 'wait'" class="value_type">未开始</text>
  22 + <text v-else-if="interDetail.status == 'running'" class="value_type">进行中</text>
  23 + <text v-else-if="interDetail.status == 'done'" class="value_type">已结束</text>
  24 + </view>
  25 + <view style="margin-top: 32rpx;">
  26 + <text>学生姓名</text>
  27 + <text class="value_type">{{interDetail.studentName}}</text>
  28 + </view>
  29 + <view style="margin-top: 32rpx;">
  30 + <text>是否到岗</text>
  31 + <text v-if="interDetail.dutyStatus == 'wait'" class="value_type">未到岗</text>
  32 + <text v-else-if="interDetail.dutyStatus == 'online'" class="value_type">已到岗</text>
  33 + <text v-else-if="interDetail.dutyStatus == 'offline'" class="value_type">已离岗</text>
  34 + </view>
  35 + <view style="margin-top: 32rpx;">
  36 + <text>学号</text>
  37 + <text class="value_type">{{interDetail.studentNumber}}</text>
  38 + </view>
  39 + <view style="margin-top: 32rpx;">
  40 + <text>学生手机号</text>
  41 + <text class="value_type">{{interDetail.studentPhone}}</text>
  42 + </view>
  43 + <view style="margin-top: 32rpx;">
  44 + <text>班级</text>
  45 + <text class="value_type">{{interDetail.classInfo}}</text>
  46 + </view>
  47 + <view style="margin-top: 32rpx;">
  48 + <text>实习成绩</text>
  49 + <text v-if="grades" class="value_type">{{grades}}</text>
  50 + <text v-else class="value_type">--</text>
  51 + </view>
  52 + <view style="margin-top: 32rpx; overflow: hidden;">
  53 + <text>实习评价</text>
  54 + <text v-if="interDetail.teacherView" class="value_type">{{interDetail.teacherView}}</text>
  55 + <text v-else class="value_type">--</text>
  56 + </view>
  57 + </view>
  58 + <!-- 项目信息 -->
  59 + <text class="text_title">项目信息</text>
  60 + <view class="divide_line"></view>
  61 + <view class="content_box">
  62 + <view>
  63 + <text>开设院系</text>
  64 + <text class="value_type">{{interDetail.departmentName}}</text>
  65 + </view>
  66 + <view style="margin-top: 32rpx;">
  67 + <text>开设学期</text>
  68 + <text class="value_type">{{interDetail.schoolTerm}}</text>
  69 + </view>
  70 + <view style="margin-top: 32rpx;">
  71 + <text>实习计划</text>
  72 + <text class="value_type"><text class="value_type">{{interDetail.planName}}</text></text>
  73 + </view>
  74 + <view style="margin-top: 32rpx;">
  75 + <text>实习项目</text>
  76 + <text class="value_type">{{interDetail.projectName}}</text></text>
  77 + </view>
  78 + <view style="margin-top: 32rpx;">
  79 + <text>实习形式</text>
  80 + <text v-if="projectDetail.practiceForm == 'oneself'" class="value_type">自主</text>
  81 + <text v-else-if="projectDetail.practiceForm == 'centralize'"
  82 + class="value_type">集中</text>
  83 + </view>
  84 + <view style="margin-top: 32rpx;">
  85 + <text>实习开始时间</text>
  86 + <text class="value_type">{{timeFormat(projectDetail.startTime)}}</text>
  87 + </view>
  88 + <view style="margin-top: 32rpx;">
  89 + <text>实习结束时间</text>
  90 + <text class="value_type">{{timeFormat(projectDetail.endTime)}}</text>
  91 + </view>
  92 + <view style="margin-top: 32rpx;">
  93 + <text>实习指导老师</text>
  94 + <text v-if="interDetail.teacherName" class="value_type">{{interDetail.teacherName}}</text>
  95 + <text v-else class="value_type">--</text>
  96 + </view>
  97 + <view style="margin-top: 32rpx;">
  98 + <text>老师手机号</text>
  99 + <text v-if="interDetail.teacherPhone" class="value_type">{{interDetail.teacherPhone}}</text>
  100 + <text v-else class="value_type">--</text>
  101 + </view>
  102 + </view>
  103 +
  104 + <!-- 单位信息 -->
  105 + <text class="text_title">单位信息</text>
  106 + <view class="divide_line"></view>
  107 + <view class="content_box">
  108 + <view>
  109 + <text>实习企业</text>
  110 + <text v-if="jobDetail.company"
  111 + class="value_type">{{jobDetail.company}}</text>
  112 + <text v-else class="value_type">--</text>
  113 + </view>
  114 + <view style="margin-top: 32rpx; overflow: hidden;">
  115 + <text>实习岗位</text>
  116 + <text class="value_type"
  117 + style="width: 60%; white-space: nowrap;overflow: hidden; text-overflow: ellipsis">{{jobDetail.name}}</text>
  118 + </view>
  119 + <!-- <view style="margin-top: 32rpx;">
  120 + <text>行业方向</text>
  121 + <text class="value_type">{{interDetail.job.name}}</text>
  122 + </view> -->
  123 + <view style="margin-top: 32rpx;">
  124 + <text>联系人</text>
  125 + <text v-if="jobDetail.contactName"
  126 + class="value_type">{{jobDetail.contactName}}</text>
  127 + <text v-else class="value_type">--</text>
  128 + </view>
  129 + <view style="margin-top: 32rpx;">
  130 + <text>联系电话</text>
  131 + <text v-if="jobDetail.contactPhone"
  132 + class="value_type">{{jobDetail.contactPhone}}</text>
  133 + <text v-else class="value_type">--</text>
  134 + </view>
  135 + <!-- <view style="margin-top: 32rpx;">
  136 + <text>企业邮箱</text>
  137 + <text class="value_type">{{interDetail.job.contactPhone}}</text>
  138 + </view> -->
  139 + <view style="margin-top: 32rpx; overflow: hidden;">
  140 + <text>实习地址</text>
  141 + <text v-if="jobDetail.workSite"
  142 + class="value_type">{{jobDetail.workSite}}</text>
  143 + <text v-else class="value_type">--</text>
  144 + </view>
  145 + </view>
  146 + </view>
  147 + </view>
  148 +</template>
  149 +
  150 +<script>
  151 + import {
  152 + getInternshipDetailApi,
  153 + } from '@/config/api.js';
  154 +
  155 + export default {
  156 + data() {
  157 + return {
  158 + id: '',
  159 + interDetail: {},
  160 + projectDetail: {},
  161 + jobDetail: {},
  162 + levels: {
  163 + 'excellence': '优秀',
  164 + 'good': '良好',
  165 + 'pass': '及格',
  166 + 'fail': '不及格'
  167 + },
  168 + grades: '',
  169 + }
  170 + },
  171 + onLoad(e) {
  172 + this.id = e.id;
  173 +
  174 + getInternshipDetailApi(this.id).then(res => {
  175 + this.interDetail = res;
  176 + this.projectDetail = res.projectDetail;
  177 + this.jobDetail = res.jobDetail;
  178 + this.grades = (res.markWay == "hierarchy" ? (res.level ? this.levels[res.level] : "--") : res
  179 + .score + 0 + "/100")
  180 + })
  181 + },
  182 + methods: {
  183 +
  184 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  185 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  186 + },
  187 + }
  188 + }
  189 +</script>
  190 +
  191 +<style lang="scss" scoped>
  192 + .info {
  193 + width: 690rpx;
  194 + background-color: #F7F7F7;
  195 + display: flex;
  196 + flex-direction: column;
  197 + padding: 30rpx;
  198 + }
  199 +
  200 + .header_bg {
  201 + width: 100%;
  202 + height: 100rpx;
  203 + }
  204 +
  205 + .header_img {
  206 + width: 36rpx;
  207 + height: 36rpx;
  208 + margin-left: 32rpx;
  209 + margin-right: 10rpx;
  210 + margin-top: 26rpx;
  211 + }
  212 +
  213 + .text_white {
  214 + font-size: 32rpx;
  215 + font-family: PingFangSC-Medium, PingFang SC;
  216 + font-weight: 500;
  217 + color: #FFFFFF;
  218 + line-height: 84rpx;
  219 + }
  220 +
  221 + .content {
  222 + width: 100%;
  223 + background-color: #fff;
  224 +
  225 + .text_title {
  226 + font-size: 32rpx;
  227 + font-family: PingFangSC-Medium, PingFang SC;
  228 + font-weight: 500;
  229 + color: #000000;
  230 + margin: 32rpx;
  231 + }
  232 +
  233 + .divide_line {
  234 + height: 1px;
  235 + border: 1px solid rgba(0, 0, 0, 0.06);
  236 + margin-top: 30rpx;
  237 + }
  238 +
  239 + .content_box {
  240 + padding: 32rpx;
  241 + margin-bottom: 48rpx;
  242 + }
  243 +
  244 + .value_type {
  245 + font-size: 28rpx;
  246 + font-family: PingFangSC-Regular, PingFang SC;
  247 + font-weight: 400;
  248 + float: right;
  249 + color: #000000;
  250 + text-align: right;
  251 + width: 400rpx;
  252 + }
  253 + }
  254 +</style>
... ...
  1 +<template>
  2 + <view class="signin_list">
  3 + <mi-calendar :leaveDateList="[`2022-8-2`,`2022-8-4`]" :suspensionDateList="[`2022-08-08`]"
  4 + :normalDateList="[`2022-8-3`]"></mi-calendar>
  5 +
  6 + <view class="steps">
  7 + <u-steps current="1" direction="column">
  8 + <u-steps-item title="已下单" desc="10:30">
  9 + </u-steps-item>
  10 + <u-steps-item title="已出库" desc="10:35">
  11 + </u-steps-item>
  12 + <u-steps-item title="运输中" desc="11:40"></u-steps-item>
  13 + </u-steps>
  14 + </view>
  15 + </view>
  16 +</template>
  17 +
  18 +<script>
  19 + import {
  20 + mapGetters,
  21 + mapState,
  22 + mapActions
  23 + } from 'vuex'
  24 + import listMixin from "@/common/mixins/list-mixin.js";
  25 +
  26 + import {
  27 + getsignInListApi,
  28 + } from '@/config/api.js';
  29 +
  30 +
  31 + export default {
  32 + data() {
  33 + return {
  34 +
  35 + }
  36 + },
  37 +
  38 + onLoad(option) {
  39 + this.studentId = option.studentId;
  40 +
  41 + getsignInListApi({
  42 + studentId: option.studentId,
  43 + })
  44 +
  45 + },
  46 +
  47 + methods: {
  48 +
  49 + }
  50 + }
  51 +</script>
  52 +
  53 +<style lang="scss" scoped>
  54 + .signin_list {
  55 +
  56 + .steps {
  57 + font-size: 28rpx;
  58 + line-height: 36rpx;
  59 + color: #202131;
  60 + }
  61 +
  62 + .steps /deep/ .u-text__value {
  63 + font-size: 28rpx;
  64 + }
  65 + }
  66 +</style>
... ...
  1 +<template>
  2 + <view class="internship_box">
  3 + <view class="internship" v-if="hasLogin">
  4 +
  5 + <view class="search_box">
  6 + <view class="search">
  7 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  8 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  9 + </u-search>
  10 + </view>
  11 + </view>
  12 +
  13 + <view class="list_box" v-if="list.length > 0">
  14 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  15 +
  16 + <view class="info">
  17 + <view class="avatar">{{getNameLastTwo(item.studentName)}}</view>
  18 + <view class="student_info">
  19 + <view class="name">
  20 + <text>{{overflowHide(item.studentName, 4)}}</text>
  21 + <text>({{item.studentNumber}})</text>
  22 + </view>
  23 + <view class="mobile">
  24 + <text>{{item.studentPhone}}</text>
  25 + </view>
  26 + </view>
  27 + </view>
  28 +
  29 + </view>
  30 + <c-loading :loading="loading"></c-loading>
  31 + </view>
  32 + <view v-else class="no_data">
  33 + <c-no-data></c-no-data>
  34 + </view>
  35 +
  36 + </view>
  37 + <view class="no_login" v-else>
  38 + <view class="image">
  39 + <u-image :style="{margin:'0 auto'}" :src="vuex_baseImgUrl+'/internship_bg.png'" width="480rpx"
  40 + height="480rpx"></u-image>
  41 + </view>
  42 + <view class="btn">
  43 + <text>登录后可查看待办事项</text>
  44 + <u-button type="primary" text="登录" color="#06B079" :customStyle="{width:'340rpx'}" @click="handelLOgin">
  45 + </u-button>
  46 + </view>
  47 + </view>
  48 + </view>
  49 +</template>
  50 +
  51 +<script>
  52 + import {
  53 + mapGetters,
  54 + mapState,
  55 + mapActions
  56 + } from 'vuex'
  57 +
  58 + import listMixin from "@/common/mixins/list-mixin.js";
  59 +
  60 + import {
  61 + getStudentListApi,
  62 + } from '@/config/api.js';
  63 +
  64 + export default {
  65 + mixins: [listMixin],
  66 + data() {
  67 + return {
  68 + classInfoId: '',
  69 + keyword: '',
  70 + list: [],
  71 + search: {
  72 + keySearch: "",
  73 + },
  74 + }
  75 + },
  76 +
  77 + onLoad(option) {
  78 + this.classInfoId = option.classInfoId
  79 +
  80 + this.search.keySearch = '';
  81 +
  82 + this.finished = false;
  83 + this.loading = "loadmore";
  84 + this.page = 0;
  85 + this.list = [];
  86 + this._getList();
  87 + },
  88 +
  89 + onShow() {
  90 +
  91 + },
  92 +
  93 + computed: {
  94 + ...mapGetters([
  95 + 'doneRoles',
  96 + ]),
  97 + ...mapState({
  98 + hasLogin: 'hasLogin',
  99 + vuex_user: 'vuex_user',
  100 + teacher: (state) => state.vuex_user.teacher,
  101 + }),
  102 +
  103 +
  104 + },
  105 +
  106 + methods: {
  107 + getNameLastTwo(value) {
  108 + if (value && value.length > 3) {
  109 + return value.substring(value.length - 3)
  110 + } else {
  111 + return value;
  112 + }
  113 + },
  114 +
  115 + overflowHide(value, num = 4) {
  116 + if (value && value.length > num) {
  117 + return `${value.slice(0, num)}...`
  118 + } else {
  119 + return value;
  120 + }
  121 + },
  122 +
  123 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  124 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  125 + },
  126 +
  127 + handelSearch(value) {
  128 + this.finished = false;
  129 + this.loading = "loadmore";
  130 + this.page = 0;
  131 + this.list = [];
  132 + this._getList();
  133 + },
  134 +
  135 + // scroll-view到底部加载更多
  136 + onreachBottom() {},
  137 + // 搜索
  138 + searchSubmit() {
  139 + // 调用混合搜索
  140 + this._searchData();
  141 + },
  142 + // 模拟后端分页
  143 + async getData(requestParams) {
  144 + const {
  145 + search = {}
  146 + } = requestParams;
  147 +
  148 + let params = {};
  149 + params.pageNumber = requestParams.page + 1;
  150 + params.pageSize = 5;
  151 +
  152 + if (this.classInfoId) {
  153 + params.classInfoId = this.classInfoId
  154 + }
  155 +
  156 + if (this.keyword) {
  157 + params.keySearch = this.keyword
  158 + }
  159 +
  160 + return await getStudentListApi(params);
  161 + },
  162 + // 数据请求(没错就是这么少的代码)
  163 + async _getList() {
  164 + if (this.page == 0) {
  165 + this.list = [];
  166 + }
  167 +
  168 + // 根据实际情况修改自己修改key
  169 + let result = await this.getData({
  170 + page: this.page, // 传入页码
  171 + size: this.size, // 传入每页条数
  172 + search: this.search, // 传入搜索的对象
  173 + });
  174 +
  175 + this.total = result.total;
  176 + this.list = this.list.concat(result.records)
  177 + },
  178 +
  179 + handelDetail(record) {
  180 + this.$u.route({
  181 + url: `pages/main/internship/traineeDetail/traineeDetail?studentId=${record.studentId}`
  182 + })
  183 + },
  184 +
  185 + }
  186 + }
  187 +</script>
  188 +
  189 +<style lang="scss" scoped>
  190 + .internship_box {
  191 + background-color: #F7F7F7;
  192 + min-height: 100%;
  193 + height: auto;
  194 +
  195 + .internship {
  196 + width: 100%;
  197 + margin: 0 auto;
  198 +
  199 + .search_box {
  200 + padding: 36rpx 0;
  201 + background-color: #FFFFFF;
  202 +
  203 + .search {
  204 + width: 690rpx;
  205 + margin: 0 auto;
  206 + }
  207 +
  208 + }
  209 +
  210 + .list_box {
  211 + padding: 0 0 50rpx 0;
  212 +
  213 + .item {
  214 + position: relative;
  215 + width: 630rpx;
  216 + margin: 30rpx auto;
  217 + padding: 30rpx;
  218 + border-radius: 12rpx;
  219 + background-color: #FFFFFF;
  220 +
  221 + .info {
  222 + display: flex;
  223 + flex-flow: row nowrap;
  224 + align-items: center;
  225 + margin: 0 0 30rpx 0;
  226 +
  227 + .avatar {
  228 + width: 94rpx;
  229 + height: 94rpx;
  230 + border-radius: 4rpx;
  231 + background-color: #06B079;
  232 + font-size: 24rpx;
  233 + line-height: 94rpx;
  234 + color: #FFFFFF;
  235 + text-align: center;
  236 + }
  237 +
  238 + .student_info {
  239 + .name {
  240 + font-size: 32rpx;
  241 + line-height: 32rpx;
  242 + color: #121212;
  243 + font-weight: 500;
  244 + margin: 0 20rpx;
  245 +
  246 + text:last-child {
  247 + font-size: 26rpx;
  248 + color: #26292F;
  249 + padding: 0 0 0 20rpx;
  250 + }
  251 + }
  252 +
  253 + .mobile {
  254 + padding: 20rpx 0 0 20rpx;
  255 + font-size: 26rpx;
  256 + line-height: 36rpx;
  257 + color: #26292F;
  258 + }
  259 + }
  260 + }
  261 + }
  262 + }
  263 + }
  264 +
  265 + .no_login {
  266 + padding: 180rpx 0 0 0;
  267 + text-align: center;
  268 +
  269 + .image {
  270 + width: 480rpx;
  271 + margin: 0 auto;
  272 + }
  273 +
  274 + .btn {
  275 + position: relative;
  276 + top: -80rpx;
  277 +
  278 + text {
  279 + font-size: 24rpx;
  280 + line-height: 52rpx;
  281 + color: #909097;
  282 +
  283 + }
  284 + }
  285 + }
  286 +
  287 + }
  288 +</style>
... ...
  1 +<template>
  2 + <view class="report_detail">
  3 + <view class="box form_info">
  4 + <view class="info">
  5 + <view class="avatar">{{getNameLastTwo(detail.studentName)}}</view>
  6 + <view class="name">{{overflowHide(detail.studentName, 6)}}</view>
  7 + <view class="number">NO.{{detail.studentNumber}}</view>
  8 + </view>
  9 + <view class="company">
  10 + <text>联系电话</text>
  11 + <text>{{detail.studentPhone || '--'}}</text>
  12 + </view>
  13 + <view class="company">
  14 + <text>班级信息</text>
  15 + <text>{{detail.departmentName}} {{detail.classInfo}}</text>
  16 + </view>
  17 + </view>
  18 +
  19 + <view class="tab_box">
  20 + <view class="tab">
  21 + <u-tabs :list="tabs" :scrollable="false" lineWidth="30rpx" lineHeight="4rpx" lineColor="#06B079"
  22 + :inactiveStyle="{fontSize:'28rpx', color:'#4A4A53'}"
  23 + :activeStyle="{fontSize:'36rpx', color:'#06B079'}" @change="handelTab" :current="current">
  24 + </u-tabs>
  25 + </view>
  26 + <view class="u-icon" v-if="current == 0">
  27 + <u-icon slot="icon" size="32" :name="'/static/img/home/筛选icon@2x.png'" @click="show = true"></u-icon>
  28 + </view>
  29 + </view>
  30 +
  31 + <view v-if="current == 0">
  32 + <view class="box attendance">
  33 + <view class="title">考勤</view>
  34 + <view class="item_icon">
  35 + <text>考勤天数</text>
  36 + <view @click="handelRecord('signin')">
  37 + <text>{{detail.attendanceCount || 0}}天</text>
  38 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  39 + </view>
  40 + </view>
  41 + </view>
  42 +
  43 + <view class="box attendance">
  44 + <view class="title">提交材料</view>
  45 + <view class="item_icon">
  46 + <text>三方协议</text>
  47 + <view @click="handelRecord('aggrent')">
  48 + <text>查看</text>
  49 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  50 + </view>
  51 + </view>
  52 + <view class="item_icon">
  53 + <text>日志</text>
  54 + <view @click="handelRecord('daily')">
  55 + <text>{{detail.dailyLogCount || 0}}篇</text>
  56 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  57 + </view>
  58 + </view>
  59 + <view class="item_icon">
  60 + <text>周志</text>
  61 + <view @click="handelRecord('weekly')">
  62 + <text>{{detail.weekLogCount || 0}}篇</text>
  63 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  64 + </view>
  65 + </view>
  66 + <view class="item_icon">
  67 + <text>月志</text>
  68 + <view @click="handelRecord('monthly')">
  69 + <text>{{detail.monthlyLogCount || 0}}篇</text>
  70 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  71 + </view>
  72 + </view>
  73 + <view class="item_icon">
  74 + <text>实习报告</text>
  75 + <view @click="handelRecord('report')">
  76 + <text>{{detail.internshipReportCount || 0}}次</text>
  77 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="28"></u-icon>
  78 + </view>
  79 + </view>
  80 + </view>
  81 + </view>
  82 +
  83 + <view class="practical_courses" v-if="current == 1">
  84 + <view class="list_box" v-if="list.length > 0">
  85 + <view class="item" v-for="(item, i) in list" :key="i">
  86 +
  87 + <view class="company_box">
  88 + <view class="company">
  89 + <u-icon size="32rpx" name="/static/img/home/实习单位icon@2x.png"></u-icon>
  90 + <text>{{item.companyName}}</text>
  91 + </view>
  92 + <view class="address">
  93 + <u-icon size="32rpx" name="/static/img/home/实习单位icon@2x.png"></u-icon>
  94 + <text>{{item.province}}/{{item.city}}/{{item.district}}</text>
  95 + </view>
  96 + </view>
  97 +
  98 + <view class="projiect_item" v-for="(ele, index) in item.jobResultList" :key="index">
  99 +
  100 + <view class="projiect">
  101 + <text>实习岗位</text>
  102 + <text>{{ele.jobName || '--'}}</text>
  103 + </view>
  104 + <view class="projiect">
  105 + <text>实习时间</text>
  106 + <text>{{ ele.startTime>0 ? `${timeFormat(ele.startTime)}至${timeFormat(ele.endTime)}` : '--'}}</text>
  107 + </view>
  108 + <view class="projiect">
  109 + <text>联系人</text>
  110 + <text>{{ele.contactName|| '--'}}</text>
  111 + </view>
  112 + <view class="projiect">
  113 + <text>联系电话</text>
  114 + <text>{{ele.contactPhone|| ''}}</text>
  115 + </view>
  116 + </view>
  117 + </view>
  118 + <c-loading :loading="loading"></c-loading>
  119 + </view>
  120 +
  121 + </view>
  122 +
  123 + <view class="practical_courses" v-if="current == 2">
  124 + <view class="list_box" v-if="list.length > 0">
  125 + <view class="item" v-for="(item, i) in list" :key="i">
  126 +
  127 + <view class="title_box">
  128 + <view class="title">{{item.courseName}}</view>
  129 + <text class="credit">学分:{{item.credit}}分</text>
  130 + </view>
  131 +
  132 + <view class="projiect_item" v-for="(ele, index) in item.achievementDataList" :key="index">
  133 +
  134 + <view class="projiect">
  135 + <text>项目名称</text>
  136 + <text>{{ele.projectName || '--'}}</text>
  137 + </view>
  138 + <view class="projiect">
  139 + <text>实习时间</text>
  140 + <text>{{ ele.internshipStartTime>0 ? `${timeFormat(ele.internshipStartTime)}至${timeFormat(ele.internshipEndTime)}` : '--'}}</text>
  141 + </view>
  142 + <view class="projiect">
  143 + <text>实习单号</text>
  144 + <text @click="handelDetail(ele, 'internship')"
  145 + :style="{color:'#06B079',textDecoration:'underline'}">{{ele.formNumber|| '--'}}</text>
  146 + </view>
  147 + <view class="projiect">
  148 + <text>成绩</text>
  149 + <text>{{ele.level|| ''}}</text>
  150 + </view>
  151 +
  152 + <view class="projiect">
  153 + <text>学分</text>
  154 + <text @click="handelDetail(ele, 'credit')"
  155 + :style="{color:'#06B079',textDecoration:'underline'}">{{ele.credit|| '0'}}</text>
  156 + </view>
  157 + </view>
  158 + </view>
  159 + <c-loading :loading="loading"></c-loading>
  160 + </view>
  161 +
  162 + </view>
  163 +
  164 + <u-popup :show="show" mode="right" @close="close" @open="open">
  165 + <view class="popup_search">
  166 + <view class="content">
  167 + <view class="title">按项目筛选</view>
  168 + <scroll-view class="scroll" scroll-y="true">
  169 + <view class="item" v-for="(item, i) in projectList" :key="i" @click="handelClick(item)">
  170 + <view :style="{backgroundColor: '#06B079',color: '#FFFFFF'}" v-if="item.id == projectId">
  171 + <text>{{item.name}}</text>
  172 + </view>
  173 + <view v-else>
  174 + <text>{{item.name}}</text>
  175 + </view>
  176 + </view>
  177 + </scroll-view>
  178 + </view>
  179 +
  180 + <view class="footer">
  181 + <view class="left_btn">
  182 + <c-button type="cancel" text="重置" @click="handelCancel">
  183 + </c-button>
  184 + </view>
  185 + <view class="right_btn">
  186 + <c-button type="confirm" text="确定" @click="hancelSubmit">
  187 + </c-button>
  188 + </view>
  189 + </view>
  190 + </view>
  191 + </u-popup>
  192 + </view>
  193 +</template>
  194 +
  195 +<script>
  196 + import {
  197 + mapGetters,
  198 + mapState,
  199 + mapActions
  200 + } from 'vuex'
  201 + import listMixin from "@/common/mixins/list-mixin.js";
  202 +
  203 + import {
  204 + getInternshipProcessDetailApi,
  205 + getInternshipJobListApi,
  206 + getPracticalCoursesListApi,
  207 + } from '@/config/api.js';
  208 +
  209 + export default {
  210 + data() {
  211 + return {
  212 + studentId: '',
  213 + detail: {},
  214 + current: 0,
  215 + tabs: [{
  216 + name: '实习过程',
  217 + }, {
  218 + name: '实习岗位',
  219 + }, {
  220 + name: '实践课程'
  221 + }],
  222 + show: false,
  223 + projectId: '',
  224 + list: [],
  225 + search: {
  226 + //搜索对象必须为key search的对象
  227 + status: 'wait,pass,reject',
  228 +
  229 + },
  230 + }
  231 + },
  232 +
  233 + onLoad(option) {
  234 + this.$store.dispatch(`home/getProjectList`, {
  235 + pageSize: -1,
  236 + })
  237 +
  238 + this.studentId = option.studentId;
  239 + getInternshipProcessDetailApi({
  240 + studentId: option.studentId,
  241 + }).then(data => {
  242 + if (data) {
  243 + this.detail = data
  244 + }
  245 + })
  246 + },
  247 +
  248 + computed: {
  249 + ...mapState('home', {
  250 + // 箭头函数可使代码更简练
  251 + projectList: 'projectList',
  252 + }),
  253 + },
  254 +
  255 + methods: {
  256 +
  257 + getNameLastTwo(value) {
  258 + if (value && value.length > 3) {
  259 + return value.substring(value.length - 3)
  260 + } else {
  261 + return value;
  262 + }
  263 + },
  264 +
  265 + overflowHide(value, num = 4) {
  266 + if (value && value.length > num) {
  267 + return `${value.slice(0, num)}...`
  268 + } else {
  269 + return value;
  270 + }
  271 + },
  272 +
  273 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  274 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  275 + },
  276 +
  277 + handelTab(item) {
  278 + this.current = item.index;
  279 +
  280 + switch (item.index) {
  281 +
  282 + case 1:
  283 + this.finished = false;
  284 + this.loading = "loadmore";
  285 + this.page = 0;
  286 + this.list = [];
  287 + this._getList();
  288 + break;
  289 +
  290 + case 2:
  291 + this.finished = false;
  292 + this.loading = "loadmore";
  293 + this.page = 0;
  294 + this.list = [];
  295 + this._getList();
  296 + break;
  297 + }
  298 + },
  299 +
  300 + handelRecord(type) {
  301 +
  302 + switch (type) {
  303 +
  304 + case 'signin':
  305 + this.$u.route({
  306 + url: `pages/main/internship/signInList/signInList?studentId=${this.detail.studentId}&projectId=${this.projectId}`
  307 + })
  308 + break;
  309 +
  310 + case 'aggrent':
  311 + this.$u.route({
  312 + url: `pages/main/internship/agreementList/agreementList?studentId=${this.detail.studentId}&projectId=${this.projectId}`
  313 + })
  314 + break;
  315 +
  316 + case 'daily':
  317 + this.$u.route({
  318 + url: `pages/main/home/logReview/logReview?cagegory=daily`
  319 + })
  320 + break;
  321 +
  322 + case 'weekly':
  323 + this.$u.route({
  324 + url: `pages/main/home/logReview/logReview?cagegory=weekly`
  325 + })
  326 + break;
  327 +
  328 + case 'monthly':
  329 + this.$u.route({
  330 + url: `pages/main/home/logReview/logReview?cagegory=monthly`
  331 + })
  332 + break;
  333 +
  334 + case 'report':
  335 + this.$u.route({
  336 + url: `pages/main/home/reportReview/reportReview?studentId=${this.detail.studentId}&projectId=${this.projectId}`
  337 + })
  338 + break;
  339 + }
  340 +
  341 + },
  342 +
  343 + open() {
  344 +
  345 + },
  346 +
  347 + close() {
  348 + this.show = false
  349 + },
  350 +
  351 + handelClick(values) {
  352 + this.projectId = values.id;
  353 + },
  354 +
  355 + handelCancel() {
  356 + this.switchValue = false;
  357 + this.projectId = '';
  358 + },
  359 +
  360 + hancelSubmit() {
  361 + this.finished = false;
  362 +
  363 + getInternshipProcessDetailApi({
  364 + studentId: this.studentId,
  365 + projectId: this.projectId,
  366 + }).then(data => {
  367 + if (data) {
  368 + this.detail = data
  369 + }
  370 + })
  371 + },
  372 +
  373 + // scroll-view到底部加载更多
  374 + onreachBottom() {},
  375 + // 搜索
  376 + searchSubmit() {
  377 + // 调用混合搜索
  378 + this._searchData();
  379 + },
  380 + // 模拟后端分页
  381 + async getData(requestParams) {
  382 + const {
  383 + search = {}
  384 + } = requestParams;
  385 +
  386 + let params = {};
  387 + params.pageNumber = requestParams.page + 1;
  388 + params.pageSize = 5;
  389 +
  390 + if (this.studentId) {
  391 + params.studentId = this.studentId
  392 + }
  393 +
  394 + if (this.current == 1) {
  395 + return await getInternshipJobListApi(params);
  396 + } else {
  397 + return await getPracticalCoursesListApi(params);
  398 + }
  399 +
  400 +
  401 + },
  402 + // 数据请求(没错就是这么少的代码)
  403 + async _getList() {
  404 + if (this.page == 0) {
  405 + this.list = [];
  406 + }
  407 +
  408 + // 根据实际情况修改自己修改key
  409 + let result = await this.getData({
  410 + page: this.page, // 传入页码
  411 + size: this.size, // 传入每页条数
  412 + search: this.search, // 传入搜索的对象
  413 + });
  414 +
  415 + console.log(this.list, result)
  416 +
  417 + this.total = result.total;
  418 +
  419 + if (this.list.length == 0 && result.length == 0) {
  420 + this.shownoData = false
  421 + } else {
  422 + this.shownoData = true
  423 + }
  424 +
  425 + this.list = this.list.concat(result)
  426 + },
  427 +
  428 + handelDetail(record, type) {
  429 + switch (type) {
  430 + case 'internship':
  431 + this.$u.route({
  432 + url: `pages/main/internship/intershipInfo/intershipInfo?id=${this.detail.id}`
  433 + })
  434 + break;
  435 +
  436 + case 'credit':
  437 + this.$u.route({
  438 + url: `pages/main/internship/achievementDetail/achievementDetail?id=${this.detail.id}`
  439 + })
  440 + break;
  441 + }
  442 + }
  443 +
  444 + }
  445 + }
  446 +</script>
  447 +
  448 +<style lang="scss" scoped>
  449 + .report_detail {
  450 + width: 100%;
  451 + min-height: 100%;
  452 + height: auto;
  453 + background-color: #F7F7F7;
  454 + padding: 20rpx 0 0 0;
  455 +
  456 + .box {
  457 + width: 630rpx;
  458 + margin: 20rpx auto;
  459 + padding: 30rpx 30rpx 12rpx 30rpx;
  460 + border-radius: 12rpx;
  461 + background-color: #FFFFFF;
  462 +
  463 + .title {
  464 + font-size: 32rpx;
  465 + line-height: 32rpx;
  466 + color: #202131;
  467 + margin: 0 0 30rpx 0;
  468 + }
  469 +
  470 + .title::before {
  471 + content: "";
  472 + display: inline-block;
  473 + width: 6rpx;
  474 + height: 32rpx;
  475 + background-color: #06B079;
  476 + margin: 0 12rpx 0 0;
  477 + position: relative;
  478 + top: 4rpx;
  479 + border-radius: 8rpx;
  480 + }
  481 +
  482 + .item {
  483 + margin: 0 0 24rpx 0;
  484 +
  485 + text:first-child {
  486 + display: inline-block;
  487 + width: 112rpx;
  488 + text-align: justify;
  489 + text-align-last: justify;
  490 + font-size: 28rpx;
  491 + line-height: 48rpx;
  492 + color: #909097;
  493 + vertical-align: top;
  494 + }
  495 +
  496 + text:last-child {
  497 + display: inline-block;
  498 + width: 440rpx;
  499 + font-size: 28rpx;
  500 + line-height: 48rpx;
  501 + color: #202131;
  502 + margin: 0 0 0 78rpx;
  503 + }
  504 + }
  505 +
  506 + .item_icon {
  507 + margin: 0 0 24rpx 0;
  508 + display: flex;
  509 + flex-flow: row nowrap;
  510 + justify-content: space-between;
  511 +
  512 + text {
  513 + display: inline-block;
  514 + width: 112rpx;
  515 + text-align: justify;
  516 + text-align-last: justify;
  517 + font-size: 28rpx;
  518 + line-height: 48rpx;
  519 + color: #909097;
  520 + vertical-align: top;
  521 + }
  522 +
  523 + view {
  524 + display: flex;
  525 + flex-flow: row nowrap;
  526 +
  527 + text {
  528 + display: inline-block;
  529 + width: auto;
  530 + font-size: 28rpx;
  531 + line-height: 48rpx;
  532 + color: #202131;
  533 + margin: 0 0 0 78rpx;
  534 + }
  535 + }
  536 + }
  537 + }
  538 +
  539 + .form_info {
  540 + .info {
  541 + display: flex;
  542 + flex-flow: row nowrap;
  543 + align-items: center;
  544 + margin: 0 0 30rpx 0;
  545 +
  546 + .avatar {
  547 + width: 94rpx;
  548 + height: 94rpx;
  549 + padding: 0 8rpx;
  550 + border-radius: 4rpx;
  551 + background-color: #06B079;
  552 + font-size: 24rpx;
  553 + line-height: 94rpx;
  554 + color: #FFFFFF;
  555 + text-align: center;
  556 + }
  557 +
  558 + .name {
  559 + font-size: 32rpx;
  560 + line-height: 44rpx;
  561 + color: #202131;
  562 + font-weight: 500;
  563 + margin: 0 20rpx;
  564 + }
  565 +
  566 + .number {
  567 + font-size: 28rpx;
  568 + line-height: 32rpx;
  569 + color: #909097;
  570 + }
  571 + }
  572 +
  573 + .company {
  574 + display: flex;
  575 + flex-flow: row nowrap;
  576 + margin: 0 0 30rpx 0;
  577 +
  578 + text {
  579 + width: 120rpx;
  580 + font-size: 28rpx;
  581 + line-height: 32rpx;
  582 + color: #909097;
  583 + margin: 0 0 0 16rpx;
  584 + }
  585 +
  586 + text:last-child {
  587 + width: 470rpx;
  588 + color: #202131;
  589 + margin: 0 0 0 30rpx;
  590 + }
  591 + }
  592 + }
  593 +
  594 + .tab_box {
  595 + position: relative;
  596 +
  597 + .tab {
  598 + width: 600rpx;
  599 + }
  600 +
  601 + .u-icon {
  602 + width: 32rpx;
  603 + position: absolute;
  604 + top: 30rpx;
  605 + right: 30rpx;
  606 + }
  607 + }
  608 +
  609 + .practical_courses {
  610 +
  611 + .list_box {
  612 + padding: 30rpx 0 50rpx 0;
  613 +
  614 + .item {
  615 + position: relative;
  616 + width: 630rpx;
  617 + margin: 0 auto 30rpx;
  618 + padding: 30rpx;
  619 + border-radius: 12rpx;
  620 + background-color: #FFFFFF;
  621 +
  622 + .title_box {
  623 + display: flex;
  624 + flex-flow: row nowrap;
  625 +
  626 + .title {
  627 + font-size: 32rpx;
  628 + line-height: 44rpx;
  629 + color: #202131;
  630 + margin: 0 0 30rpx 0;
  631 + font-weight: 500;
  632 + }
  633 +
  634 + .title::before {
  635 + content: "";
  636 + display: inline-block;
  637 + width: 6rpx;
  638 + height: 32rpx;
  639 + background-color: #06B079;
  640 + margin: 0 12rpx 0 0;
  641 + position: relative;
  642 + top: 4rpx;
  643 + border-radius: 8rpx;
  644 + }
  645 +
  646 + .credit {
  647 + font-size: 28rpx;
  648 + line-height: 44rpx;
  649 + color: #909097;
  650 + margin: 0 0 0 32rpx;
  651 + }
  652 + }
  653 +
  654 + .company_box {
  655 + .company {
  656 + display: flex;
  657 + flex-flow: row nowrap;
  658 + font-size: 32rpx;
  659 + line-height: 44rpx;
  660 + color: #202131;
  661 + margin: 0 0 20rpx 0;
  662 + font-weight: 500;
  663 +
  664 + text {
  665 + margin: 0 0 0 8rpx;
  666 + }
  667 + }
  668 +
  669 + .address {
  670 + display: flex;
  671 + flex-flow: row nowrap;
  672 + font-size: 28rpx;
  673 + line-height: 32rpx;
  674 + color: #909097;
  675 + margin: 0 0 20rpx 0;
  676 +
  677 + text {
  678 + margin: 0 0 0 8rpx;
  679 + }
  680 + }
  681 + }
  682 +
  683 + .projiect_item {
  684 + width: 570rpx;
  685 + border-radius: 12rpx;
  686 + background-color: #F8F8FB;
  687 + margin: 0 0 20rpx 0;
  688 + padding: 30rpx;
  689 +
  690 + .projiect {
  691 + display: flex;
  692 + flex-flow: row nowrap;
  693 + margin: 0 0 30rpx 0;
  694 +
  695 + text {
  696 + width: 120rpx;
  697 + font-size: 28rpx;
  698 + line-height: 32rpx;
  699 + color: #909097;
  700 + text-align: justify;
  701 + text-align-last: justify;
  702 + }
  703 +
  704 + text:last-child {
  705 + width: 420rpx;
  706 + color: #202131;
  707 + margin: 0 0 0 30rpx;
  708 + text-align: start;
  709 + text-align-last: start;
  710 + }
  711 + }
  712 + }
  713 +
  714 +
  715 +
  716 + }
  717 + }
  718 + }
  719 +
  720 + .popup_search {
  721 + width: 640rpx;
  722 + position: relative;
  723 +
  724 + .content {
  725 + padding: 0 40rpx;
  726 +
  727 + .title {
  728 + padding: 24rpx 0;
  729 + font-size: 28rpx;
  730 + line-height: 36rpx;
  731 + color: #202131;
  732 + }
  733 +
  734 + .scroll {
  735 + max-height: 60vh;
  736 +
  737 + .item {
  738 + width: 540rpx;
  739 + height: 96rpx;
  740 + border-radius: 4rpx;
  741 + border: 2rpx solid #C1C1C9;
  742 + margin: 0 10rpx 20rpx;
  743 + font-size: 24rpx;
  744 + line-height: 32rpx;
  745 + color: #C0C0C9;
  746 + display: flex;
  747 + flex-flow: row wrap;
  748 + align-items: center;
  749 +
  750 + text {
  751 + display: inline-block;
  752 + width: 500rpx;
  753 + height: 64rpx;
  754 + padding: 16rpx 20rpx;
  755 + }
  756 +
  757 +
  758 + }
  759 + }
  760 +
  761 + .time {
  762 + padding: 40rpx 0 0 0;
  763 + }
  764 +
  765 + .switch {
  766 + display: flex;
  767 + flex-flow: row nowrap;
  768 + justify-content: space-between;
  769 + padding: 40rpx 0 0 0;
  770 +
  771 + text {
  772 + font-size: 28rpx;
  773 + line-height: 36rpx;
  774 + color: #202131;
  775 + }
  776 + }
  777 +
  778 +
  779 + }
  780 +
  781 + .footer {
  782 + width: 560rpx;
  783 + height: 96rpx;
  784 + padding: 28rpx 40rpx;
  785 + background: #FFFFFF;
  786 + position: fixed;
  787 + bottom: 0;
  788 + right: 0;
  789 + z-index: 99;
  790 + border-top: 2rpx solid #E2E2E8;
  791 +
  792 + view {
  793 + display: inline-block;
  794 + }
  795 +
  796 + .left_btn {
  797 + width: 194rpx;
  798 + margin: 0 20rpx 0 0;
  799 + }
  800 +
  801 + .right_btn {
  802 + width: 346rpx;
  803 + }
  804 + }
  805 + }
  806 + }
  807 +</style>
... ...
  1 +<template>
  2 + <view class="account_safe">
  3 + <view class="cell top">
  4 + <u-cell-group>
  5 + <u-cell title="登录账号" :isLink="true" url="/pages/main/my/editAccount/editAccount" arrow-direction="right"
  6 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  7 + <text slot="value" class="u-slot-value">{{accountName}}</text>
  8 + </u-cell>
  9 + <u-cell title="修改登录密码" :isLink="true" url="/pages/main/my/editPassword/editPassword"
  10 + arrow-direction="right" :rightIconStyle="{fontSize:'26rpx'}"
  11 + :title-style="{color:'#909097', fontSize:'28rpx'}">
  12 + <text slot="value" class="u-slot-value">******</text>
  13 + </u-cell>
  14 + </u-cell-group>
  15 + </view>
  16 +
  17 + <view class="cell bottom">
  18 + <u-cell-group :border="false">
  19 + <u-cell title="手机号" :isLink="true" url="/pages/main/my/editMobile/editMobile" arrow-direction="right"
  20 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  21 + <text slot="value" class="u-slot-value">{{getPhone}}</text>
  22 + </u-cell>
  23 + <u-cell title="注销账户" :isLink="true" url="/pages/main/my/removeAccount/removeAccount" arrow-direction="right"
  24 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  25 + </u-cell>
  26 + </u-cell-group>
  27 + </view>
  28 +
  29 + </view>
  30 +</template>
  31 +
  32 +<script>
  33 + import {
  34 + mapState,
  35 + mapActions
  36 + } from 'vuex'
  37 + import {
  38 + replaceTextToStar
  39 + } from '@/common/commonUtil.js'
  40 +
  41 + export default {
  42 + data() {
  43 + return {
  44 +
  45 + }
  46 + },
  47 +
  48 + computed: {
  49 + ...mapState({
  50 + accountName: (state) => state.vuex_user.username ? state.vuex_user.username : '',
  51 +
  52 + getPhone(state) {
  53 + let phone = state.vuex_user.phone;
  54 + return phone ? replaceTextToStar(phone) : '';
  55 + },
  56 +
  57 + }),
  58 + },
  59 +
  60 + methods: {
  61 + link(type) {
  62 +
  63 + switch (type) {
  64 + case 'account':
  65 + this.$u.route('/pages/student/my/edit-account/edit-account');
  66 + break;
  67 +
  68 + case 'password':
  69 + this.$u.route('/pages/student/my/edit-password/edit-password');
  70 + break;
  71 + }
  72 +
  73 + },
  74 + }
  75 + }
  76 +</script>
  77 +
  78 +<style lang="scss" scoped>
  79 + .account_safe {
  80 + width: 100%;
  81 + height: 100%;
  82 + background-color: #F7F7F7;
  83 + padding: 20rpx 0 0 0;
  84 +
  85 + .top {
  86 + margin: 0 0 20rpx 0;
  87 + }
  88 +
  89 + .cell {
  90 + background-color: #FFFFFF;
  91 +
  92 + .u-slot-value {
  93 + font-size: 28rpx;
  94 + line-height: 40rpx;
  95 + color: #202131;
  96 + }
  97 + }
  98 +
  99 + .cell /deep/ .u-cell {
  100 + padding: 12rpx 0;
  101 +
  102 + .u-cell__value {
  103 + font-size: 34rpx;
  104 + color: rgba(0, 0, 0, 0.5);
  105 + }
  106 + }
  107 + }
  108 +</style>
... ...
  1 +<template>
  2 + <view>
  3 + <view style="width: 100%;height: 100%;">
  4 + <view class="title" style="margin: 32rpx;">账户注销协议</view>
  5 + <view class="content">
  6 + <text class="text" :user-select="true">
  7 + 【特别说明】亲爱的用户,在您正式开始下一步账号注销流程前,我们先为您做出如下特别说明:注销账号后,您将无法再以此账号登录和使用一起教育科技(以下简称“我们”或者“一起教育科技”)的产品与服务以及产品及服务中与第三方合作的服务内容(以下简称为“产品与服务”),这同时也可能会给您的售后维权带来不便。且账号一旦注销完成,将无法恢复。请您在注销前慎重考虑。
  8 +
  9 +
  10 +
  11 + 若您经过慎重考虑后仍执意决定注销账号的,请您务必先行仔细阅读和充分理解本《账号注销协议》,在同意全部内容、且在账号符合全部注销条件后,按照我们的注销操作指引点击进行下一步操作,您勾选本注销协议并点击下一步操作的,即视为您已经同意并签署和遵守本协议全部内容。如您在注销后需要再次使用我们的服务的,欢迎您使用手机号码或我们允许的其他方式重新注册。
  12 +
  13 +
  14 +
  15 + (如您执意决定注销账号的,请继续向下阅读)
  16 +
  17 +
  18 +
  19 + 一、您知悉并同意:您的账号注销后,将(可能)产生包括但不限于如下结果需要您自行承担。
  20 + </text>
  21 + </view>
  22 + <view style="position: fixed;bottom: 0;width: 100%;">
  23 + <view class="divide_line"></view>
  24 + <view class="bottom">
  25 + <view class="bd1">
  26 + <text class="text1" @click="giveUp">放弃注销</text>
  27 + </view>
  28 + <view class="bd2">
  29 + <text class="text2" @click="getCode">同意注销</text>
  30 + </view>
  31 + </view>
  32 + </view>
  33 + </view>
  34 +
  35 + <u-overlay :show="showModal">
  36 + <view class="modal" v-show="showModal">
  37 + <image src="/static/img/my/delete.png" class="close" @click="closeModal"></image>
  38 + <view class="text0" style="margin-top:64rpx">请输入验证码</view>
  39 + <view class="text1" style="margin: 32rpx;">已发送至手机号:{{getPhone}}</view>
  40 + <view style="margin: 32rpx auto;width:'200rpx'">
  41 + <u-code-input :maxlength="4" v-model="currentCode" size="48" :focus="false" :dot="true" :width="76"
  42 + @change="change" @finish="goNext"></u-code-input>
  43 + </view>
  44 + <view style="margin-top: 32rpx;">
  45 + <u-code ref="uCode" @change="codeChange">
  46 + </u-code>
  47 + <view class="text2" @click="getCode">{{tips}}</view>
  48 + </view>
  49 + </view>
  50 + </u-overlay>
  51 +
  52 + </view>
  53 +</template>
  54 +
  55 +<script>
  56 + import {
  57 + replaceTextToStar
  58 + } from '@/common/commonUtil.js'
  59 + import {
  60 + mapState,
  61 + mapActions
  62 + } from 'vuex'
  63 +
  64 + import {
  65 + getSmsCodeApi,
  66 + delAccountApi,
  67 + } from '@/config/api.js';
  68 +
  69 + export default {
  70 + data() {
  71 + return {
  72 + showModal: false,
  73 + title_style: {
  74 + "font-size": "34rpx",
  75 + "font-family": "PingFangSC-Medium, PingFang SC",
  76 + "font-weight": 500,
  77 + "color": "#000000"
  78 + },
  79 + tips: '',
  80 + currentCode: ""
  81 + }
  82 + },
  83 +
  84 + computed: {
  85 + ...mapState({
  86 + // phone: (state) => state.vuex_user.phone,
  87 + getPhone(state) {
  88 + let phone = state.vuex_user.phone;
  89 + return replaceTextToStar(phone);
  90 + },
  91 + }),
  92 + },
  93 +
  94 + methods: {
  95 + giveUp() {
  96 + uni.navigateBack({
  97 + delta: 2
  98 + });
  99 + },
  100 +
  101 + getCode() { //获取验证码
  102 + this.showModal = true;
  103 + if (this.$refs.uCode.canGetCode) {
  104 + // 模拟向后端请求验证码
  105 + uni.showLoading({
  106 + title: '正在获取验证码'
  107 + })
  108 +
  109 + getSmsCodeApi({
  110 + phone: this.vuex_phone
  111 + }).then(data => {
  112 + console.log(data)
  113 +
  114 + uni.hideLoading();
  115 + // 这里此提示会被this.start()方法中的提示覆盖
  116 + this.$u.toast('验证码已发送');
  117 + // 通知验证码组件内部开始倒计时
  118 + this.$refs.uCode.start();
  119 +
  120 + })
  121 + } else {
  122 + this.$u.toast('倒计时结束后再发送');
  123 + }
  124 + },
  125 +
  126 + closeModal() {
  127 + if (this.showModal) {
  128 + this.showModal = false;
  129 + this.$refs.uCode.reset();
  130 + this.currentCode = "";
  131 + }
  132 + },
  133 +
  134 + change(e) {
  135 + this.currentCode = e;
  136 + },
  137 +
  138 + codeChange(text) {
  139 + this.tips = text;
  140 + },
  141 +
  142 + goNext(e) {
  143 + console.log('输入结束,当前值为:' + e);
  144 +
  145 + delAccountApi({
  146 + phone: this.vuex_phone,
  147 + code: e,
  148 + }).then(async data => {
  149 + if (data && data.code == 200) {
  150 + uni.showToast({
  151 + title: '注销成功'
  152 + });
  153 + this.closeModal();
  154 +
  155 + await uni.$u.vuex('vuex_user', {});
  156 + await uni.$u.vuex('vuex_token', {});
  157 + await uni.setStorageSync('lifeData', {})
  158 +
  159 + this.$u.route({
  160 + url: '/pages/main/my/freezing/freezing',
  161 + type: 'reLaunch',
  162 + });
  163 + }
  164 + })
  165 + }
  166 + }
  167 + }
  168 +</script>
  169 +
  170 +<style lang="scss" scoped>
  171 + .title {
  172 + font-size: 48rpx;
  173 + font-family: PingFangSC-Medium, PingFang SC;
  174 + font-weight: 500;
  175 + color: #26292F;
  176 + margin-top: 66rpx;
  177 + }
  178 +
  179 + .content {
  180 + width: 690rpx;
  181 + padding: 12rpx 30rpx;
  182 + margin-bottom: 180rpx;
  183 +
  184 + .text {
  185 + font-size: 28rpx;
  186 + font-family: PingFangSC-Regular, PingFang SC;
  187 + font-weight: 400;
  188 + color: #26292F;
  189 + line-height: 40rpx;
  190 + }
  191 + }
  192 +
  193 + .divide_line {
  194 + width: 100%;
  195 + height: 2rpx;
  196 + border: 2rpx solid #F0F0F1;
  197 + }
  198 +
  199 + .bottom {
  200 + height: 144rpx;
  201 + background-color: #fff;
  202 + display: flex;
  203 + flex-direction: row;
  204 +
  205 + .bd1 {
  206 + height: 96rpx;
  207 + border-radius: 8rpx;
  208 + background-color: rgba(0, 0, 0, 0.03);
  209 + margin: auto 30rpx;
  210 + width: 30%;
  211 + display: flex;
  212 + }
  213 +
  214 + .bd2 {
  215 + height: 96rpx;
  216 + border-radius: 8rpx;
  217 + background-color: rgba(12, 177, 122, 1);
  218 + margin: auto 30rpx;
  219 + width: 60%;
  220 + display: flex;
  221 + }
  222 +
  223 + .text1 {
  224 + color: rgba(0, 0, 0, 0.45);
  225 + font-size: 34rpx;
  226 + font-family: PingFangSC-Medium;
  227 + line-height: 48rpx;
  228 + margin: auto;
  229 + }
  230 +
  231 + .text2 {
  232 + color: #ffff;
  233 + font-size: 34rpx;
  234 + line-height: 48rpx;
  235 + margin: auto;
  236 + }
  237 + }
  238 +
  239 + .modal {
  240 + width: 88%;
  241 + position: relative;
  242 + display: flex;
  243 + flex-direction: column;
  244 + margin: 200rpx auto;
  245 + padding-bottom: 64rpx;
  246 + border-radius: 12rpx;
  247 + background-color: #fff;
  248 +
  249 + .close {
  250 + width: 48rpx;
  251 + height: 48rpx;
  252 + padding: 12rpx;
  253 + position: fixed;
  254 + right: 40rpx;
  255 + }
  256 +
  257 + .text0 {
  258 + font-size: 34rpx;
  259 + font-family: PingFangSC-Medium, PingFang SC;
  260 + font-weight: 500;
  261 + color: #000000;
  262 + text-align: center;
  263 + }
  264 +
  265 + .text1 {
  266 + font-size: 34rpx;
  267 + font-family: PingFangSC-Regular, PingFang SC;
  268 + font-weight: 400;
  269 + color: rgba(0, 0, 0, 0.45);
  270 + text-align: center;
  271 + }
  272 +
  273 + .text2 {
  274 + font-size: 30rpx;
  275 + font-family: PingFangSC-Regular, PingFang SC;
  276 + font-weight: 400;
  277 + color: rgba(0, 0, 0, 0.5);
  278 + line-height: 48rpx;
  279 + text-align: center;
  280 + }
  281 + }
  282 +</style>
... ...
  1 +<template>
  2 + <view class="app">
  3 + <view class="content">
  4 + <view class="title">{{title}}</view>
  5 + <!-- <view class="desc">{{desc}}</view> -->
  6 + <text class="paragraph1">
  7 + 隐私政策
  8 + \n
  9 + 本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。&nbsp;您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。
  10 + \n
  11 + 1.&nbsp;适用范围
  12 + \n
  13 + a)&nbsp;在您注册本应用帐号时,您根据本应用要求提供的个人注册信息;
  14 + \n
  15 + b)&nbsp;在您使用本应用网络服务,或访问本应用平台网页时,本应用自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;
  16 + \n
  17 + c)&nbsp;本应用通过合法途径从商业伙伴处取得的用户个人数据。
  18 + \n
  19 + 您了解并同意,以下信息不适用本隐私权政策:
  20 + \n
  21 + a)&nbsp;您在使用本应用平台提供的搜索服务时输入的关键字信息;
  22 + \n
  23 + b)&nbsp;本应用收集到的您在本应用发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;
  24 + \n
  25 + c)&nbsp;违反法律规定或违反本应用规则行为及本应用已对您采取的措施。
  26 + </text>
  27 + </view>
  28 + </view>
  29 +</template>
  30 +
  31 +<script>
  32 + export default {
  33 + data() {
  34 + return {
  35 + type: '0',
  36 + title: '',
  37 + desc: ''
  38 + }
  39 + },
  40 + onReady() {
  41 + if (this.type == '0') {
  42 + this.title = '隐私协议';
  43 + this.desc = '隐私政策本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。';
  44 + }else {
  45 + this.title = '用户政策';
  46 + this.desc = '用户政策本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。';
  47 + }
  48 + },
  49 + methods: {
  50 +
  51 + }
  52 + }
  53 +</script>
  54 +
  55 +<style lang="scss" scoped>
  56 + .app {
  57 + .content {
  58 + .title {
  59 + margin: 24px 16px 0;
  60 + font-size: 24px;
  61 + font-weight: 400;
  62 + color: #26292F;
  63 + }
  64 +
  65 + .paragraph1 {
  66 + margin: 24px 16px 0;
  67 + padding: 0 0 150rpx 0;
  68 + display: block;
  69 + overflow-wrap: break-word;
  70 + color: rgba(38, 41, 47, 1);
  71 + font-size: 14px;
  72 + line-height: 20px;
  73 + overflow: hidden;
  74 + text-overflow: ellipsis;
  75 + }
  76 +
  77 + }
  78 + }
  79 +</style>
... ...
  1 +<template>
  2 + <view class="edit-account">
  3 + <view class="account_name">
  4 + <view class="img_bg">
  5 + <u-image src="/static/img/my/LOGO@2x.png" width="200rpx" height="96rpx" />
  6 + </view>
  7 + <view class="name">
  8 + <text>账号名:</text>
  9 + <text>{{oldAccount}}</text>
  10 + </view>
  11 + <view class="describe">账号名是用户唯一凭证</view>
  12 + </view>
  13 + <view class="form input_warp">
  14 +
  15 + <u-form labelPosition="left" :model="form" :rules="rules" :error-type="errorType" ref="uForm">
  16 + <u-form-item label="新账号名" labelWidth="150rpx" prop="username" borderBottom>
  17 + <u-input v-model="form.username" @input="handleInput" border="none" :placeholderStyle="{color: 'C1C1C9'}" placeholder="请输入新的账号名">
  18 + </u-input>
  19 + </u-form-item>
  20 + </u-form>
  21 +
  22 + <view class="tips">*变更成功后需重新登录</view>
  23 + <view class="button_warp">
  24 + <c-button type="confirm" shape="circle" @click="submit" :disabled="disabled" text="确认修改"></c-button>
  25 + </view>
  26 + </view>
  27 +
  28 + </view>
  29 +</template>
  30 +
  31 +<script>
  32 + import {
  33 + mapState,
  34 + mapActions
  35 + } from 'vuex'
  36 +
  37 + import {
  38 + updateUserInfoApi,
  39 + } from '@/config/api.js';
  40 +
  41 + export default {
  42 + data() {
  43 +
  44 + return {
  45 + errorType: ['toast'],
  46 + disabled: true,
  47 + form: {
  48 + username: '',
  49 +
  50 + },
  51 + rules: {
  52 + username: [{
  53 + required: true,
  54 + message: '请输入新账号',
  55 + trigger: ['blur', 'change'],
  56 + },
  57 + {
  58 + pattern: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/g,
  59 + // 正则检验前先将值转为字符串
  60 + transform(value) {
  61 + return String(value);
  62 + },
  63 + message: '支持6-20个字母、数字、下划线或减号,以字母开头'
  64 + },
  65 + ],
  66 + }
  67 + }
  68 + },
  69 +
  70 + onLoad(option) {
  71 +
  72 + },
  73 +
  74 + onShow() {
  75 +
  76 + },
  77 +
  78 + // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  79 + onReady() {
  80 + this.$refs.uForm.setRules(this.rules);
  81 + },
  82 +
  83 + computed: {
  84 + ...mapState({
  85 +
  86 + oldAccount: (state) => state.vuex_user.username ? state.vuex_user.username : '',
  87 + }),
  88 + },
  89 +
  90 + methods: {
  91 +
  92 + handleInput(value) {
  93 + console.log(value)
  94 + if (value) {
  95 + this.disabled = false;
  96 + } else {
  97 + this.disabled = true;
  98 + }
  99 + },
  100 +
  101 + submit() {
  102 + console.log(this.form)
  103 +
  104 + this.$refs.uForm.validate().then(res => {
  105 + uni.$u.toast('校验通过');
  106 +
  107 + updateUserInfoApi({
  108 + ...this.form,
  109 + type: 'username',
  110 + }).then(async res => {
  111 + if (res) {
  112 + this.$u.toast('修改密码成功');
  113 + await this.$store.dispatch(`user/loginOut`);
  114 + }
  115 +
  116 + })
  117 +
  118 + }).catch(errors => {
  119 + console.log(errors)
  120 + uni.$u.toast('校验失败')
  121 + })
  122 +
  123 + },
  124 + }
  125 + }
  126 +</script>
  127 +
  128 +<style lang="scss" scoped>
  129 + .edit-account /deep/ .u-input__input {
  130 + font-size: 34rpx;
  131 + }
  132 +
  133 + .edit-account {
  134 + padding: 0 28rpx;
  135 +
  136 + .account_name {
  137 + .img_bg {
  138 + width: 200rpx;
  139 + padding: 100rpx 0 0 0;
  140 + margin: 0 auto;
  141 + }
  142 +
  143 + .name {
  144 + text-align: center;
  145 + padding: 64rpx 0 0 0;
  146 +
  147 + text {
  148 + font-size: 28rpx;
  149 + line-height: 40rpx;
  150 + color: #909097;
  151 + }
  152 +
  153 + text:last-child {
  154 + font-size: 48rpx;
  155 + line-height: 68rpx;
  156 + color: #202131;
  157 + font-weight: 500;
  158 + }
  159 + }
  160 +
  161 + .describe {
  162 + text-align: center;
  163 + font-size: 28rpx;
  164 + line-height: 40rpx;
  165 + color: #909097;
  166 + padding: 0 0 170rpx;
  167 + }
  168 + }
  169 +
  170 + .form {
  171 + .tips {
  172 + font-size: 26rpx;
  173 + color: #909097;
  174 + margin: 12rpx 0 78rpx 0;
  175 + }
  176 + }
  177 + }
  178 +</style>
... ...
  1 +<template>
  2 + <view class="edit-mobile">
  3 + <view class="form input_warp">
  4 + <u-form labelPosition="left" :model="form" :rules="rules" :error-type="errorType" ref="uForm">
  5 + <u-form-item label="新手机号" labelWidth="150rpx" borderBottom prop="phone">
  6 + <u-input v-model="form.phone" @input="handleInput" border="none"
  7 + :placeholderStyle="{color: 'C1C1C9'}" placeholder="请输入手机号码" />
  8 + </u-form-item>
  9 + <u-form-item label="验证码" labelWidth="150rpx" borderBottom prop="code">
  10 + <u-input v-model="form.code" @input="handleInput" border="none"
  11 + :placeholderStyle="{color: 'C1C1C9'}" placeholder="请输入验证码" />
  12 + <u-button type="default" size="mini" slot="right" :hair-line="false"
  13 + :custom-style="{color:'#202131', border:'none',fontSize:'32rpx'}" @click="getCode">{{codeText}}
  14 + </u-button>
  15 + <u-code ref="uCode" @change="codeChange"></u-code>
  16 + </u-form-item>
  17 + </u-form>
  18 + <view class="tips">*变更成功后需重新登录</view>
  19 + <view class="button_warp">
  20 + <c-button type="confirm" shape="circle" @click="submit" :disabled="disabled" text="提交"></c-button>
  21 + </view>
  22 + </view>
  23 +
  24 + <view>
  25 + <u-toast ref="uToast" />
  26 + </view>
  27 + </view>
  28 +</template>
  29 +
  30 +<script>
  31 + import {
  32 + getSmsCodeApi,
  33 + updateUserInfoApi,
  34 + } from '@/config/api.js';
  35 +
  36 + export default {
  37 + data() {
  38 + return {
  39 + errorType: ['toast'],
  40 + disabled: true,
  41 + codeText: '发送验证码',
  42 + form: {
  43 + phone: '',
  44 + code: '',
  45 +
  46 + },
  47 + rules: {
  48 + phone: [{
  49 + required: true,
  50 + message: '请输入手机号',
  51 + trigger: ['blur', 'change'],
  52 + },
  53 + {
  54 + validator: (rule, value, callback) => {
  55 + return this.$u.test.mobile(value);
  56 + },
  57 + message: '请输入正确的手机号'
  58 + },
  59 + ],
  60 + code: [{
  61 + required: true,
  62 + message: '请输入验证码',
  63 + trigger: ['blur', 'change'],
  64 + }, {
  65 + validator: (rule, value, callback) => {
  66 + return this.$u.test.code(value, '4');
  67 + },
  68 + message: '请输入正确的验证码'
  69 + }, ],
  70 + },
  71 + }
  72 + },
  73 +
  74 + onLoad(option) {
  75 +
  76 + },
  77 +
  78 + onShow() {
  79 +
  80 + },
  81 +
  82 + // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  83 + onReady() {
  84 + this.$refs.uForm.setRules(this.rules);
  85 + },
  86 +
  87 + methods: {
  88 +
  89 + handleInput(value) {
  90 + const {
  91 + phone = '', code = ''
  92 + } = this.form;
  93 +
  94 + if (phone && code) {
  95 + this.disabled = false;
  96 + } else {
  97 + this.disabled = true;
  98 + }
  99 + },
  100 +
  101 + codeChange(text) {
  102 + this.codeText = text;
  103 + },
  104 +
  105 + getCode() {
  106 + const {
  107 + phone = ''
  108 + } = this.form;
  109 +
  110 + if (!(phone && /^1[0-9]{10}$/.test(phone))) {
  111 + this.$refs.uToast.show({
  112 + title: '请填写正确手机号',
  113 + type: 'error',
  114 + duration: 1500,
  115 + })
  116 +
  117 + } else {
  118 + if (this.$refs.uCode.canGetCode) {
  119 + // 模拟向后端请求验证码
  120 + uni.showLoading({
  121 + title: '正在获取验证码'
  122 + })
  123 + setTimeout(() => {
  124 + uni.hideLoading();
  125 + // 通知验证码组件内部开始倒计时
  126 + this.$refs.uCode.start();
  127 +
  128 + getSmsCodeApi({
  129 + phone: phone
  130 + })
  131 +
  132 + }, 1000);
  133 + } else {
  134 + this.$u.toast('倒计时结束后再发送');
  135 + }
  136 + }
  137 + },
  138 +
  139 + submit() {
  140 +
  141 + this.$refs.uForm.validate().then(res => {
  142 + uni.$u.toast('校验通过');
  143 +
  144 + updateUserInfoApi({
  145 + ...this.form,
  146 + type: 'phone',
  147 + userType: 'teacher'
  148 + }).then(async res => {
  149 + if (res) {
  150 +
  151 + this.$u.toast('修改手机号码成功');
  152 + await this.$store.dispatch(`user/loginOut`);
  153 + }
  154 + })
  155 +
  156 + }).catch(errors => {
  157 + console.log(errors)
  158 + uni.$u.toast('校验失败')
  159 + })
  160 + }
  161 + }
  162 + }
  163 +</script>
  164 +
  165 +<style lang="scss" scoped>
  166 + .edit-mobile /deep/ .u-input__input {
  167 + font-size: 34rpx;
  168 + }
  169 +
  170 + .edit-mobile {
  171 + padding: 0 28rpx;
  172 +
  173 + .form {
  174 + .tips {
  175 + font-size: 24rpx;
  176 + color: #FA6400;
  177 + margin: 36rpx 0 78rpx 0;
  178 + }
  179 + }
  180 + }
  181 +</style>
... ...
  1 +<template>
  2 + <view class="edit-password">
  3 + <view class="form input_warp">
  4 + <u-form labelPosition="left" :model="form" :rules="rules" :error-type="errorType" ref="uForm">
  5 +
  6 + <u-form-item label="密码" labelWidth="150rpx" borderBottom prop="newPwd">
  7 + <u-input v-model="form.newPwd" @input="handleInput" border="none" :placeholderStyle="{color: 'C1C1C9'}"
  8 + placeholder="请输入密码" />
  9 + </u-form-item>
  10 + <u-form-item label="再次确认" labelWidth="150rpx" borderBottom prop="secondPwd">
  11 + <u-input v-model="form.secondPwd" @input="handleInput" border="none" :placeholderStyle="{color: 'C1C1C9'}"
  12 + placeholder="再次确认" />
  13 + </u-form-item>
  14 +
  15 + </u-form>
  16 + <view class="tips">*变更成功后需重新登录</view>
  17 + <view class="button_warp">
  18 + <c-button type="confirm" shape="circle" @click="getCode" :disabled="disabled" text="提交"></c-button>
  19 + </view>
  20 + </view>
  21 +
  22 + <u-overlay :show="showModal">
  23 + <view class="modal" v-show="showModal">
  24 + <image src="/static/img/my/delete.png" class="close" @click="closeModal"></image>
  25 + <view class="text0" style="margin-top:64rpx">请输入验证码</view>
  26 + <view class="text1" style="margin: 32rpx;">已发送至手机号:{{getPhone}}</view>
  27 + <view style="margin: 32rpx auto;width:'200rpx'">
  28 + <u-code-input :maxlength="4" v-model="currentCode" size="48" :focus="false" :dot="true" :width="76"
  29 + @change="change" @finish="goNext"></u-code-input>
  30 + </view>
  31 + <view style="margin-top: 32rpx;">
  32 + <u-code ref="uCode" @change="codeChange">
  33 + </u-code>
  34 + <view class="text2" @click="getCode">{{tips}}</view>
  35 + </view>
  36 + </view>
  37 + </u-overlay>
  38 +
  39 + </view>
  40 +</template>
  41 +
  42 +<script>
  43 + import {
  44 + replaceTextToStar
  45 + } from '@/common/commonUtil.js'
  46 +
  47 + import {
  48 + mapState,
  49 + mapActions
  50 + } from 'vuex'
  51 +
  52 + import {
  53 + getSmsCodeApi,
  54 + updateUserInfoApi,
  55 + } from '@/config/api.js';
  56 +
  57 + import md5 from '@/common/md5';
  58 +
  59 + export default {
  60 + data() {
  61 +
  62 + return {
  63 + errorType: ['toast'],
  64 + disabled: true,
  65 + form: {
  66 + newPwd: '',
  67 + secondPwd: '',
  68 +
  69 + },
  70 + rules: {
  71 + newPwd: [{
  72 + required: true,
  73 + message: '请输入密码',
  74 + trigger: ['blur', 'change'],
  75 + },
  76 + {
  77 + min: 6,
  78 + max: 20,
  79 + message: '长度在6-20个字符之间'
  80 + },
  81 + {
  82 + pattern: /^[a-zA-Z0-9_]*$/g,
  83 + transform(value) {
  84 + return String(value);
  85 + },
  86 + message: '只能包含字母或数字或下划线'
  87 + },
  88 + ],
  89 + secondPwd: [{
  90 + required: true,
  91 + message: '请输入密码',
  92 + trigger: ['blur', 'change'],
  93 + },
  94 + {
  95 + min: 6,
  96 + max: 20,
  97 + message: '长度在6-20个字符之间'
  98 + },
  99 + {
  100 + pattern: /^[a-zA-Z0-9_]*$/g,
  101 + transform(value) {
  102 + return String(value);
  103 + },
  104 + message: '只能包含字母或数字或下划线'
  105 + },
  106 + ],
  107 + },
  108 + showModal: false,
  109 + tips: '',
  110 + currentCode: ""
  111 + }
  112 + },
  113 +
  114 + onLoad(option) {
  115 + let title = this.vuex_user.password ? '修改密码' : '设置密码'
  116 + uni.setNavigationBarTitle({
  117 + title: title
  118 + })
  119 + },
  120 +
  121 + onShow() {
  122 +
  123 + },
  124 +
  125 + // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  126 + onReady() {
  127 + this.$refs.uForm.setRules(this.rules);
  128 + },
  129 +
  130 + computed: {
  131 + ...mapState({
  132 + phone: (state) => state.vuex_user.phone,
  133 + getPhone(state) {
  134 + let phone = state.vuex_user.phone;
  135 + return replaceTextToStar(phone);
  136 + },
  137 + }),
  138 + },
  139 +
  140 + methods: {
  141 +
  142 + handleInput(value) {
  143 + const {
  144 + newPwd = '', secondPwd = ''
  145 + } = this.form;
  146 +
  147 + if (newPwd && secondPwd) {
  148 + this.disabled = false;
  149 + } else {
  150 + this.disabled = true;
  151 + }
  152 + },
  153 +
  154 + getCode() { //获取验证码
  155 +
  156 + const {
  157 + newPwd = '', secondPwd = ''
  158 + } = this.form;
  159 +
  160 + if (newPwd != secondPwd) {
  161 + this.$u.toast('两次输入密码不一致');
  162 + return;
  163 + }
  164 +
  165 + this.$refs.uForm.validate().then(res => {
  166 + uni.$u.toast('校验通过');
  167 +
  168 + this.showModal = true;
  169 + if (this.$refs.uCode.canGetCode) {
  170 + // 模拟向后端请求验证码
  171 + uni.showLoading({
  172 + title: '正在获取验证码'
  173 + })
  174 +
  175 + getSmsCodeApi({
  176 + phone: this.phone
  177 + }).then(data => {
  178 + console.log(data)
  179 +
  180 + uni.hideLoading();
  181 + // 这里此提示会被this.start()方法中的提示覆盖
  182 + this.$u.toast('验证码已发送');
  183 + // 通知验证码组件内部开始倒计时
  184 + this.$refs.uCode.start();
  185 +
  186 + })
  187 + } else {
  188 + this.$u.toast('倒计时结束后再发送');
  189 + }
  190 +
  191 + }).catch(errors => {
  192 + console.log(errors)
  193 + uni.$u.toast('校验失败')
  194 + })
  195 + },
  196 +
  197 + closeModal() {
  198 + if (this.showModal) {
  199 + this.showModal = false;
  200 + this.$refs.uCode.reset();
  201 + this.currentCode = "";
  202 + }
  203 + },
  204 +
  205 + change(e) {
  206 + this.currentCode = e;
  207 + },
  208 +
  209 + codeChange(text) {
  210 + this.tips = text;
  211 + },
  212 +
  213 + goNext(e) {
  214 + console.log('输入结束,当前值为:' + e);
  215 +
  216 + updateUserInfoApi({
  217 + // ...this.form,
  218 + newPwd: md5.hex_md5(this.form.newPwd),
  219 + secondPwd: md5.hex_md5(this.form.secondPwd),
  220 + phone: this.phone,
  221 + type: 'password',
  222 + code: e,
  223 + }).then(async res => {
  224 + if (res) {
  225 + this.$u.toast('修改密码成功');
  226 + await this.$store.dispatch(`user/loginOut`);
  227 + }
  228 + })
  229 + },
  230 +
  231 + }
  232 + }
  233 +</script>
  234 +
  235 +<style lang="scss" scoped>
  236 + .edit-password /deep/ .u-input__input {
  237 + font-size: 34rpx;
  238 + }
  239 +
  240 + .edit-password {
  241 + padding: 0 28rpx;
  242 +
  243 + .form {
  244 + .tips {
  245 + font-size: 24rpx;
  246 + color: #FA6400;
  247 + margin: 36rpx 0 78rpx 0;
  248 + }
  249 + }
  250 +
  251 + .modal {
  252 + width: 88%;
  253 + position: relative;
  254 + display: flex;
  255 + flex-direction: column;
  256 + margin: 200rpx auto;
  257 + padding-bottom: 64rpx;
  258 + border-radius: 12rpx;
  259 + background-color: #fff;
  260 +
  261 + .close {
  262 + width: 48rpx;
  263 + height: 48rpx;
  264 + padding: 12rpx;
  265 + position: fixed;
  266 + right: 40rpx;
  267 + }
  268 +
  269 + .text0 {
  270 + font-size: 34rpx;
  271 + font-family: PingFangSC-Medium, PingFang SC;
  272 + font-weight: 500;
  273 + color: #000000;
  274 + text-align: center;
  275 + }
  276 +
  277 + .text1 {
  278 + font-size: 34rpx;
  279 + font-family: PingFangSC-Regular, PingFang SC;
  280 + font-weight: 400;
  281 + color: rgba(0, 0, 0, 0.45);
  282 + text-align: center;
  283 + }
  284 +
  285 + .text2 {
  286 + font-size: 30rpx;
  287 + font-family: PingFangSC-Regular, PingFang SC;
  288 + font-weight: 400;
  289 + color: rgba(0, 0, 0, 0.5);
  290 + line-height: 48rpx;
  291 + text-align: center;
  292 + }
  293 + }
  294 + }
  295 +</style>
... ...
  1 +<template>
  2 + <view class="freezing">
  3 + <view class="box">
  4 + <view class="icon">
  5 + <icon type="waiting" size="53"></icon>
  6 + </view>
  7 + <view class="text">
  8 + <view class="title">冻结中</view>
  9 + <view class="describe">您已经提交账号注销申请,此账号已被冻结, 工作人员会在15个工作日内处理您的请求</view>
  10 + </view>
  11 + </view>
  12 +
  13 + <view class="btn fixed_bottom_btn">
  14 + <view class="left_btn">
  15 + <c-button type="cancel" text="撤销注销" @click="giveUp">
  16 + </c-button>
  17 + </view>
  18 + <view class="right_btn">
  19 + <c-button type="confirm" text="联系客服" @click="contactCustomer">
  20 + </c-button>
  21 + </view>
  22 + </view>
  23 +
  24 + </view>
  25 +</template>
  26 +
  27 +<script>
  28 + import {
  29 + mapState,
  30 + mapActions
  31 + } from 'vuex'
  32 +
  33 + import {
  34 + cancelDelAccountApi,
  35 + } from '@/config/api.js';
  36 +
  37 + export default {
  38 + data() {
  39 + return {
  40 +
  41 + }
  42 + },
  43 +
  44 + onLoad(option) {
  45 +
  46 + },
  47 +
  48 + computed: {
  49 + ...mapState({
  50 + // vuex_phone: (state) => state.vuex_phone,
  51 + }),
  52 + },
  53 +
  54 + methods: {
  55 + giveUp() {
  56 + cancelDelAccountApi({
  57 + phone: this.vuex_phone,
  58 + }).then(async data => {
  59 + console.log(data)
  60 + uni.showToast({
  61 + title: '撤销成功'
  62 + });
  63 +
  64 + this.$u.route('/pages/main/my/login/login');
  65 + })
  66 + },
  67 +
  68 + contactCustomer() {
  69 + uni.makePhoneCall({
  70 + phoneNumber: "150-7142-1900"
  71 + })
  72 + },
  73 + }
  74 + }
  75 +</script>
  76 +
  77 +<style lang="scss" scoped>
  78 + .freezing {
  79 + width: 100%;
  80 + height: 100%;
  81 + position: relative;
  82 +
  83 + .box {
  84 + .icon {
  85 + padding: 308rpx 0 0 0;
  86 + text-align: center;
  87 + }
  88 +
  89 + .text {
  90 + text-align: center;
  91 +
  92 + .title {
  93 + font-size: 34rpx;
  94 + color: #000000;
  95 + line-height: 48rpx;
  96 + margin: 44rpx 0 32rpx 0;
  97 + }
  98 +
  99 + .describe {
  100 + width: 560rpx;
  101 + margin: 0 auto;
  102 + font-size: 28rpx;
  103 + color: rgba(0, 0, 0, 0.5);
  104 + line-height: 40rpx;
  105 + }
  106 + }
  107 + }
  108 +
  109 + .fixed_bottom_btn {
  110 + width: 100%;
  111 + height: 144rpx;
  112 + padding: 24rpx 32rpx;
  113 + background: #FFFFFF;
  114 + position: fixed;
  115 + bottom: 0;
  116 + left: 0;
  117 + z-index: 99;
  118 + border-top: 1rpx solid #F0F0F1;
  119 +
  120 + view {
  121 + display: inline-block;
  122 + }
  123 +
  124 + .left_btn {
  125 + width: 212rpx;
  126 + margin: 0 40rpx 0 0;
  127 + }
  128 +
  129 + .right_btn {
  130 + width: 434rpx;
  131 + }
  132 + }
  133 + }
  134 +</style>
... ...
... ... @@ -9,10 +9,8 @@
9 9 </view>
10 10
11 11 <view class="btn button_warp">
12   - <c-button type="confirm" shape="circle"
13   - :customStyle="{borderRadius:'48rpx',fontSize:'34rpx',color:'#fff',fontWeight:'400'}" text="微信一键登录"
14   - :disabled="isDisable" openType="getPhoneNumber" @getPhoneNumber="getPhoneNumber"
15   - @click="getUserProfile"></c-button>
  12 + <c-button type="confirm" text="微信一键登录" :disabled="isDisable" openType="getPhoneNumber"
  13 + @getPhoneNumber="getPhoneNumber" @click="getUserProfile"></c-button>
16 14 </view>
17 15
18 16 <view class="changeLogin" @click="handelMobileLogin">
... ... @@ -45,7 +43,7 @@
45 43
46 44 export default {
47 45 data() {
48   - return {
  46 + return {
49 47 isDisable: true,
50 48 checked: [],
51 49 service: "https://yxlypublic.oss-cn-beijing.aliyuncs.com/WeChat/agreement/%E3%80%8A%E4%BC%98%E5%AD%A6%E4%B9%90%E4%B8%9A%E7%94%A8%E6%88%B7%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE%E3%80%8B.htm",
... ... @@ -66,13 +64,13 @@
66 64
67 65 onShow() {
68 66
69   - },
70   -
71   - watch: {
72   - checked: function(newVal, oldVal) {
73   - this.isDisable = newVal.length != 0 ? false : true;
74   -
75   - }
  67 + },
  68 +
  69 + watch: {
  70 + checked: function(newVal, oldVal) {
  71 + this.isDisable = newVal.length != 0 ? false : true;
  72 +
  73 + }
76 74 },
77 75
78 76 computed: {
... ... @@ -98,7 +96,7 @@
98 96 })
99 97 },
100 98
101   - checkboxChange(n) {
  99 + checkboxChange(n) {
102 100 console.log(n)
103 101
104 102 },
... ... @@ -127,7 +125,7 @@
127 125
128 126 this.$store.dispatch(`user/login`, {
129 127 way: 'wechat_code',
130   - type: 'student',
  128 + type: 'teacher',
131 129 jsCode: res.code,
132 130 code: e.detail.code,
133 131 })
... ...
... ... @@ -204,11 +204,10 @@
204 204 },
205 205
206 206 phoneLogin() {
207   - // this.getUserProfile();
208 207 if (this.changeLogin == '账号密码登录') {
209 208 this.$store.dispatch(`user/login`, {
210 209 way: 'code',
211   - type: 'student',
  210 + type: 'teacher',
212 211 phone: this.form.mobile,
213 212 code: this.form.password,
214 213 })
... ... @@ -216,7 +215,7 @@
216 215 console.log(md5.hex_md5(this.form.password));
217 216 this.$store.dispatch(`user/login`, {
218 217 way: 'name',
219   - type: 'student',
  218 + type: 'teacher',
220 219 username: this.form.mobile,
221 220 password: md5.hex_md5(this.form.password),
222 221 })
... ...
  1 +<template>
  2 + <view class="account_safe">
  3 + <view class="cell top">
  4 + <u-cell-group>
  5 + <u-cell title="登录账号" :isLink="true" url="/pages/main/my/editAccount/editAccount" arrow-direction="right"
  6 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  7 + <text slot="value" class="u-slot-value">{{accountName}}</text>
  8 + </u-cell>
  9 + <u-cell title="姓名" arrow-direction="right" :rightIconStyle="{fontSize:'26rpx'}"
  10 + :title-style="{color:'#909097', fontSize:'28rpx'}">
  11 + <text slot="value" class="u-slot-value">{{teacherName}}</text>
  12 + </u-cell>
  13 + <u-cell title="手机号" :isLink="true" url="/pages/main/my/editMobile/editMobile" arrow-direction="right"
  14 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  15 + <text slot="value" class="u-slot-value">{{getPhone}}</text>
  16 + </u-cell>
  17 + <u-cell title="工号" arrow-direction="right" :rightIconStyle="{fontSize:'26rpx'}"
  18 + :title-style="{color:'#909097', fontSize:'28rpx'}">
  19 + </u-cell>
  20 + <u-cell title="院系专业" arrow-direction="right" :rightIconStyle="{fontSize:'26rpx'}"
  21 + :title-style="{color:'#909097', fontSize:'28rpx'}">
  22 + <text slot="value" class="u-slot-value">{{departmentName}}</text>
  23 + </u-cell>
  24 + </u-cell-group>
  25 + </view>
  26 +
  27 +
  28 + </view>
  29 +</template>
  30 +
  31 +<script>
  32 + import {
  33 + mapState,
  34 + mapActions
  35 + } from 'vuex'
  36 + import {
  37 + replaceTextToStar
  38 + } from '@/common/commonUtil.js'
  39 +
  40 + export default {
  41 + data() {
  42 + return {
  43 +
  44 + }
  45 + },
  46 +
  47 + computed: {
  48 + ...mapState({
  49 + accountName: (state) => state.vuex_user.username ? state.vuex_user.username : '',
  50 + teacherName: (state) => state.vuex_user.teacher.name ? state.vuex_user.teacher.name : '',
  51 + jobNumber: (state) => state.vuex_user.teacher.number ? state.vuex_user.teacher.number : '',
  52 + departmentName: (state) => state.vuex_user.teacher.departments[0].name ? state.vuex_user.teacher
  53 + .departments[0].name : '',
  54 +
  55 + getPhone(state) {
  56 + let phone = state.vuex_user.phone;
  57 + return phone ? replaceTextToStar(phone) : '';
  58 + },
  59 +
  60 + }),
  61 + },
  62 +
  63 + methods: {
  64 + link(type) {
  65 +
  66 + switch (type) {
  67 + case 'account':
  68 + this.$u.route('/pages/student/my/edit-account/edit-account');
  69 + break;
  70 +
  71 + case 'password':
  72 + this.$u.route('/pages/student/my/edit-password/edit-password');
  73 + break;
  74 + }
  75 +
  76 + },
  77 + }
  78 + }
  79 +</script>
  80 +
  81 +<style lang="scss" scoped>
  82 + .account_safe {
  83 + width: 100%;
  84 + height: 100%;
  85 + background-color: #F7F7F7;
  86 + padding: 20rpx 0 0 0;
  87 +
  88 + .top {
  89 + margin: 0 0 20rpx 0;
  90 + }
  91 +
  92 + .cell {
  93 + background-color: #FFFFFF;
  94 +
  95 + .u-slot-value {
  96 + font-size: 28rpx;
  97 + line-height: 40rpx;
  98 + color: #202131;
  99 + }
  100 + }
  101 +
  102 + .cell /deep/ .u-cell {
  103 + padding: 12rpx 0;
  104 +
  105 + .u-cell__value {
  106 + font-size: 34rpx;
  107 + color: rgba(0, 0, 0, 0.5);
  108 + }
  109 + }
  110 + }
  111 +</style>
... ...
  1 +<template>
  2 + <view class="account_safe">
  3 + <view class="cell top">
  4 + <u-cell-group>
  5 + <u-cell title="用户政策" :isLink="true" url="/pages/main/my/userPolicy/userPolicy" arrow-direction="right"
  6 + :rightIconStyle="{fontSize:'26rpx'}" :title-style="{color:'#909097', fontSize:'28rpx'}">
  7 + </u-cell>
  8 + <u-cell title="隐私协议" :isLink="true" url="/pages/main/my/agreement/agreement"
  9 + arrow-direction="right" :rightIconStyle="{fontSize:'26rpx'}"
  10 + :title-style="{color:'#909097', fontSize:'28rpx'}">
  11 + </u-cell>
  12 + </u-cell-group>
  13 + </view>
  14 +
  15 + </view>
  16 +</template>
  17 +
  18 +<script>
  19 + import {
  20 + mapState,
  21 + mapActions
  22 + } from 'vuex'
  23 + import {
  24 + replaceTextToStar
  25 + } from '@/common/commonUtil.js'
  26 +
  27 + export default {
  28 + data() {
  29 + return {
  30 +
  31 + }
  32 + },
  33 +
  34 + computed: {
  35 + ...mapState({
  36 + accountName: (state) => state.vuex_user.username ? state.vuex_user.username : '',
  37 +
  38 + getPhone(state) {
  39 + let phone = state.vuex_user.phone;
  40 + return phone ? replaceTextToStar(phone) : '';
  41 + },
  42 +
  43 + }),
  44 + },
  45 +
  46 + methods: {
  47 + link(type) {
  48 +
  49 + switch (type) {
  50 + case 'account':
  51 + this.$u.route('/pages/student/my/edit-account/edit-account');
  52 + break;
  53 +
  54 + case 'password':
  55 + this.$u.route('/pages/student/my/edit-password/edit-password');
  56 + break;
  57 + }
  58 +
  59 + },
  60 + }
  61 + }
  62 +</script>
  63 +
  64 +<style lang="scss" scoped>
  65 + .account_safe {
  66 + width: 100%;
  67 + height: 100%;
  68 + background-color: #F7F7F7;
  69 + padding: 20rpx 0 0 0;
  70 +
  71 + .top {
  72 + margin: 0 0 20rpx 0;
  73 + }
  74 +
  75 + .cell {
  76 + background-color: #FFFFFF;
  77 +
  78 + .u-slot-value {
  79 + font-size: 28rpx;
  80 + line-height: 40rpx;
  81 + color: #202131;
  82 + }
  83 + }
  84 +
  85 + .cell /deep/ .u-cell {
  86 + padding: 12rpx 0;
  87 +
  88 + .u-cell__value {
  89 + font-size: 34rpx;
  90 + color: rgba(0, 0, 0, 0.5);
  91 + }
  92 + }
  93 + }
  94 +</style>
... ...
  1 +<template>
  2 + <view class="remove_account">
  3 + <view class="title">注销账户</view>
  4 + <view class="sub_title" style="margin-top: 20rpx;">账号主体:{{getPhone}}</view>
  5 + <view class="content">
  6 + <text class="text">
  7 + 如您注销优学乐业服务,则当前服务在APP
  8 + 小程序、等留存的信息均将被清空且无法被
  9 + 找回。具体包括一下信息:
  10 +
  11 + · 优学乐业学生注册账号及状态信息
  12 +
  13 + · 优学乐业保存的学生个人信息
  14 +
  15 + · 优学乐业保存的学生学籍信息
  16 +
  17 + · 学生所有实习及相关活动记录
  18 +
  19 + · 学生实习成绩信息
  20 +
  21 + · 订阅消息、短信等通知不再进行推送
  22 + </text>
  23 + </view>
  24 + <view class="footer">
  25 + <view class="left_btn">
  26 + <c-button type="confirm" shape="circle" @click="removeAccount" :disabled="false" text="注销申请"></c-button>
  27 + </view>
  28 + </view>
  29 + </view>
  30 +</template>
  31 +
  32 +<script>
  33 + import {
  34 + replaceTextToStar
  35 + } from '@/common/commonUtil.js'
  36 + import {
  37 + mapState,
  38 + mapActions
  39 + } from 'vuex'
  40 +
  41 + export default {
  42 + data() {
  43 + return {
  44 +
  45 + }
  46 + },
  47 +
  48 + computed: {
  49 + ...mapState({
  50 + getPhone(state) {
  51 + let phone = state.vuex_user.phone;
  52 + return replaceTextToStar(phone);
  53 + },
  54 + }),
  55 + },
  56 +
  57 + methods: {
  58 + removeAccount() {
  59 + this.$u.route('/pages/main/my/againRemove/againRemove');
  60 + }
  61 + }
  62 + }
  63 +</script>
  64 +
  65 +<style lang="scss" scoped>
  66 + .remove_account {
  67 + background-color: #FFFFFF;
  68 + }
  69 +
  70 + .title {
  71 + font-size: 44rpx;
  72 + font-family: PingFangSC-Medium, PingFang SC;
  73 + font-weight: 500;
  74 + color: #000000;
  75 + margin-top: 48rpx;
  76 + text-align: center;
  77 + }
  78 +
  79 + .sub_title {
  80 + font-size: 17px;
  81 + font-family: PingFangSC-Regular, PingFang SC;
  82 + font-weight: 400;
  83 + color: rgba(0, 0, 0, 0.65);
  84 + line-height: 24px;
  85 + text-align: center;
  86 + }
  87 +
  88 + .content {
  89 + width: 594rpx;
  90 + background: rgba(0, 0, 0, 0.03);
  91 + padding: 48rpx;
  92 + margin: 48rpx auto;
  93 +
  94 + .text {
  95 + font-size: 30rpx;
  96 + font-family: PingFangSC-Regular, PingFang SC;
  97 + font-weight: 400;
  98 + color: rgba(0, 0, 0, 0.65);
  99 + line-height: 42rpx;
  100 + }
  101 + }
  102 +
  103 + .footer {
  104 + width: 100%;
  105 + height: 96rpx;
  106 + padding: 28rpx 30rpx;
  107 + background: #FFFFFF;
  108 + position: fixed;
  109 + bottom: 0;
  110 + left: 0;
  111 + z-index: 99;
  112 + border-top: 2rpx solid #E2E2E8;
  113 +
  114 + view {
  115 + display: inline-block;
  116 + }
  117 +
  118 + .left_btn {
  119 + width: 690rpx;
  120 + margin: 0 30rpx 0 0;
  121 + }
  122 + }
  123 +</style>
... ...
  1 +<template>
  2 + <view class="app">
  3 + <view class="content">
  4 + <view class="title">{{title}}</view>
  5 + <!-- <view class="desc">{{desc}}</view> -->
  6 + <text class="paragraph1">
  7 + 用户政策
  8 + \n
  9 + 本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。&nbsp;您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。
  10 + \n
  11 + 1.&nbsp;适用范围
  12 + \n
  13 + a)&nbsp;在您注册本应用帐号时,您根据本应用要求提供的个人注册信息;
  14 + \n
  15 + b)&nbsp;在您使用本应用网络服务,或访问本应用平台网页时,本应用自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;
  16 + \n
  17 + c)&nbsp;本应用通过合法途径从商业伙伴处取得的用户个人数据。
  18 + \n
  19 + 您了解并同意,以下信息不适用本隐私权政策:
  20 + \n
  21 + a)&nbsp;您在使用本应用平台提供的搜索服务时输入的关键字信息;
  22 + \n
  23 + b)&nbsp;本应用收集到的您在本应用发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;
  24 + \n
  25 + c)&nbsp;违反法律规定或违反本应用规则行为及本应用已对您采取的措施。
  26 + </text>
  27 + </view>
  28 + </view>
  29 +</template>
  30 +
  31 +<script>
  32 + export default {
  33 + data() {
  34 + return {
  35 + title: '',
  36 + desc: ''
  37 + }
  38 + },
  39 + onReady() {
  40 + this.title = '用户政策';
  41 + this.desc = '隐私政策本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。';
  42 + },
  43 + methods: {
  44 +
  45 + }
  46 + }
  47 +</script>
  48 +
  49 +<style lang="scss" scoped>
  50 + .app {
  51 + .content {
  52 + .title {
  53 + margin: 24px 16px 0;
  54 + font-size: 24px;
  55 + font-weight: 400;
  56 + color: #26292F;
  57 + }
  58 +
  59 + .paragraph1 {
  60 + margin: 24px 16px 0;
  61 + padding: 0 0 150rpx 0;
  62 + display: block;
  63 + overflow-wrap: break-word;
  64 + color: rgba(38, 41, 47, 1);
  65 + font-size: 14px;
  66 + line-height: 20px;
  67 + overflow: hidden;
  68 + text-overflow: ellipsis;
  69 + }
  70 +
  71 + }
  72 + }
  73 +</style>
... ...
  1 +<template>
  2 + <view class="edit-account">
  3 + <view class="account_name">
  4 + <view class="img_bg">
  5 + <u-image src="/static/img/my/LOGO@2x.png" width="200rpx" height="96rpx" />
  6 + </view>
  7 + <view class="describe">版本号v1.3.3</view>
  8 + </view>
  9 +
  10 +
  11 + </view>
  12 +</template>
  13 +
  14 +<script>
  15 +
  16 +
  17 + export default {
  18 + data() {
  19 +
  20 + return {
  21 +
  22 + }
  23 + },
  24 +
  25 + onLoad(option) {
  26 +
  27 + },
  28 +
  29 + onShow() {
  30 +
  31 + },
  32 +
  33 +
  34 +
  35 +
  36 + methods: {
  37 +
  38 +
  39 + }
  40 + }
  41 +</script>
  42 +
  43 +<style lang="scss" scoped>
  44 + .edit-account /deep/ .u-input__input {
  45 + font-size: 34rpx;
  46 + }
  47 +
  48 + .edit-account {
  49 + padding: 0 28rpx;
  50 +
  51 + .account_name {
  52 + .img_bg {
  53 + width: 200rpx;
  54 + padding: 100rpx 0 0 0;
  55 + margin: 0 auto;
  56 + }
  57 +
  58 + .describe {
  59 + text-align: center;
  60 + font-size: 24rpx;
  61 + line-height: 48rpx;
  62 + color: #202131;
  63 + padding: 40rpx 0 0 0;
  64 + }
  65 + }
  66 + }
  67 +</style>
... ...
  1 +<template>
  2 + <view class="written-off">
  3 + <view class="box">
  4 + <view class="icon">
  5 + <icon type="warn" size="53"></icon>
  6 + </view>
  7 + <view class="text">
  8 + <view class="title">已注销</view>
  9 + <view class="describe">您的账号已注销,请更换账号登录</view>
  10 + </view>
  11 + </view>
  12 +
  13 + <view class="footer">
  14 + <view class="left_btn">
  15 + <c-button type="confirm" shape="circle" @click="popPhoneNumber" text="联系客服"></c-button>
  16 + </view>
  17 + </view>
  18 + </view>
  19 +</template>
  20 +
  21 +<script>
  22 + export default {
  23 + data() {
  24 + return {
  25 +
  26 + }
  27 + },
  28 + methods: {
  29 + popPhoneNumber(){
  30 + uni.makePhoneCall({
  31 + phoneNumber:"150-7142-1900"
  32 + })
  33 + },
  34 + }
  35 + }
  36 +</script>
  37 +
  38 +<style lang="scss" scoped>
  39 + .written-off {
  40 + width: 100%;
  41 + height: 100%;
  42 + position: relative;
  43 +
  44 + .box {
  45 + .icon {
  46 + padding: 308rpx 0 0 0;
  47 + text-align: center;
  48 + }
  49 +
  50 + .text {
  51 + text-align: center;
  52 +
  53 + .title {
  54 + font-size: 34rpx;
  55 + color: #000000;
  56 + line-height: 48rpx;
  57 + margin: 44rpx 0 32rpx 0;
  58 + }
  59 +
  60 + .describe {
  61 + font-size: 28rpx;
  62 + color: rgba(0, 0, 0, 0.5);
  63 + line-height: 40rpx;
  64 + }
  65 + }
  66 + }
  67 +
  68 + .footer {
  69 + width: 100%;
  70 + height: 96rpx;
  71 + padding: 28rpx 30rpx;
  72 + background: #FFFFFF;
  73 + position: fixed;
  74 + bottom: 0;
  75 + left: 0;
  76 + z-index: 99;
  77 + border-top: 2rpx solid #E2E2E8;
  78 +
  79 + view {
  80 + display: inline-block;
  81 + }
  82 +
  83 + .left_btn {
  84 + width: 690rpx;
  85 + margin: 0 30rpx 0 0;
  86 + }
  87 + }
  88 + }
  89 +</style>
... ...
1 1 <template>
2   - <view style="height: 100%;">
  2 + <view class="home_box">
  3 + <view class="home">
3 4
  5 + <view class="bar"></view>
  6 +
  7 + <view class="info" v-if="hasLogin">
  8 + <u-row justify="space-between" customStyle="margin-bottom: 24rpx">
  9 + <u-col span="5">
  10 + <view class="name">
  11 + <text>{{teacher.name}}</text>
  12 + <text>老师您好!</text>
  13 + </view>
  14 + </u-col>
  15 + <u-col span="3">
  16 + <view class="identity" @click="handelChange">
  17 + <u-icon size="36rpx" :label="doneRoles" labelPos="right" labelSize="24rpx"
  18 + labelColor="#202131" name="/static/img/home/切换身份@2x.png"></u-icon>
  19 + </view>
  20 + </u-col>
  21 + </u-row>
  22 + </view>
  23 +
  24 + <view class="info" v-else>
  25 + <u-row justify="space-between" customStyle="margin-bottom: 24rpx">
  26 + <u-col span="5">
  27 + <view class="name" @click="handelLOgin">
  28 + <text>未登录</text>
  29 + <text>您还没有登录</text>
  30 + </view>
  31 + </u-col>
  32 + </u-row>
  33 + </view>
  34 +
  35 + <view class="gate">
  36 + <u-row justify="space-between" gutter="16rpx" customStyle="margin-bottom: 10px">
  37 + <u-col span="4">
  38 + <view class="box">
  39 + <view class="item review" data-type="review" @click="handelGate">
  40 + <u-image src="/static/img/home/报名审核背景@2x.png" width="220rpx" height="256rpx" />
  41 + <view class="copywriting">
  42 + <text>报名审核</text>
  43 + <text>提供简单描述文字</text>
  44 + </view>
  45 + </view>
  46 + </view>
  47 + </u-col>
  48 + <u-col span="4">
  49 + <view class="box">
  50 + <view class="item signIn" :style="{marginBottom:'16rpx'}" data-type="signin"
  51 + @click="handelGate">
  52 + <u-image src="/static/img/home/学生签到背景@2x.png" width="220rpx" height="120rpx" />
  53 + <view>
  54 + <u-icon size="48rpx" label="学生签到" labelPos="right" labelSize="28rpx"
  55 + labelColor="#1F71DE" name="/static/img/home/icon-学生签到@2x.png"></u-icon>
  56 + <text>提供简单描述文字</text>
  57 + </view>
  58 + </view>
  59 + <view class="item report" data-type="report" @click="handelGate">
  60 + <u-image src="/static/img/home/报告审批背景@2x.png" width="220rpx" height="120rpx" />
  61 + <view>
  62 + <u-icon size="48rpx" label="报告审核" labelPos="right" labelSize="28rpx"
  63 + labelColor="#FD9A03" name="/static/img/home/icon-报名审批@2x.png"></u-icon>
  64 + <text>提供简单描述文字</text>
  65 + </view>
  66 + </view>
  67 + </view>
  68 + </u-col>
  69 + <u-col span="4">
  70 + <view class="box">
  71 + <view class="item signIn" :style="{marginBottom:'16rpx'}" data-type="log"
  72 + @click="handelGate">
  73 + <u-image src="/static/img/home/日志批阅背景@2x.png" width="220rpx" height="120rpx" />
  74 + <view>
  75 + <u-icon size="48rpx" label="日志批阅" labelPos="right" labelSize="28rpx"
  76 + labelColor="#7A7EF9" name="/static/img/home/icon-日志批阅@2x.png"></u-icon>
  77 + <text>提供简单描述文字</text>
  78 + </view>
  79 + </view>
  80 + <view class="item report" data-type="achievement" @click="handelGate">
  81 + <u-image src="/static/img/home/成绩鉴定背景@2x.png" width="220rpx" height="120rpx" />
  82 + <view>
  83 + <u-icon size="48rpx" label="成绩鉴定" labelPos="right" labelSize="28rpx"
  84 + labelColor="#FF6363" name="/static/img/home/icon-成绩鉴定@2x.png"></u-icon>
  85 + <text>提供简单描述文字</text>
  86 + </view>
  87 + </view>
  88 + </view>
  89 + </u-col>
  90 + </u-row>
  91 +
  92 + </view>
  93 +
  94 + <view class="todoList">
  95 + <view class="title">待办事项</view>
  96 + <view v-if="hasLogin">
  97 + <view class="cell">
  98 + <u-cell-group :border="false">
  99 + <u-cell v-if="statistics && statistics.internshipApply && statistics.internshipApply > 0"
  100 + :isLink="true" url="/pages/main/home/registrationReview/registrationReview"
  101 + arrow-direction="right" :rightIconStyle="{fontSize:'24rpx'}" :border="false">
  102 + <view slot="title" class="u-slot-title">
  103 + <view class="u-cell-title">实习申请</view>
  104 + <view class="u-cell-text">
  105 + 您有<text>{{statistics.internshipApply}}</text>条<text>实习申请</text>待处理!</view>
  106 + </view>
  107 + <text slot="value" class="u-slot-value">立即处理</text>
  108 + </u-cell>
  109 +
  110 + <u-cell
  111 + v-if="statistics && statistics.formLogWaitReview && statistics.formLogWaitReview > 0"
  112 + :isLink="true" url="/pages/main/home/logReview/logReview" arrow-direction="right"
  113 + :rightIconStyle="{fontSize:'24rpx'}" :border="false">
  114 + <view slot="title" class="u-slot-title">
  115 + <view class="u-cell-title">日志批阅</view>
  116 + <view class="u-cell-text">
  117 + 您有<text>{{statistics.formLogWaitReview}}</text>篇<text>日志</text>待批阅!</view>
  118 + </view>
  119 + <text slot="value" class="u-slot-value">立即批阅</text>
  120 + </u-cell>
  121 +
  122 + <u-cell v-if="statistics && statistics.reportWaitReview && statistics.reportWaitReview > 0"
  123 + :isLink="true" url="/pages/main/home/reportReview/reportReview" arrow-direction="right"
  124 + :rightIconStyle="{fontSize:'24rpx'}" :border="false">
  125 + <view slot="title" class="u-slot-title">
  126 + <view class="u-cell-title">报告批阅</view>
  127 + <view class="u-cell-text">
  128 + 您有<text>{{statistics.reportWaitReview}}</text>篇<text>实习报告</text>待批阅!</view>
  129 + </view>
  130 + <text slot="value" class="u-slot-value">立即批阅</text>
  131 + </u-cell>
  132 +
  133 + <u-cell
  134 + v-if="statistics && statistics.achievementWaitAppraisal && statistics.achievementWaitAppraisal > 0"
  135 + :isLink="true" url="/pages/main/home/achievementAppraisal/achievementAppraisal"
  136 + arrow-direction="right" :rightIconStyle="{fontSize:'24rpx'}" :border="false">
  137 + <view slot="title" class="u-slot-title">
  138 + <view class="u-cell-title">成绩评定</view>
  139 + <view class="u-cell-text">
  140 + 您有<text>{{statistics.achievementWaitAppraisal}}</text>个<text>成绩</text>待评定!
  141 + </view>
  142 + </view>
  143 + <text slot="value" class="u-slot-value">立即评定</text>
  144 + </u-cell>
  145 +
  146 + </u-cell-group>
  147 + </view>
  148 + </view>
  149 + <view class="no_login" v-else>
  150 + <text>登录后可查看待办事项</text>
  151 + <u-button type="primary" text="登录" color="#06B079" :customStyle="{width:'340rpx'}"
  152 + @click="handelLOgin"></u-button>
  153 + </view>
  154 + </view>
  155 + </view>
4 156 </view>
5 157 </template>
6 158
7 159 <script>
  160 + import {
  161 + mapGetters,
  162 + mapState,
  163 + mapActions
  164 + } from 'vuex'
  165 +
  166 +
  167 + import {
  168 + putTeacherRolesApi,
  169 + getTodoListStatisticsApi,
  170 + } from '@/config/api.js';
8 171
9 172 export default {
10 173 data() {
11 174 return {
12   -
  175 + statistics: {}
13 176 }
14 177 },
15 178
16 179 onLoad() {
17   -
  180 +
18 181 },
19 182
20 183 onShow() {
  184 + if (this.hasLogin) {
  185 + getTodoListStatisticsApi().then(data => {
  186 + if (data) {
  187 + this.statistics = data;
  188 + }
  189 + })
  190 + }
  191 + },
  192 +
  193 + computed: {
  194 + ...mapGetters([
  195 + 'doneRoles',
  196 + ]),
  197 + ...mapState({
  198 + hasLogin: 'hasLogin',
  199 + vuex_user: 'vuex_user',
  200 + teacher: (state) => state.vuex_user.teacher,
  201 + }),
  202 +
21 203
22 204 },
23 205
24 206 methods: {
25 207
  208 + handelLOgin() {
  209 + this.$u.route('/pages/main/my/login/login');
  210 + },
  211 +
  212 + handelChange() {
  213 + let {
  214 + roles = []
  215 + } = this.teacher;
  216 +
  217 + if (roles.length < 2) {
  218 + this.$u.toast('暂无可切换权限')
  219 + } else {
  220 +
  221 + let selectRoles = roles.filter(item => item.id != this.teacher.roleId);
  222 +
  223 + putTeacherRolesApi(this.teacher.id, {
  224 + roleId: selectRoles[0].id
  225 + }).then(data => {
  226 + if (data) {
  227 + console.log(data)
  228 + this.$store.dispatch(`user/getUserInfo`)
  229 + }
  230 + })
  231 + }
  232 + },
  233 +
  234 +
  235 +
  236 + handelGate(even) {
  237 + if (!this.hasLogin) {
  238 + this.$u.route('/pages/main/my/login/login');
  239 + return;
  240 + }
  241 +
  242 + let {
  243 + type = ''
  244 + } = even.currentTarget.dataset;
  245 +
  246 + switch (type) {
  247 + case 'review':
  248 + this.$u.route('/pages/main/home/registrationReview/registrationReview');
  249 + break;
  250 +
  251 + case 'signin':
  252 + this.$u.route('/pages/main/home/studentSignIn/studentSignIn');
  253 + break;
  254 +
  255 + case 'log':
  256 + this.$u.route('/pages/main/home/logReview/logReview');
  257 + break;
  258 +
  259 + case 'report':
  260 + this.$u.route('/pages/main/home/reportReview/reportReview');
  261 + break;
  262 +
  263 + case 'achievement':
  264 + this.$u.route('/pages/main/home/achievementAppraisal/achievementAppraisal');
  265 + break;
  266 +
  267 +
  268 +
  269 +
  270 +
  271 +
  272 + }
  273 +
  274 + },
  275 +
26 276 }
27 277 }
28 278 </script>
29 279
30 280 <style lang="scss" scoped>
  281 + .cell /deep/ .u-cell {
  282 + background-color: #FFFFFF;
  283 + border-radius: 12rpx;
  284 + margin: 0 0 20rpx 0;
  285 +
  286 + // .u-flex {
  287 + // position: relative;
  288 + // top: -2rpx;
  289 + // }
  290 +
  291 + // .u-cell_title {
  292 + // margin: 0 16rpx;
  293 + // color: rgba(0, 0, 0, 0.65);
  294 + // }
  295 + }
  296 +
  297 + .home_box {
  298 + background-color: #F7F7F7;
  299 + min-height: 100%;
  300 + height: auto;
  301 +
  302 + .home {
  303 + width: 690rpx;
  304 + margin: 0 auto;
  305 +
  306 + .bar {
  307 + width: 100%;
  308 + height: 288rpx;
  309 + background-color: #E4F7F4;
  310 + margin: 0 0 34rpx 0;
  311 +
  312 + }
  313 +
  314 + .info {
  315 + .name {
  316 + text {
  317 + font-size: 36rpx;
  318 + line-height: 52rpx;
  319 + color: #202131;
  320 + }
  321 +
  322 + text:last-child {
  323 + font-size: 24rpx;
  324 + line-height: 36rpx;
  325 + color: #909097;
  326 + margin: 0 0 0 12rpx;
  327 + }
  328 + }
  329 +
  330 + .identity {
  331 + margin: 0 0 0 10rpx;
  332 + }
  333 + }
  334 +
  335 + .gate {
  336 + margin-bottom: 50rpx;
  337 +
  338 + .box {
  339 + width: 220rpx;
  340 + height: 256rpx;
  341 +
  342 + .item {
  343 + position: relative;
  344 + width: 220rpx;
  345 + height: 120rpx;
  346 +
  347 + view {
  348 + position: absolute;
  349 + top: 20rpx;
  350 + left: 20rpx;
  351 +
  352 + text {
  353 + display: block;
  354 + margin: 8rpx 0 0 6rpx;
  355 + font-size: 20rpx;
  356 + line-height: 20rpx;
  357 + color: #909097;
  358 + }
  359 + }
  360 + }
  361 +
  362 + .review {
31 363
  364 +
  365 + .copywriting {
  366 + position: absolute;
  367 + top: 56rpx;
  368 + right: 32rpx;
  369 +
  370 + text {
  371 + display: block;
  372 + font-size: 28rpx;
  373 + line-height: 36rpx;
  374 + color: #06B079;
  375 + margin: 0;
  376 + }
  377 +
  378 + text:last-child {
  379 + font-size: 20rpx;
  380 + line-height: 52rpx;
  381 + color: #909097;
  382 + }
  383 +
  384 + }
  385 + }
  386 + }
  387 + }
  388 +
  389 + .todoList {
  390 + .no_login {
  391 + padding: 150rpx 0 0 0;
  392 + text-align: center;
  393 +
  394 + text {
  395 + font-size: 24rpx;
  396 + line-height: 52rpx;
  397 + color: #909097;
  398 + }
  399 + }
  400 +
  401 + .title {
  402 + font-size: 32rpx;
  403 + line-height: 32rpx;
  404 + color: #202131;
  405 + }
  406 +
  407 + .title::before {
  408 + content: "";
  409 + display: inline-block;
  410 + width: 6rpx;
  411 + height: 32rpx;
  412 + background-color: #06B079;
  413 + margin: 0 12rpx 0 0;
  414 + position: relative;
  415 + top: 4rpx;
  416 + border-radius: 8rpx;
  417 + }
  418 +
  419 + .cell {
  420 + margin: 20rpx 0 0 0;
  421 +
  422 + .u-slot-title {
  423 + .u-cell-title {
  424 + font-size: 24rpx;
  425 + line-height: 54rpx;
  426 + color: #909097;
  427 + }
  428 +
  429 + .u-cell-text {
  430 + font-size: 28rpx;
  431 + line-height: 60rpx;
  432 + color: #202131;
  433 +
  434 + text {
  435 + color: #06B079;
  436 + }
  437 + }
  438 + }
  439 +
  440 + .u-slot-value {
  441 + font-size: 24rpx;
  442 + line-height: 36rpx;
  443 + color: #909097;
  444 + }
  445 + }
  446 +
  447 + }
  448 + }
  449 + }
32 450 </style>
... ...
1 1 <template>
2   - <view class="internship">
3   -
  2 + <view class="internship_box">
  3 + <view class="internship" v-if="hasLogin">
  4 +
  5 + <view class="search_box">
  6 + <view class="search">
  7 + <u-search placeholder="请输入学生姓名/学号/手机号" placeholderColor="#C1C1C9" searchIconSize="36" height="64rpx"
  8 + bgColor="#F4F4F4" :showAction="false" shape="square" v-model="keyword" @search="handelSearch">
  9 + </u-search>
  10 + </view>
  11 + </view>
  12 +
  13 + <view class="list_box" v-if="list.length > 0">
  14 + <view class="item" v-for="(item, i) in list" :key="i" @click="handelDetail(item)">
  15 +
  16 + <view class="info">
  17 + <u-image src="/static/img/internship/班级icon@2x.png" width="88rpx" height="88rpx" />
  18 + <view class="title_name">
  19 + <view class="title">
  20 + {{item.startSchoolYear}}
  21 + </view>
  22 + <view class="time">
  23 + <text>{{item.classInfoName}}</text>
  24 + </view>
  25 + </view>
  26 + <view class="num">
  27 + <text>{{item.classInfoTotal || 0}}/{{item.internedTotal || 0}}</text>
  28 + <u-icon :style="{margin:'0 0 0 8rpx'}" name="arrow-right" color="#909097" size="24">
  29 + </u-icon>
  30 + </view>
  31 + </view>
  32 +
  33 + </view>
  34 + <c-loading :loading="loading"></c-loading>
  35 + </view>
  36 + <view v-else class="no_data">
  37 + <c-no-data></c-no-data>
  38 + </view>
  39 +
  40 + </view>
  41 + <view class="no_login" v-else>
  42 + <view class="image">
  43 + <u-image :style="{margin:'0 auto'}" :src="vuex_baseImgUrl+'/internship_bg.png'" width="480rpx"
  44 + height="480rpx"></u-image>
  45 + </view>
  46 + <view class="btn">
  47 + <text>登录后可查看待办事项</text>
  48 + <u-button type="primary" text="登录" color="#06B079" :customStyle="{width:'340rpx'}" @click="handelLOgin">
  49 + </u-button>
  50 + </view>
  51 + </view>
4 52 </view>
5 53 </template>
6 54
7 55 <script>
  56 + import {
  57 + mapGetters,
  58 + mapState,
  59 + mapActions
  60 + } from 'vuex'
  61 +
  62 + import listMixin from "@/common/mixins/list-mixin.js";
  63 +
  64 + import {
  65 + getClassListApi,
  66 + } from '@/config/api.js';
8 67
9 68 export default {
  69 + mixins: [listMixin],
10 70 data() {
11 71 return {
12   -
13   - };
  72 + keyword: '',
  73 + list: [],
  74 + search: {
  75 + keySearch: "",
  76 + },
  77 + }
14 78 },
15 79
16   - onLoad() {},
  80 + onLoad() {
17 81
18   - async onShow() {
19   -
20 82 },
21 83
22   - methods: {
23   -
  84 + onShow() {
  85 + if (this.hasLogin) {
  86 + this.search.keySearch = '';
  87 +
  88 + this.finished = false;
  89 + this.loading = "loadmore";
  90 + this.page = 0;
  91 + this.list = [];
  92 + this._getList();
  93 + }
  94 + },
  95 +
  96 + computed: {
  97 + ...mapGetters([
  98 + 'doneRoles',
  99 + ]),
  100 + ...mapState({
  101 + hasLogin: 'hasLogin',
  102 + vuex_user: 'vuex_user',
  103 + teacher: (state) => state.vuex_user.teacher,
  104 + }),
  105 +
  106 +
24 107 },
25   - };
26   -</script>
  108 +
  109 + methods: {
  110 + timeFormat(timestamp, format = 'yyyy-mm-dd') {
  111 + return timestamp > 0 ? uni.$u.timeFormat(timestamp, format) : '--'
  112 + },
  113 +
  114 + handelLOgin() {
  115 + this.$u.route('/pages/main/my/login/login');
  116 + },
  117 +
  118 + handelSearch(value) {
  119 + this.finished = false;
  120 + this.loading = "loadmore";
  121 + this.page = 0;
  122 + this.list = [];
  123 + this._getList();
  124 + },
  125 +
  126 + handelDetail(record) {
  127 + this.$u.route({
  128 + url: `pages/main/internship/studentList/studentList?classInfoId=${record.classInfoId}`
  129 + })
  130 + },
  131 +
  132 + // scroll-view到底部加载更多
  133 + onreachBottom() {},
  134 + // 搜索
  135 + searchSubmit() {
  136 + // 调用混合搜索
  137 + this._searchData();
  138 + },
  139 + // 模拟后端分页
  140 + async getData(requestParams) {
  141 + const {
  142 + search = {}
  143 + } = requestParams;
  144 +
  145 + let params = {};
  146 + params.pageNumber = requestParams.page + 1;
  147 + params.pageSize = 5;
  148 +
  149 + if (this.keyword) {
  150 + params.keySearch = this.keyword
  151 + }
  152 +
  153 + return await getClassListApi(params);
  154 + },
  155 + // 数据请求(没错就是这么少的代码)
  156 + async _getList() {
  157 + if (this.page == 0) {
  158 + this.list = [];
  159 + }
  160 +
  161 + // 根据实际情况修改自己修改key
  162 + let result = await this.getData({
  163 + page: this.page, // 传入页码
  164 + size: this.size, // 传入每页条数
  165 + search: this.search, // 传入搜索的对象
  166 + });
  167 +
  168 + this.total = result.total;
  169 +
  170 + if (this.list.length == 0 && result.records.length == 0) {
  171 + this.shownoData = false
  172 + } else {
  173 + this.shownoData = true
  174 + }
  175 +
  176 + this.list = this.list.concat(result.records)
  177 + },
  178 +
  179 + }
  180 + }
  181 +</script>
27 182
28 183 <style lang="scss" scoped>
  184 + .internship_box {
  185 + background-color: #F7F7F7;
  186 + min-height: 100%;
  187 + height: auto;
  188 +
  189 + .internship {
  190 + width: 100%;
  191 + margin: 0 auto;
  192 +
  193 + .search_box {
  194 + padding: 36rpx 0;
  195 + background-color: #FFFFFF;
  196 +
  197 + .search {
  198 + width: 690rpx;
  199 + margin: 0 auto;
  200 + }
  201 +
  202 + }
  203 +
  204 + .list_box {
  205 + padding: 0 0 50rpx 0;
  206 +
  207 + .item {
  208 + position: relative;
  209 + width: 630rpx;
  210 + margin: 30rpx auto;
  211 + padding: 30rpx;
  212 + border-radius: 12rpx;
  213 + background-color: #FFFFFF;
  214 +
  215 + .info {
  216 + display: flex;
  217 + flex-flow: row nowrap;
  218 + align-items: center;
  219 + position: relative;
  220 +
  221 + .title_name {
  222 + .title {
  223 + font-size: 24rpx;
  224 + line-height: 36rpx;
  225 + color: #06B079;
  226 + margin: 0 12rpx;
  227 + }
  228 +
  229 + .time {
  230 + padding: 12rpx 0 0 12rpx;
  231 + font-size: 28rpx;
  232 + line-height: 40rpx;
  233 + color: #202131;
  234 + }
  235 + }
  236 +
  237 + .num {
  238 + display: flex;
  239 + flex-flow: row nowrap;
  240 + position: absolute;
  241 + top: 26rpx;
  242 + right: 0rpx;
  243 +
  244 + text {
  245 + font-size: 24rpx;
  246 + line-height: 36rpx;
  247 + color: #909097;
  248 + }
  249 + }
  250 + }
  251 + }
  252 + }
  253 + }
  254 +
  255 + .no_login {
  256 + padding: 180rpx 0 0 0;
  257 + text-align: center;
  258 +
  259 + .image {
  260 + width: 480rpx;
  261 + margin: 0 auto;
  262 + }
  263 +
  264 + .btn {
  265 + position: relative;
  266 + top: -80rpx;
  267 +
  268 + text {
  269 + font-size: 24rpx;
  270 + line-height: 52rpx;
  271 + color: #909097;
  272 +
  273 + }
  274 + }
  275 + }
29 276
30   -
  277 + }
31 278 </style>
... ...
1   -<template>
2   - <view>
  1 +<template>
  2 + <view class="my_box">
  3 + <view class="my" v-if="hasLogin">
  4 + <view class="box-bg">
  5 + <u-image width="100%" height="500rpx" :src="vuex_baseImgUrl+'/myBg.png'" />
  6 + </view>
  7 + <view class="container">
  8 + <view class="avatar">
  9 + <u-image :src="reversedAvatarUrl" shape="circle" width="190rpx" height="190rpx" />
  10 + </view>
  11 + <view class="top">
  12 +
  13 + <view class="title">
  14 + <text class="name">{{reversedName}}</text>
  15 + <view class="info" @click="link('person')">
  16 + <text class="edit-name">{{"个人资料"}}</text>
  17 + <u-icon class="arrowRight" width="20rpx" name="arrow-right" color="#B2B2B2" size="28">
  18 + </u-icon>
  19 + </view>
  20 + </view>
  21 +
  22 + <view class="cell">
  23 + <u-cell-group :border="false">
  24 + <u-cell icon="/static/img/my/school_authen.png" title="账号与安全" :isLink="true"
  25 + url="/pages/main/my/accountSafe/accountSafe" arrow-direction="right"
  26 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  27 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  28 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  29 + </u-cell>
  30 + <u-cell icon="/static/img/my/school_authen.png" title="政策与协议" :isLink="true"
  31 + url="/pages/main/my/policiesAgreement/policiesAgreement" arrow-direction="right"
  32 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  33 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  34 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  35 + </u-cell>
  36 + </u-cell-group>
  37 + </view>
  38 + </view>
  39 +
  40 + <view class="bottom">
  41 + <view class="cell">
  42 + <u-cell-group :border="false">
  43 + <u-cell icon="/static/img/my/school_authen.png" title="版本信息" :isLink="true"
  44 + url="/pages/main/my/versionInfo/versionInfo" arrow-direction="right"
  45 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  46 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  47 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  48 + </u-cell>
  49 + </u-cell-group>
  50 + </view>
  51 + </view>
  52 +
  53 + <view class="btn loginOut">
  54 + <c-button type="cancel" @click="link('loginOut')" text="退出登录">
  55 + </c-button>
  56 + </view>
  57 + </view>
  58 + </view>
  59 +
  60 + <view class="my" v-else>
  61 + <view class="box-bg">
  62 + <u-image width="100%" height="500rpx" :src="vuex_baseImgUrl+'/myBg.png'" />
  63 + </view>
  64 + <view class="container">
  65 + <view class="avatar">
  66 + <u-image src="/static/img/my/default_avatar.png" shape="circle" width="190rpx" height="190rpx" />
  67 + </view>
  68 + <view class="top">
  69 +
  70 + <view class="title">
  71 + <text class="name" @click="handelLOgin">{{`未登录/注册`}}</text>
  72 + <view class="info" @click="handelLOgin">
  73 + <text class="edit-name">{{"个人资料"}}</text>
  74 + <u-icon class="arrowRight" width="20rpx" name="arrow-right" color="#B2B2B2" size="28">
  75 + </u-icon>
  76 + </view>
  77 + </view>
  78 +
  79 + <view class="cell">
  80 + <u-cell-group :border="false">
  81 + <u-cell icon="/static/img/my/school_authen.png" title="账号与安全" :isLink="true"
  82 + url="/pages/main/my/login/login" arrow-direction="right"
  83 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  84 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  85 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  86 + </u-cell>
  87 + <u-cell icon="/static/img/my/school_authen.png" title="政策与协议" :isLink="true"
  88 + url="/pages/main/my/login/login" arrow-direction="right"
  89 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  90 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  91 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  92 + </u-cell>
  93 + </u-cell-group>
  94 + </view>
  95 + </view>
  96 +
  97 + <view class="bottom">
  98 + <view class="cell">
  99 + <u-cell-group :border="false">
  100 + <u-cell icon="/static/img/my/school_authen.png" title="版本信息" :isLink="true"
  101 + url="/pages/main/my/login/login" arrow-direction="right"
  102 + :rightIconStyle="{fontSize:'36rpx'}" :border="false"
  103 + :title-style="{padding:'0 0 0 14rpx', color:'#333', fontSize:'36rpx'}">
  104 + <u-icon slot="icon" size="64" :name="'/static/img/my/school_authen.png'"></u-icon>
  105 + </u-cell>
  106 + </u-cell-group>
  107 + </view>
  108 + </view>
  109 + </view>
  110 + </view>
  111 +
  112 + </view>
  113 +</template>
  114 +
  115 +<script>
  116 + import {
  117 + mapState,
  118 + mapActions
  119 + } from 'vuex'
  120 +
  121 + export default {
  122 + data() {
  123 + return {
  124 + avatarUrl: '',
  125 + }
  126 + },
  127 +
  128 + onLoad() {
  129 +
  130 + },
  131 +
  132 + onShow() {
  133 + if (this.hasLogin) {
  134 + this.getUserInfo()
  135 + }
  136 + },
  137 +
  138 + computed: {
  139 + ...mapState({
  140 + hasLogin: 'hasLogin',
  141 + vuex_user: 'vuex_user',
  142 + vuex_weixinUserInfo: 'vuex_weixinUserInfo',
  143 + teacher: (state) => state.vuex_user.teacher,
  144 + userBasicInfo: (state) => state.vuex_user.userBasicInfo,
  145 + vuex_weixinUserInfo: (state) => state.vuex_weixinUserInfo,
  146 + }),
  147 +
  148 + //name
  149 + reversedName() {
  150 + return (this.userBasicInfo && this.userBasicInfo.name) ? this.userBasicInfo.name : this.vuex_user.username;
  151 + },
  152 +
  153 + //avatar
  154 + reversedAvatarUrl() {
  155 + if (this.userBasicInfo && this.userBasicInfo.avatarUrl) {
  156 + return this.vuex_ossUrlPubilc + '/' + this.userBasicInfo.avatarUrl
  157 + }
  158 + return (this.vuex_weixinUserInfo && this.vuex_weixinUserInfo.avatarUrl) ? this.vuex_weixinUserInfo
  159 + .avatarUrl : '/static/img/my/default_avatar.png';
  160 + }
  161 + },
  162 +
  163 + methods: {
  164 +
  165 + ...mapActions('user', {
  166 + getUserInfo: 'getUserInfo',
  167 + }),
  168 +
  169 + handelLOgin() {
  170 + this.$u.route('/pages/main/my/login/login');
  171 + },
3 172
4   - </view>
5   -</template>
6   -
7   -<script>
8   -
9   - export default {
10   - data() {
11   - return {
12   -
13   - }
14   - },
15   -
16   - onShow() {
  173 + link(type) {
  174 + const {
  175 + dispatch
  176 + } = this.$store;
  177 +
  178 + switch (type) {
  179 +
  180 + case 'person':
  181 + this.$u.route('/pages/main/my/personInfo/personInfo');
  182 + break;
  183 +
  184 + case 'loginOut':
  185 + dispatch(`user/loginOut`);
  186 + break;
  187 +
17 188
18   - },
19   -
20   - methods: {
  189 + }
21 190
22   - }
23   - }
24   -</script>
25   -
26   -<style lang="scss" scoped>
27   -
  191 + },
  192 +
  193 + }
  194 +
  195 +
  196 + }
  197 +</script>
  198 +
  199 +<style lang="scss" scoped>
  200 + .my_box {
  201 + width: 100%;
  202 + height: 100%;
  203 + }
  204 +
  205 + .my {
  206 + width: 100%;
  207 + height: 100%;
  208 + position: relative;
  209 + background-color: #F7F7F7;
  210 +
  211 + .box-bg {}
  212 +
  213 + .container {
  214 + width: 100%;
  215 + position: absolute;
  216 + top: 320rpx;
  217 + left: 0;
  218 + background-color: #F7F7F7;
  219 + padding: 0 0 100rpx 0;
  220 +
  221 +
  222 +
  223 + .avatar {
  224 + position: absolute;
  225 + top: -95rpx;
  226 + left: 32rpx;
  227 + }
  228 +
  229 + .top {
  230 + background: #FFFFFF;
  231 + box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.03);
  232 + border-top-left-radius: 20px;
  233 + border-top-right-radius: 20px;
  234 +
  235 + .title {
  236 + padding: 32rpx 0 0 234rpx;
  237 + display: flex;
  238 + flex-flow: row nowrap;
  239 + justify-content: space-between;
  240 +
  241 +
  242 + .name {
  243 + display: inline-block;
  244 + width: 300rpx;
  245 + overflow: hidden;
  246 + text-overflow: ellipsis;
  247 + white-space: nowrap;
  248 + font-size: 44rpx;
  249 + line-height: 60rpx;
  250 + font-size: 500;
  251 + }
  252 +
  253 + .info {
  254 + display: flex;
  255 + flex-flow: row nowrap;
  256 + padding: 0 30rpx 0 0;
  257 +
  258 + .edit-name {
  259 + float: right;
  260 + font-size: 26rpx;
  261 + line-height: 36rpx;
  262 + padding: 12rpx 6rpx 0 0;
  263 + color: rgba(0, 0, 0, 0.65);
  264 + }
  265 +
  266 + .arrowRight {
  267 + float: right;
  268 + padding: 18rpx 32rpx 0 130rpx;
  269 + }
  270 + }
  271 + }
  272 +
  273 + .cell {
  274 + margin: 62rpx 0 0 0;
  275 + }
  276 +
  277 + .cell /deep/ .u-cell {
  278 + padding: 16rpx 2rpx;
  279 + }
  280 + }
  281 +
  282 + .bottom {
  283 + margin: 16rpx 0 0 0;
  284 + background-color: #FFFFFF;
  285 + }
  286 +
  287 + .loginOut {
  288 + width: 634rpx;
  289 + margin: 48rpx auto 0;
  290 + }
  291 +
  292 +
  293 +
  294 +
  295 + }
  296 +
  297 + .fixed_bottom_btn {
  298 + width: 100%;
  299 + height: 144rpx;
  300 + padding: 24rpx 32rpx;
  301 + background: #FFFFFF;
  302 + position: fixed;
  303 + bottom: 0;
  304 + left: 0;
  305 + z-index: 99;
  306 + border-top: 1rpx solid #F0F0F1;
  307 +
  308 + view {
  309 + display: inline-block;
  310 + }
  311 +
  312 + .left_btn {
  313 + width: 212rpx;
  314 + margin: 0 40rpx 0 0;
  315 + }
  316 +
  317 + .right_btn {
  318 + width: 434rpx;
  319 + }
  320 + }
  321 + }
28 322 </style>
... ...
1 1 {
2   - "projectname": "job-sharing",
  2 + "projectname": "yxly-teacher",
3 3 "setting": {
4 4 "compileHotReLoad": true
5 5 },
... ...
1 1 import Vue from 'vue'
2 2 import Vuex from 'vuex'
3 3 import user from './modules/user'
4   -import position from './modules/position'
  4 +import home from './modules/home'
5 5 Vue.use(Vuex)
6 6
7 7 let lifeData = {};
... ... @@ -14,7 +14,7 @@ try {
14 14 }
15 15
16 16 // 需要永久存储,且下次APP启动需要取出的,在state中的变量名
17   -let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_phone', 'vuex_weixinUserInfo' ];
  17 +let saveStateKeys = ['hasLogin', 'vuex_user', 'vuex_token', 'vuex_phone', 'vuex_weixinUserInfo'];
18 18
19 19 // 保存变量到本地存储中
20 20 const saveLifeData = function(key, value) {
... ... @@ -31,12 +31,13 @@ const saveLifeData = function(key, value) {
31 31 }
32 32 const store = new Vuex.Store({
33 33 modules: {
34   - user,
35   - position,
  34 + user,
  35 + home,
36 36 },
37 37 state: {
38   - vuex_appId: 'wx84b71301436652ce',
39   - vuex_corpId: 'ww4300c59cb9537f9e',//企业ID
  38 + hasLogin: lifeData.hasLogin ? lifeData.hasLogin : false,
  39 + vuex_appId: 'wx6cd2152282abd34c',
  40 + vuex_corpId: 'ww4300c59cb9537f9e', //企业ID
40 41 // 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
41 42 // 加上vuex_前缀,是防止变量名冲突,也让人一目了然
42 43 vuex_user: lifeData.vuex_user ? lifeData.vuex_user : '',
... ... @@ -48,12 +49,12 @@ const store = new Vuex.Store({
48 49 vuex_demo: '绛紫',
49 50 vuex_baseImgUrl: "https://yxlypublic.oss-cn-beijing.aliyuncs.com/WeChat/yxly-teacher",
50 51 vuex_ossUrl: "https://yxly.oss-cn-beijing.aliyuncs.com",
51   - vuex_ossUrlPubilc: "https://yxlypublic.oss-cn-beijing.aliyuncs.com",
52   - vuex_customer_chatUrl:"https://work.weixin.qq.com/kfid/kfc04063cd2d1081221",//企业微信客服
53   - vuex_customer_phone:"",
54   - vuex_applyUrl:"",
55   - vuex_homeUrl:"",
56   - vuex_internshipDetailUrl:"",
  52 + vuex_ossUrlPubilc: "https://yxlypublic.oss-cn-beijing.aliyuncs.com",
  53 + vuex_customer_chatUrl: "https://work.weixin.qq.com/kfid/kfc04063cd2d1081221", //企业微信客服
  54 + vuex_customer_phone: "",
  55 + vuex_applyUrl: "",
  56 + vuex_homeUrl: "",
  57 + vuex_internshipDetailUrl: "",
57 58 // vuex_ossUrl: "https://oss.workai.com.cn",
58 59 vuex_OssInit: {},
59 60 vuex_area: {},
... ... @@ -63,6 +64,26 @@ const store = new Vuex.Store({
63 64 ],
64 65
65 66 },
  67 + getters: {
  68 + doneRoles: state => {
  69 + if (state.vuex_user) {
  70 + const {
  71 + teacher = {}
  72 + } = state.vuex_user;
  73 +
  74 + if (teacher && teacher.roles && teacher.roles.length > 0) {
  75 + let selectRoles = teacher.roles.filter(item => item.id == teacher.roleId);
  76 + return selectRoles[0].name
  77 + } else {
  78 + return ''
  79 + }
  80 + } else {
  81 + return ''
  82 + }
  83 +
  84 +
  85 + },
  86 + },
66 87 mutations: {
67 88 $uStore(state, payload) {
68 89 // 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
... ... @@ -86,7 +107,7 @@ const store = new Vuex.Store({
86 107 },
87 108
88 109 setWenxinUserInfo(state, result) {
89   - state.vuex_weixinUserInfo = result.userInfo;
  110 + state.vuex_weixinUserInfo = result.userInfo;
90 111 uni.$u.vuex('vuex_weixinUserInfo', result.userInfo);
91 112 },
92 113 }
... ...
  1 +import {
  2 + getProjectListApi,
  3 +} from '@/config/api.js';
  4 +
  5 +const state = () => ({
  6 + projectList: [],
  7 +})
  8 +
  9 +const getters = {
  10 +
  11 +}
  12 +
  13 +const actions = {
  14 +
  15 + async getProjectList({
  16 + commit,
  17 + dispatch,
  18 + state
  19 + }, params) {
  20 + const result = await getProjectListApi(params);
  21 + if (result&& result.records) {
  22 + commit('setProjectList', result);
  23 + return result;
  24 + }
  25 + },
  26 +
  27 +}
  28 +
  29 +const mutations = {
  30 +
  31 + setProjectList(state, result) {
  32 + state.projectList = result.records;
  33 + },
  34 +
  35 +}
  36 +
  37 +export default {
  38 + namespaced: true,
  39 + state,
  40 + getters,
  41 + actions,
  42 + mutations
  43 +}
... ...
1   -const state = () => ({
2   - positionDetail: {},
3   - reason: '',
4   -})
5   -
6   -const getters = {
7   - doneReleaseTime: state => {
8   - let {
9   - publishTime = 0
10   - } = state.positionDetail;
11   -
12   - return publishTime > 0 ? uni.$u.timeFormat(publishTime, 'mm/dd') : '';
13   - },
14   -
15   - doneSalary: state => {
16   - let {
17   - wageType = '', wageLower = '', wageUpper = '',
18   - } = state.positionDetail;
19   -
20   - let wageTypeOption = {
21   - "monthly": "月",
22   - "daily": "日",
23   - "hourly": "时",
24   - "annual": "年"
25   - };
26   -
27   - let salary = '';
28   -
29   - switch (wageType) {
30   -
31   - case 'negotiable':
32   - salary = '薪资面议'
33   - break;
34   -
35   - default:
36   - if (wageLower == wageUpper) {
37   - salary = `${wageLower}/${wageTypeOption[wageType]}`
38   - } else {
39   - salary = `${wageLower}~${wageUpper}/${wageTypeOption[wageType]}`
40   - }
41   - break;
42   - }
43   -
44   - return salary;
45   - },
46   -
47   - doneAddress: state => {
48   - let {
49   - province = '', district = '',
50   - } = state.positionDetail;
51   -
52   - return `${province}/${district}`;
53   - },
54   -
55   - doneWorkHour: state => {
56   - let {
57   - attendanceType = '', attendanceDay = '',
58   - } = state.positionDetail;
59   -
60   - let attendanceTypeOption = {
61   - "week": "周",
62   - "month": "月",
63   - "year": "年"
64   - };
65   -
66   - return attendanceType && attendanceDay ? `${attendanceDay}/${attendanceTypeOption[attendanceType]}` :
67   - "";
68   - },
69   -
70   - doneProperty: state => {
71   - let {
72   - property = '',
73   - } = state.positionDetail;
74   -
75   - let propertyOptions = {
76   - "part_time": "兼职",
77   - "internship": "实习",
78   - "full_time": "全职",
79   - "other": "其他"
80   - }
81   -
82   - return propertyOptions[property];
83   - },
84   -
85   - doneCategory: state => {
86   - let {
87   - category = '',
88   - } = state.positionDetail;
89   -
90   - let categoryOptions = {
91   - "0": "不限",
92   - "manufacture": "智能制造",
93   - "preschool": "学前教育",
94   - "healthy": "智慧康养",
95   - "software": "大数据与软件",
96   - "other": "其他",
97   - }
98   -
99   - return categoryOptions[category];
100   - },
101   -
102   - doneDegree: state => {
103   - let {
104   - degreeRequires = '',
105   - } = state.positionDetail;
106   -
107   - let degreeOptions = {
108   - "0": "不限",
109   - "1": "初中",
110   - "2": "高中",
111   - "3": "中专/技校",
112   - "4": "大专",
113   - "5": "本科",
114   - "6": "硕士",
115   - "7": "博士",
116   - "8": "MBA/EMBA"
117   - }
118   -
119   - return degreeRequires ? degreeOptions[degreeRequires] : "";
120   - },
121   -
122   - doneWorkExp: state => {
123   - let {
124   - workExp = '',
125   - } = state.positionDetail;
126   -
127   - let workExpOptions = {
128   - "0": "不限",
129   - "1": "在校生",
130   - "2": "应届生",
131   - "3": "1年以内",
132   - "4": "1-3年",
133   - "5": "3-5年",
134   - "6": "5-10年",
135   - "7": "10年以上",
136   - }
137   -
138   - return workExpOptions[workExp];
139   - },
140   -
141   - doneFlag: state => {
142   - let {
143   - flag = '',
144   - } = state.positionDetail;
145   -
146   -
147   - if(flag) {
148   - return flag.split(',');
149   - } else {
150   - return [];
151   - }
152   - },
153   -
154   -}
155   -
156   -const actions = {
157   -
158   - async getPositionDetail({
159   - commit,
160   - dispatch,
161   - state
162   - }, params) {
163   - const result = await uni.$u.api.getJobDetailApi(params);
164   - if (result) {
165   - commit('setPositionDetail', result);
166   - return result;
167   - }
168   - },
169   -
170   -}
171   -
172   -const mutations = {
173   -
174   - setPositionDetail(state, result) {
175   - state.positionDetail = result;
176   - },
177   -
178   - setPositionReason(state, result) {
179   - state.reason = result;
180   - },
181   -
182   -}
183   -
184   -export default {
185   - namespaced: true,
186   - state,
187   - getters,
188   - actions,
189   - mutations
190   -}
1 1 import {
2   - postTokenApi,
3   - getUserInfoApi,
4   - } from '@/config/api.js';
5   -
6   - const state = () => ({
7   - openid: '',
8   - isReg: '',
9   - id: '',
10   - name: '',
11   - number: '',
12   - password: '',
13   - phone: '',
14   - status: '',
15   - type: '',
16   - username: '',
17   - userBasicInfo: {},
18   -
19   - })
20   -
21   - const getters = {
22   - // doneOpenid: (state, getters, rootState) => {
23   - // return state.openid
24   - // },
25   - }
26   -
27   - // actions
28   - const actions = {
29   -
30   - async login({
31   - commit,
32   - dispatch,
33   - state
34   - }, params) {
35   - const login_result = await postTokenApi({
36   - ...params
37   - }, {
38   - custom: {
39   - auth: false
40   - }
41   - });
42   -
43   - console.log(login_result)
44   -
45   - if (login_result) {
46   -
47   - let vuex_token = `Bearer ${login_result.access_token}`
48   - await uni.$u.vuex('vuex_token', vuex_token);
49   - await uni.$u.vuex('vuex_phone', login_result.phone);
50   -
51   - switch (login_result.status) {
52   -
53   - case 'not_reg': //未注册
  2 + postTokenApi,
  3 + getUserInfoApi,
  4 +} from '@/config/api.js';
  5 +
  6 +const state = () => ({
  7 + openid: '',
  8 + isReg: '',
  9 + id: '',
  10 + name: '',
  11 + number: '',
  12 + password: '',
  13 + phone: '',
  14 + status: '',
  15 + type: '',
  16 + username: '',
  17 + userInfo: {},
  18 + userBasicInfo: {},
  19 +
  20 +})
  21 +
  22 +const getters = {
  23 +
  24 +}
  25 +
  26 +// actions
  27 +const actions = {
  28 +
  29 + async login({
  30 + commit,
  31 + dispatch,
  32 + state
  33 + }, params) {
  34 + const login_result = await postTokenApi({
  35 + ...params
  36 + }, {
  37 + custom: {
  38 + auth: false
  39 + }
  40 + });
  41 +
  42 + if (login_result) {
  43 +
  44 + await commit('setLogin', login_result);
  45 +
  46 + switch (login_result.status) {
  47 +
  48 + case 'not_reg': //未注册
  49 + uni.$u.route({
  50 + url: '/pages/student/my/login/login',
  51 + type: 'reLaunch',
  52 + });
  53 + break;
  54 +
  55 + case 'annulled': //已注销
  56 + uni.$u.route({
  57 + url: '/pages/student/my/written-off/written-off',
  58 + type: 'navigateTo',
  59 + });
  60 + break;
  61 +
  62 + case 'annulling': //注销中
  63 + uni.$u.route({
  64 + url: '/pages/student/my/freezing/freezing',
  65 + type: 'navigateTo',
  66 + });
  67 + break;
  68 +
  69 + case 'active': //已注册
  70 + const userInfo = await dispatch(`getUserInfo`);
  71 + if (userInfo?.teacher) {
54 72 uni.$u.route({
55   - url: '/pages/student/my/login/login',
56   - type: 'reLaunch',
57   - });
58   - break;
  73 + url: 'pages/tabBar/home/home',
  74 + type: 'switchTab',
  75 + params: {
59 76
60   - case 'annulled': //已注销
61   - uni.$u.route({
62   - url: '/pages/student/my/written-off/written-off',
63   - type: 'navigateTo',
64   - });
65   - break;
  77 + }
  78 + })
  79 + }
66 80
67   - case 'annulling': //注销中
68   - uni.$u.route({
69   - url: '/pages/student/my/freezing/freezing',
70   - type: 'navigateTo',
71   - });
72   - break;
73   -
74   - case 'active': //已注册
75   - const userInfo = await dispatch(`getUserInfo`);
76   -
77   - // if (userInfo) {
78   - // const {
79   - // student = {}
80   - // } = userInfo;
81   - // if (student && JSON.stringify(student) != '{}' && student.status == 'verified') {
82   - // uni.$u.route({
83   - // url: 'pages/student/tabBar/internship/internship',
84   - // type: 'switchTab',
85   - // params: {
86   -
87   - // }
88   - // })
89   -
90   - // } else {
91   - // uni.$u.route({
92   - // url: `/pages/student/my/student-status-certification/student-status-certification`,
93   - // type: 'reLaunch',
94   - // params: {
95   -
96   - // }
97   - // })
98   - // }
99   - // }
100   -
101   - break;
102   - }
103   -
104   - return login_result;
  81 + break;
105 82 }
106   -
107   -
108   - },
109   -
110   - async loginOut({
111   - commit,
112   - dispatch,
113   - state
114   - }, params) {
115   -
116   - await uni.$u.vuex('vuex_user', {});
117   - await uni.$u.vuex('vuex_token', {});
118   - await uni.setStorageSync('lifeData', {});
119   -
120   - uni.$u.route('/pages/student/my/login/login');
121   - },
122   -
123   - async getUserInfo({
124   - commit,
125   - dispatch,
126   - state
127   - }, params) {
128   -
129   - const userInfo = await getUserInfoApi();
130   -
131   - uni.$u.vuex('vuex_user', userInfo);
132   -
133   - return userInfo;
134   - },
135   - }
136   -
137   - // mutations
138   - const mutations = {
139   -
140   - setUserInfo(state, userInfo) {
141   - state.id = userInfo.id;
142   - state.name = userInfo.name;
143   - state.phone = userInfo.phone;
144   - state.username = userInfo.username;
145   - state.userBasicInfo = userInfo.userBasicInfo;
146   - },
147   - }
148   -
149   - export default {
150   - namespaced: true,
151   - state,
152   - getters,
153   - actions,
154   - mutations
155   - }
  83 + }
  84 +
  85 +
  86 + },
  87 +
  88 + async loginOut({
  89 + commit,
  90 + dispatch,
  91 + state
  92 + }, params) {
  93 +
  94 + await commit('setLoginOut', {});
  95 + uni.$u.route('/pages/main/my/login/login');
  96 + },
  97 +
  98 + async getUserInfo({
  99 + commit,
  100 + dispatch,
  101 + state
  102 + }, params) {
  103 +
  104 + const result = await getUserInfoApi();
  105 +
  106 + commit('setUserInfo', result);
  107 +
  108 + uni.$u.vuex('vuex_user', result);
  109 +
  110 + return result;
  111 + },
  112 +}
  113 +
  114 +// mutations
  115 +const mutations = {
  116 +
  117 + setLogin(state, result) {
  118 + let vuex_token = `Bearer ${result.access_token}`
  119 + uni.$u.vuex('vuex_token', vuex_token);
  120 + uni.$u.vuex('vuex_phone', result.phone);
  121 + uni.$u.vuex('hasLogin', true);
  122 + },
  123 +
  124 + setLoginOut(state, result) {
  125 + uni.$u.vuex('vuex_token', '');
  126 + uni.$u.vuex('vuex_phone', '');
  127 + uni.$u.vuex('vuex_user', {});
  128 + uni.$u.vuex('hasLogin', false);
  129 + },
  130 +
  131 + setUserInfo(state, result) {
  132 + state.userInfo = result;
  133 + },
  134 +
  135 +
  136 +
  137 +}
  138 +
  139 +export default {
  140 + namespaced: true,
  141 + state,
  142 + getters,
  143 + actions,
  144 + mutations
  145 +}
... ...
  1 +<template>
  2 + <view>
  3 + <view class="mi_calendar">
  4 + <view class="top-bar">
  5 + <i class="top-change-month" @click="changeMonth('prev')" />
  6 + <view class="top-bar-ym">{{ y }}.{{ m < 10 ? `0${m}` : m }}</view>
  7 + <i v-show="m == new Date().getMonth() + 1" :style="{ opacity: '0.3' }"
  8 + class="top-change-month next-month" />
  9 + <i v-show="m != new Date().getMonth() + 1" class="top-change-month next-month"
  10 + @click="changeMonth('next')" />
  11 + </view>
  12 + <view class="week">
  13 + <view class="week-day" v-for="(item, index) in weekDay" :key="index">{{ item }}</view>
  14 + </view>
  15 + <view :class="{ hide: !monthOpen }" class="content" :style="{ height: height }">
  16 + <view :style="{ top: positionTop + 'rpx' }" class="days">
  17 + <view :class="['item', { nolm: !item.lm }]" v-for="(item, index) in dates" :key="index">
  18 + <view class="day" :key="`${item.year}-${item.month + 1}-${item.date}`"
  19 + @click="selectOne(item, $event)"
  20 + :class="{ choose: choose == `${item.year}-${item.month}-${item.date}` }">
  21 + {{ item.date }}
  22 + </view>
  23 + <view class="flag_icon late" v-if="filterType('LEAVE', item.year, item.month, item.date)">
  24 + </view>
  25 + <view class="flag_icon truancy"
  26 + v-if="filterType('SUSPENSION', item.year, item.month, item.date)"></view>
  27 + <view class="flag_icon normal" v-if="filterType('NORMAL', item.year, item.month, item.date)">
  28 + </view>
  29 + <!-- <view class="today-text" v-if="isToday(item.year, item.month, item.date)">{{ text.today }}</view> -->
  30 + </view>
  31 + </view>
  32 + </view>
  33 + </view>
  34 + <!-- <view class="type-check">
  35 + <view class="label" v-for="(item, index) in statusText" :key="index"><i></i><text>{{ item }}</text></view>
  36 + </view> -->
  37 + </view>
  38 +</template>
  39 +
  40 +<script>
  41 + export default {
  42 + name: 'mi-calendar',
  43 + props: {
  44 + // 第一列星期几
  45 + weekstart: {
  46 + type: Number,
  47 + default: 1
  48 + },
  49 + // 请假日期
  50 + leaveDateList: {
  51 + type: Array,
  52 + default: () => []
  53 + },
  54 + // 停课日期
  55 + suspensionDateList: {
  56 + type: Array,
  57 + default: () => []
  58 + },
  59 + // 正常考勤日期
  60 + normalDateList: {
  61 + type: Array,
  62 + default: () => []
  63 + },
  64 + // 是否展开 暂未实现
  65 + open: {
  66 + type: Boolean,
  67 + default: true
  68 + }
  69 + },
  70 + data() {
  71 + return {
  72 + statusText: ['出勤', '请假', '停课'],
  73 + text: {
  74 + year: '年',
  75 + month: '月',
  76 + week: ['一', '二', '三', '四', '五', '六', '日'],
  77 + today: '今'
  78 + },
  79 + y: new Date().getFullYear(), // 年
  80 + // m: new Date().getMonth() >= 10 ? new Date().getMonth() + 1 : `0${new Date().getMonth() + 1}`, // 月
  81 + m: new Date().getMonth() + 1,
  82 + dates: [], // 当前月日期集合
  83 + positionTop: 0,
  84 + monthOpen: true,
  85 + choose: ''
  86 + };
  87 + },
  88 + created() {
  89 + this.dates = this.monthDay(this.y, this.m);
  90 + // console.log(this.y, this.m);
  91 + // !this.open && this.trgWeek();
  92 + },
  93 + mounted() {
  94 + const date = new Date();
  95 + const y = date.getFullYear();
  96 + const m = date.getMonth() + 1;
  97 + const d = date.getDate();
  98 + this.choose = `${y}-${m}-${d}`;
  99 + },
  100 + computed: {
  101 + // 顶部星期栏目
  102 + weekDay() {
  103 + return this.text.week.slice(this.weekstart - 1).concat(this.text.week.slice(0, this.weekstart - 1));
  104 + },
  105 + height() {
  106 + return (this.dates.length / 7) * 80 + 'rpx';
  107 + }
  108 + },
  109 + methods: {
  110 + // 获取当前月份天数
  111 + monthDay(y, m) {
  112 + let firstDayOfMonth = new Date(y, m - 1, 1).getDay(); // 当月第一天星期几
  113 + let lastDateOfMonth = new Date(y, m, 0).getDate(); // 当月最后一天
  114 + let lastDayOfLastMonth = new Date(y, m - 1, 0).getDate(); // 上一月的最后一天
  115 + let dates = []; // 所有渲染日历
  116 + let weekstart = this.weekstart == 7 ? 0 : this.weekstart; // 方便进行日期计算,默认星期从0开始
  117 + let startDay = (() => {
  118 + // 周初有几天是上个月的
  119 + if (firstDayOfMonth == weekstart) {
  120 + return 0;
  121 + } else if (firstDayOfMonth > weekstart) {
  122 + return firstDayOfMonth - weekstart;
  123 + } else {
  124 + return 7 - weekstart + firstDayOfMonth;
  125 + }
  126 + })();
  127 + let endDay = 7 - ((startDay + lastDateOfMonth) % 7); // 结束还有几天是下个月的
  128 + for (let i = 1; i <= startDay; i++) {
  129 + const date = lastDayOfLastMonth - startDay + i;
  130 + dates.push({
  131 + date,
  132 + day: weekstart + i - 1 || 7,
  133 + month: m - 1 >= 0 ? m - 1 : 12,
  134 + year: m - 1 >= 0 ? y : y - 1
  135 + });
  136 + }
  137 + for (let j = 1; j <= lastDateOfMonth; j++) {
  138 + dates.push({
  139 + date: j,
  140 + day: (j % 7) + firstDayOfMonth - 1 || 7,
  141 + month: m,
  142 + year: y,
  143 + lm: true
  144 + });
  145 + }
  146 + for (let k = 1; k <= endDay; k++) {
  147 + dates.push({
  148 + date: k,
  149 + day: (lastDateOfMonth + startDay + weekstart + k - 1) % 7 || 7,
  150 + month: m + 1 <= 11 ? m + 1 : 0,
  151 + year: m + 1 <= 11 ? y : y + 1
  152 + });
  153 + }
  154 + return dates;
  155 + },
  156 + getFormatString(m) {
  157 + return m >= 10 ? m : `0${m}`;
  158 + },
  159 + filterType(type, y, m, d) {
  160 + const opt = {
  161 + LEAVE: 'leaveDateList', // 请假
  162 + SUSPENSION: 'suspensionDateList', // 停课
  163 + NORMAL: 'normalDateList' // 出勤
  164 + };
  165 + const list = opt[type];
  166 + const dataList = this[list];
  167 + let flag = false;
  168 + for (let i = 0; i < dataList.length; i++) {
  169 + const M = this.getFormatString(m);
  170 + const D = this.getFormatString(d);
  171 + const dy = `${y}-${M}-${D}`;
  172 + if (dataList[i] == dy) {
  173 + flag = true;
  174 + break;
  175 + }
  176 + }
  177 + return flag;
  178 + },
  179 + isToday(y, m, d) {
  180 + let date = new Date();
  181 + return y == date.getFullYear() && m == date.getMonth() + 1 && d == date.getDate();
  182 + },
  183 + // 切换成周模式
  184 + trgWeek() {
  185 + this.monthOpen = !this.monthOpen;
  186 + if (this.monthOpen) {
  187 + this.positionTop = 0;
  188 + } else {
  189 + let index = -1;
  190 + this.dates.forEach((i, x) => {
  191 + this.isToday(i.year, i.month, i.date) && (index = x);
  192 + });
  193 + this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 80;
  194 + }
  195 + },
  196 + // 点击回调
  197 + selectOne({
  198 + year,
  199 + month,
  200 + date
  201 + }, event) {
  202 + let date_time = `${year}-${this.getFormatString(month)}-${this.getFormatString(date)}`;
  203 + if (month != this.m) {
  204 + console.log('不在可选范围内');
  205 + return false;
  206 + }
  207 + this.choose = `${year}-${month}-${date}`;
  208 + this.$emit('change', date_time);
  209 + },
  210 + // 月份切换
  211 + changeMonth(action) {
  212 + if (action === 'next') {
  213 + if (this.m == 12) {
  214 + this.m = 1;
  215 + this.y++;
  216 + } else {
  217 + this.m++;
  218 + }
  219 + } else {
  220 + if (this.m == 1) {
  221 + this.m = 12;
  222 + this.y--;
  223 + } else {
  224 + this.m--;
  225 + }
  226 + }
  227 + this.dates = this.monthDay(this.y, this.m);
  228 + this.$emit(`changeMonth`, this.y, this.m);
  229 + }
  230 + }
  231 + };
  232 +</script>
  233 +
  234 +<style lang="scss" scoped>
  235 + $working: #80b2ff;
  236 + $leave: #ffcd3c;
  237 + $suspend: #f46864;
  238 +
  239 + .mi_calendar {
  240 + color: #1a1a1a;
  241 + font-size: 28rpx;
  242 + text-align: center;
  243 + padding: 30rpx 10rpx;
  244 + margin: 20rpx 30rpx;
  245 + background-color: #fff;
  246 + border-radius: 12rpx;
  247 + box-shadow: 0 3rpx 32rpx 0rpx rgba(0, 0, 0, 0.1);
  248 + overflow: hidden;
  249 +
  250 + .top-bar {
  251 + display: flex;
  252 + height: 80rpx;
  253 + align-items: center;
  254 + justify-content: center;
  255 +
  256 + .top-bar-ym {
  257 + font-size: 32rpx;
  258 + height: 80rpx;
  259 + width: 120rpx;
  260 + line-height: 80rpx;
  261 + }
  262 +
  263 + .top-change-month {
  264 + width: 23rpx;
  265 + height: 13rpx;
  266 + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAaCAYAAADIUm6MAAAAAXNSR0IArs4c6QAAA95JREFUWEfN1ktsG0UYB/D/Z+9sQlWgvCVOHDhEtpeGRogDr0OqtLQU75YaRIsgBwpUIEBFaSsVqkKpeBQQiPdLBESLwDTeJS0vNQdAFQIpEGltKwcOnJBKBLRVSeOdtT80Jo2cYI8fcVrmZu1/vu/n2dnZpVQK0XDc2M5M/QDOI+JvOWo85I5N/Yr/wbC7Oy+jYvgSM10P4C8iHjS6wt1kx80nQPzYLCPxb1FEevf7wfiZtN9imV1FlEbAdOksB9MushNiAsCFVYBHiiXqHc4HuTOBd64wE1ziQwAuqdJ/QsH/BrCoBm4CJfS5eTl2OvF2THQjgq8BXFSj7yTZcbEXhPUa2J8g9Lm+HD0deNsSPeAy+vya/Rj7yOnCBWyIEQBLNbCjXMJKLy9/WEh8Miaupgi+BLBE02eMQrmcVGAar/7lMs2E4xHmVUO58PBC4J24cS0THQRwjqb+TxTKvsw4/ijD1bC7sQShUPirNBNPEPFNGT/8pp14xzJuYKYDABZr6v4IQ65wx3BUZWbg6keqB+cGBXGQgGs0BSaZOOn5oXri5z2SlrGcmDzNAQEGDpsdcnV6FMdONZwFL+NjWCxJfA7CdRrVSWJem8mFaj+2PJy4sZKJhgCcpXkQvxMsV6XzOFGZ+Q9cXVzTg0XRKfEZCL0aVcAcWeflCsOtyJPxjjVEpU8BmBr0SLFT3jw8ism5marwGXzBHAJ4hQ5PoNsz2UCtWsPDSZhrGfyRFg36SpwdOOnvcbJa4ZpwFb7xcnSYneZ+Aq/WqEKANrjZ4JNG5HbCvBXgvQCM2nk6UJgK1n3xCwq1Mlr49J43ZcT4GCBbAysC1O9mgw91eDth3gHwIIBo7Ry7ohTels4j0NWqC1eT7+mB+L0g1CqldHgmbPR8+V61jG2JfjDe0aORvrhDbnhrFLLe3WsIXl75FKIyLz6o83nATNjk+fLNysZJS9xLjNfnHr+zcIx9IibvTKdRrIdW1xuGz+DHxbtg3KUpziA86PryFZVx4uJ+JrxcBz0oYvLuRtFNw9WEnUDkZ0u8QYyNWjx4gAjMTM/p0Ex4+0pf3rcTKDWy0qcyTa14RWH1OfwqgE3NNKuSfc3NygcA9XJsbrQKL98t2xIvgPFwcy2n04QXXV9ubgXd0laZi0wmzGcJPNAMnkF7vGywpZk5c7PzWfGZWsmE+SSBtzcCYdBuLxs82khWl2kLvHx6WMYOZnpcCyLe4frhrvmi27JVKhGOZWxjpqeqwZh4m+eHz7QD3Xa4KmgnjEcA2lNxBDLAA242fL5d6AWBl/H/vt6fLjdgbM3k5PvtRKta/wD9BFRsxb0ftAAAAABJRU5ErkJggg==') no-repeat bottom center;
  267 + background-size: 23rpx 13rpx;
  268 + transform: rotate(90deg);
  269 + margin: 0 30rpx;
  270 + }
  271 +
  272 + .next-month {
  273 + transform: rotate(-90deg);
  274 + }
  275 + }
  276 +
  277 + .week {
  278 + display: flex;
  279 + align-items: center;
  280 + height: 80rpx;
  281 + line-height: 80rpx;
  282 +
  283 + view {
  284 + flex: 1;
  285 + }
  286 +
  287 + .week-day {
  288 + font-size: 26rpx;
  289 + color: #1a1a1a;
  290 + }
  291 + }
  292 +
  293 + .content {
  294 + position: relative;
  295 + overflow: hidden;
  296 + transition: height 0.4s ease;
  297 +
  298 + .days {
  299 + transition: top 0.3s;
  300 + display: flex;
  301 + align-items: center;
  302 + flex-wrap: wrap;
  303 + position: relative;
  304 +
  305 + .item {
  306 + position: relative;
  307 + display: block;
  308 + height: 80rpx;
  309 + line-height: 80rpx;
  310 + width: calc(100% / 7);
  311 +
  312 + .day {
  313 + font-style: normal;
  314 + display: inline-block;
  315 + vertical-align: middle;
  316 + width: 60rpx;
  317 + height: 60rpx;
  318 + line-height: 60rpx;
  319 + overflow: hidden;
  320 + border-radius: 50%;
  321 +
  322 + &.choose {
  323 + background: #06B079;
  324 + color: #FFF;
  325 + }
  326 + }
  327 +
  328 + &.nolm {
  329 + color: #999;
  330 + opacity: 0.3;
  331 + }
  332 +
  333 + .flag_icon {
  334 + bottom: 0;
  335 + left: 50%;
  336 + font-style: normal;
  337 + width: 12rpx;
  338 + height: 12rpx;
  339 + border-radius: 6rpx;
  340 + position: absolute;
  341 + margin-left: -6rpx;
  342 + pointer-events: none;
  343 + }
  344 +
  345 + .late {
  346 + background: #ffcd3c;
  347 + }
  348 +
  349 + .truancy {
  350 + background: #06B079;
  351 + }
  352 +
  353 + .normal {
  354 + background: #80b2ff;
  355 + }
  356 +
  357 + .today-text {
  358 + position: absolute;
  359 + font-size: 20rpx;
  360 + font-weight: normal;
  361 + width: 20rpx;
  362 + height: 20rpx;
  363 + line-height: 20rpx;
  364 + right: 0;
  365 + top: 10rpx;
  366 + color: #fff;
  367 + }
  368 + }
  369 + }
  370 + }
  371 +
  372 + .hide {
  373 + height: 80rpx !important;
  374 + }
  375 +
  376 + .weektoggel {
  377 + width: 80rpx;
  378 + height: 40rpx;
  379 + margin: 10rpx auto 0;
  380 +
  381 + &.down {
  382 + transform: rotate(180deg);
  383 + }
  384 + }
  385 + }
  386 +
  387 + .type-check {
  388 + overflow: hidden;
  389 + margin: 0 24rpx;
  390 + text-align: right;
  391 +
  392 + .label {
  393 + display: inline-block;
  394 + margin-right: 24rpx;
  395 +
  396 + i {
  397 + display: inline-block;
  398 + width: 10rpx;
  399 + height: 10rpx;
  400 + border-radius: 50%;
  401 + vertical-align: middle;
  402 + margin-right: 10rpx;
  403 + }
  404 +
  405 + text {
  406 + color: #1a1a1a;
  407 + font-size: 26rpx;
  408 + }
  409 +
  410 + &:nth-child(1) {
  411 + i {
  412 + background-color: $working;
  413 + }
  414 + }
  415 +
  416 + &:nth-child(2) {
  417 + i {
  418 + background-color: $leave;
  419 + }
  420 + }
  421 +
  422 + &:nth-child(3) {
  423 + i {
  424 + background-color: $suspend;
  425 + }
  426 + }
  427 + }
  428 + }
  429 +</style>
... ...
  1 +
  2 +## mi-calendar 使用帮助
  3 +
  4 +### 快速开始
  5 +使用 uni_modules 安装 (目前仅支持 uni_modules)
  6 +
  7 +下载该文件后,放到uni_modules文件下,然后直接页面使用。
  8 +
  9 +<mi-calendar :leaveDateList="[`2022-1-2`,`2022-1-4`]" :suspensionDateList="[`2022-01-05`]" :normalDateList="[`2022-1-3`]"></mi-calendar>
  10 +
  11 +## leaveDateList
  12 +请假日期
  13 +## suspensionDateList
  14 +停课日期
  15 +## normalDateList
  16 +正常考勤日期
  17 +
  18 +## change 切换日期
  19 +`@change="change"`
  20 +```
  21 +change(date){
  22 + console.log(date); // 日期 eg:'2022-01-01'
  23 +}
  24 +```
  25 +
  26 +## changeMonth 切换月份
  27 +`@change="change"`
  28 +```
  29 +changeMonth(year, month){
  30 + console.log(year, month); // 日期 eg:2022, 6
  31 +}
  32 +```
  33 +
  34 +
... ...
  1 +{
  2 + "id": "mi-calendar",
  3 + "displayName": "考勤日历",
  4 + "version": "1.0.0",
  5 + "description": "考勤日历",
  6 + "repository": "https://github.com/quyapeng/mi-calendar",
  7 + "keywords": [
  8 + "考勤",
  9 + "日历",
  10 + "教学"
  11 + ],
  12 + "dcloudext": {
  13 + "category": [
  14 + "前端组件",
  15 + "通用组件"
  16 + ]
  17 + }
  18 +}
... ...
... ... @@ -34,7 +34,7 @@
34 34 'background-color': disabled ? 'transparent' : '#fff',
35 35 }"
36 36 v-if="count"
37   - >{{ innerValue.length }}/{{ maxlength }}</text
  37 + >{{ innerValue.length || 0 }}/{{ maxlength }}</text
38 38 >
39 39 </view>
40 40 </template>
... ...
注册登录 后发表评论