Commit 6953c5ab30b15edf472381f03d984f4cb42b7cf7

Authored by sanmu
1 parent 20bd399f

feat: 开发完成

Showing 45 changed files with 1652 additions and 364 deletions
src/api/demo/table.ts
1 import { defHttp } from '/@/utils/http/axios'; 1 import { defHttp } from '/@/utils/http/axios';
2 import { DemoParams, DemoListGetResultModel } from './model/tableModel'; 2 import { DemoParams, DemoListGetResultModel } from './model/tableModel';
3 -import { find } from 'lodash-es';  
4 -import { FIELDS_BASE_INFO } from '../../views/project/order/constant';  
5 3
6 enum Api { 4 enum Api {
7 DEMO_LIST = '/table/getDemoList', 5 DEMO_LIST = '/table/getDemoList',
@@ -39,8 +37,8 @@ export const demoApproveListApi = async (params: DemoParams) => { @@ -39,8 +37,8 @@ export const demoApproveListApi = async (params: DemoParams) => {
39 item.fields = []; 37 item.fields = [];
40 Object.entries(item.fieldInfos.baseFields).map(([key, value]) => { 38 Object.entries(item.fieldInfos.baseFields).map(([key, value]) => {
41 if (value === 'UN_LOCKED') { 39 if (value === 'UN_LOCKED') {
42 - const obj = find(FIELDS_BASE_INFO, { field: key });  
43 - item.fields.push(obj?.label); 40 + // const obj = find(FIELDS_BASE_INFO, { field: key });
  41 + // item.fields.push(obj?.label);
44 } 42 }
45 }); 43 });
46 item.fields = item.fields.join(','); 44 item.fields = item.fields.join(',');
src/api/project/order.ts
@@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios'; @@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
3 import { useUserStoreWithOut } from '/@/store/modules/user'; 3 import { useUserStoreWithOut } from '/@/store/modules/user';
4 import { useOrderStoreWithOut } from '/@/store/modules/order'; 4 import { useOrderStoreWithOut } from '/@/store/modules/order';
5 import { formatToDate } from '/@/utils/dateUtil'; 5 import { formatToDate } from '/@/utils/dateUtil';
  6 +import message from '/@/views/form-design/utils/message';
6 7
7 enum Api { 8 enum Api {
8 ORDER_CREATE = '/order/erp/order/add', 9 ORDER_CREATE = '/order/erp/order/add',
@@ -19,11 +20,37 @@ enum Api { @@ -19,11 +20,37 @@ enum Api {
19 DICT_LIST = '/order/erp/dictionary/list_by_page', 20 DICT_LIST = '/order/erp/dictionary/list_by_page',
20 21
21 ANALYSIS = '/order/erp/profit/analysis', 22 ANALYSIS = '/order/erp/profit/analysis',
  23 + GRAVITY = '/order/erp/report/analysis',
22 24
23 OPT_LOG = '/order/erp/opt/log/list_by_page', // 操作日志 25 OPT_LOG = '/order/erp/opt/log/list_by_page', // 操作日志
24 AUDIT_LOG = '/order/erp/audit/log/list_by_page', //审批日志 26 AUDIT_LOG = '/order/erp/audit/log/list_by_page', //审批日志
25 } 27 }
26 28
  29 +export const formatSearchData = (params) => {
  30 + params.createStartTime = params.createStartTime
  31 + ? formatToDate(params.createStartTime)
  32 + : undefined;
  33 + params.productionDepartmentConsignStartTime = params.productionDepartmentConsignStartTime
  34 + ? formatToDate(params.productionDepartmentConsignStartTime)
  35 + : undefined;
  36 + params.productionDepartmentConsignEndTime = params.productionDepartmentConsignEndTime
  37 + ? formatToDate(params.productionDepartmentConsignEndTime)
  38 + : undefined;
  39 + params.orderHodStartTime = params.orderHodStartTime
  40 + ? formatToDate(params.orderHodStartTime)
  41 + : undefined;
  42 + params.orderHodEndTime = params.orderHodEndTime
  43 + ? formatToDate(params.orderHodEndTime)
  44 + : undefined;
  45 + params.selfTestPassStartTime = params.selfTestPassStartTime
  46 + ? formatToDate(params.selfTestPassStartTime)
  47 + : undefined;
  48 + params.selfTestPassEndTime = params.selfTestPassEndTime
  49 + ? formatToDate(params.selfTestPassEndTime)
  50 + : undefined;
  51 + return params;
  52 +};
  53 +
27 export const orderCreate = async (data: any) => { 54 export const orderCreate = async (data: any) => {
28 const res = await defHttp.post<any>({ url: Api.ORDER_CREATE, data }, { message: '保存成功' }); 55 const res = await defHttp.post<any>({ url: Api.ORDER_CREATE, data }, { message: '保存成功' });
29 return res; 56 return res;
@@ -50,6 +77,13 @@ export const orderAnalysis = async (data: any) =&gt; { @@ -50,6 +77,13 @@ export const orderAnalysis = async (data: any) =&gt; {
50 return res; 77 return res;
51 }; 78 };
52 79
  80 +export const orderGravity = async (data: any) => {
  81 + data = formatSearchData(data);
  82 +
  83 + const res = await defHttp.post<any>({ url: Api.GRAVITY, data });
  84 + return res;
  85 +};
  86 +
53 export const orderExport = async (data: any = {}) => { 87 export const orderExport = async (data: any = {}) => {
54 // const res = await defHttp.post<any>({ url: Api.EXPORT, data }); 88 // const res = await defHttp.post<any>({ url: Api.EXPORT, data });
55 const userStore = useUserStoreWithOut(); 89 const userStore = useUserStoreWithOut();
@@ -60,7 +94,7 @@ export const orderExport = async (data: any = {}) =&gt; { @@ -60,7 +94,7 @@ export const orderExport = async (data: any = {}) =&gt; {
60 url: '/basic-api' + Api.EXPORT, 94 url: '/basic-api' + Api.EXPORT,
61 method: 'post', 95 method: 'post',
62 responseType: 'blob', 96 responseType: 'blob',
63 - headers: { Authorization: `Bearer ${token}` }, 97 + headers: { Authorization: `${token}` },
64 data, 98 data,
65 }) 99 })
66 .then((response) => { 100 .then((response) => {
@@ -74,6 +108,8 @@ export const orderExport = async (data: any = {}) =&gt; { @@ -74,6 +108,8 @@ export const orderExport = async (data: any = {}) =&gt; {
74 a.click(); // 模拟点击操作来下载文件 108 a.click(); // 模拟点击操作来下载文件
75 URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 109 URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存
76 document.body.removeChild(a); 110 document.body.removeChild(a);
  111 +
  112 + message.success('导出成功');
77 }) 113 })
78 .catch((error) => { 114 .catch((error) => {
79 // 处理错误 115 // 处理错误
@@ -104,28 +140,7 @@ export async function uploadImg(params, onUploadProgress: (progressEvent: Progre @@ -104,28 +140,7 @@ export async function uploadImg(params, onUploadProgress: (progressEvent: Progre
104 } 140 }
105 141
106 export const getOrderList = async (params: DemoParams) => { 142 export const getOrderList = async (params: DemoParams) => {
107 - params.createStartTime = params.createStartTime  
108 - ? formatToDate(params.createStartTime)  
109 - : undefined;  
110 - params.productionDepartmentConsignStartTime = params.productionDepartmentConsignStartTime  
111 - ? formatToDate(params.productionDepartmentConsignStartTime)  
112 - : undefined;  
113 - params.productionDepartmentConsignEndTime = params.productionDepartmentConsignEndTime  
114 - ? formatToDate(params.productionDepartmentConsignEndTime)  
115 - : undefined;  
116 - params.orderHodStartTime = params.orderHodStartTime  
117 - ? formatToDate(params.orderHodStartTime)  
118 - : undefined;  
119 - params.orderHodEndTime = params.orderHodEndTime  
120 - ? formatToDate(params.orderHodEndTime)  
121 - : undefined;  
122 - params.selfTestPassStartTime = params.selfTestPassStartTime  
123 - ? formatToDate(params.selfTestPassStartTime)  
124 - : undefined;  
125 - params.selfTestPassEndTime = params.selfTestPassEndTime  
126 - ? formatToDate(params.selfTestPassEndTime)  
127 - : undefined;  
128 - 143 + params = formatSearchData(params);
129 const res = await defHttp.post<DemoListGetResultModel>({ 144 const res = await defHttp.post<DemoListGetResultModel>({
130 url: Api.ORDER, 145 url: Api.ORDER,
131 params, 146 params,
src/api/sys/config.ts 0 → 100644
  1 +import { defHttp } from '/@/utils/http/axios';
  2 +import { LoginParams, LoginResultModel } from './model/userModel';
  3 +
  4 +import { ErrorMessageMode } from '/#/axios';
  5 +
  6 +enum Api {
  7 + // Login = '/login',
  8 + LIST = '/order/erp/system_setting/query_list',
  9 + EDIT = '/order/erp/system_setting/edit',
  10 + ADD = '/order/erp/system_setting/add',
  11 + DELETE = '/order/erp/system_setting/delete_by_id',
  12 +}
  13 +
  14 +export function getList(params: LoginParams, mode: ErrorMessageMode = 'modal') {
  15 + return defHttp.post<LoginResultModel>(
  16 + {
  17 + url: Api.LIST,
  18 + params,
  19 + },
  20 + {
  21 + errorMessageMode: mode,
  22 + },
  23 + );
  24 +}
  25 +export function saveConfig(params: LoginParams) {
  26 + return defHttp.post<LoginResultModel>(
  27 + {
  28 + url: Api.EDIT,
  29 + params,
  30 + },
  31 + {
  32 + message: '保存成功',
  33 + },
  34 + );
  35 +}
  36 +
  37 +export function addConfig(params: LoginParams) {
  38 + return defHttp.post<LoginResultModel>(
  39 + {
  40 + url: Api.ADD,
  41 + params,
  42 + },
  43 + {
  44 + message: '新建成功',
  45 + },
  46 + );
  47 +}
  48 +
  49 +export function deleteConfig(params: LoginParams) {
  50 + return defHttp.post<LoginResultModel>(
  51 + {
  52 + url: Api.DELETE,
  53 + params,
  54 + },
  55 + {
  56 + message: '删除成功',
  57 + },
  58 + );
  59 +}
src/api/sys/user.ts
@@ -10,6 +10,11 @@ enum Api { @@ -10,6 +10,11 @@ enum Api {
10 GetUserInfo = '/getUserInfo', 10 GetUserInfo = '/getUserInfo',
11 GetPermCode = '/getPermCode', 11 GetPermCode = '/getPermCode',
12 TestRetry = '/testRetry', 12 TestRetry = '/testRetry',
  13 + MODIFY_PASSWORD = '/order/erp/users/update_pass',
  14 + FORGET_PASSWORD = '/order/erp/auth/password_modify',
  15 + RESET = '/order/erp/users/reset',
  16 + CAPTCHA = '/order/erp/captcha/get_img_captcha_code',
  17 + SMS = '/order/erp/captcha/send_captcha_code',
13 } 18 }
14 19
15 /** 20 /**
@@ -27,6 +32,19 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = &#39;modal&#39;) @@ -27,6 +32,19 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = &#39;modal&#39;)
27 ); 32 );
28 } 33 }
29 34
  35 +export function MODIFY_PASSWORD(params: LoginParams, mode: ErrorMessageMode = 'modal') {
  36 + return defHttp.post<LoginResultModel>(
  37 + {
  38 + url: Api.MODIFY_PASSWORD,
  39 + params,
  40 + },
  41 + {
  42 + errorMessageMode: mode,
  43 + message: '修改成功',
  44 + },
  45 + );
  46 +}
  47 +
30 /** 48 /**
31 * @description: getUserInfo 49 * @description: getUserInfo
32 */ 50 */
@@ -56,5 +74,18 @@ export function testRetry() { @@ -56,5 +74,18 @@ export function testRetry() {
56 } 74 }
57 75
58 export function getImageCaptcha() { 76 export function getImageCaptcha() {
59 - return defHttp.post({ url: '/order/erp/captcha/get_img_captcha_code' }); 77 + return defHttp.post({ url: Api.CAPTCHA });
  78 +}
  79 +
  80 +export function forgetPassword(params) {
  81 + return defHttp.post(
  82 + { url: Api.FORGET_PASSWORD, params },
  83 + {
  84 + message: '修改成功',
  85 + },
  86 + );
  87 +}
  88 +
  89 +export function getSms(params) {
  90 + return defHttp.post({ url: Api.SMS, params });
60 } 91 }
src/enums/pageEnum.ts
@@ -2,7 +2,7 @@ export enum PageEnum { @@ -2,7 +2,7 @@ export enum PageEnum {
2 // basic login path 2 // basic login path
3 BASE_LOGIN = '/login', 3 BASE_LOGIN = '/login',
4 // basic home path 4 // basic home path
5 - BASE_HOME = '/', 5 + BASE_HOME = '/home',
6 // error page path 6 // error page path
7 ERROR_PAGE = '/exception', 7 ERROR_PAGE = '/exception',
8 // error log page path 8 // error log page path
src/enums/roleEnum.ts
1 export enum RoleEnum { 1 export enum RoleEnum {
2 // super admin 2 // super admin
3 SUPER = 'super', 3 SUPER = 'super',
4 - 4 + ADMIN = 'admin',
5 // tester 5 // tester
6 TEST = 'test', 6 TEST = 'test',
7 } 7 }
src/hooks/component/order.ts
@@ -9,6 +9,11 @@ export function useOrderInfo(orderStore) { @@ -9,6 +9,11 @@ export function useOrderInfo(orderStore) {
9 value: item.dictValue, 9 value: item.dictValue,
10 }); 10 });
11 11
  12 + const exchangeRate = computed(() => {
  13 + const dictInfo = orderStore.getDictInfo;
  14 + return map(dictInfo?.exchangeRate, transformDictInfo);
  15 + });
  16 +
12 const customerCode = computed(() => { 17 const customerCode = computed(() => {
13 const dictInfo = orderStore.getDictInfo; 18 const dictInfo = orderStore.getDictInfo;
14 19
@@ -75,7 +80,11 @@ export function useOrderInfo(orderStore) { @@ -75,7 +80,11 @@ export function useOrderInfo(orderStore) {
75 return map(dictInfo?.midCheckResult, transformDictInfo); 80 return map(dictInfo?.midCheckResult, transformDictInfo);
76 }); 81 });
77 82
78 - console.log('%c [ ]-78', 'font-size:13px; background:pink; color:#bf2c9f;', endCheckResult); 83 + const businessPerson = computed(() => {
  84 + const dictInfo = orderStore.getDictInfo;
  85 + return map(dictInfo?.businessPerson, transformDictInfo);
  86 + });
  87 +
79 return { 88 return {
80 customerCode, 89 customerCode,
81 projectNo, 90 projectNo,
@@ -90,5 +99,7 @@ export function useOrderInfo(orderStore) { @@ -90,5 +99,7 @@ export function useOrderInfo(orderStore) {
90 manualPreform, 99 manualPreform,
91 midCheckResult, 100 midCheckResult,
92 endCheckResult, 101 endCheckResult,
  102 + exchangeRate,
  103 + businessPerson,
93 }; 104 };
94 } 105 }
src/layouts/default/header/components/user-dropdown/index.vue
1 <template> 1 <template>
2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`"> 2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`">
3 <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex"> 3 <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex">
4 - <img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" /> 4 + <!-- <img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" /> -->
5 <span :class="`${prefixCls}__info hidden md:block`"> 5 <span :class="`${prefixCls}__info hidden md:block`">
6 <span :class="`${prefixCls}__name `" class="truncate"> 6 <span :class="`${prefixCls}__name `" class="truncate">
7 - {{ getUserInfo.realName }} 7 + {{ getUserInfo.nickName }}
8 </span> 8 </span>
9 </span> 9 </span>
10 </span> 10 </span>
@@ -76,8 +76,13 @@ @@ -76,8 +76,13 @@
76 const userStore = useUserStore(); 76 const userStore = useUserStore();
77 77
78 const getUserInfo = computed(() => { 78 const getUserInfo = computed(() => {
79 - const { realName = '', avatar, desc } = userStore.getUserInfo || {};  
80 - return { realName, avatar: avatar || headerImg, desc }; 79 + const { nickName = '', avatar, desc } = userStore.getUserInfo || {};
  80 + console.log(
  81 + '%c [ userStore.getUserInfo ]-80',
  82 + 'font-size:13px; background:pink; color:#bf2c9f;',
  83 + userStore.getUserInfo,
  84 + );
  85 + return { nickName, avatar: avatar || headerImg, desc };
81 }); 86 });
82 87
83 const [register, { openModal }] = useModal(); 88 const [register, { openModal }] = useModal();
src/layouts/default/header/index.less
@@ -104,7 +104,7 @@ @@ -104,7 +104,7 @@
104 display: flex; 104 display: flex;
105 // padding-right: 12px; 105 // padding-right: 12px;
106 align-items: center; 106 align-items: center;
107 - min-width: 180px; 107 + min-width: 120px;
108 108
109 &__item { 109 &__item {
110 display: flex !important; 110 display: flex !important;
src/layouts/default/header/index.vue
@@ -49,7 +49,6 @@ @@ -49,7 +49,6 @@
49 /> --> 49 /> -->
50 50
51 <UserDropDown :theme="getHeaderTheme" /> 51 <UserDropDown :theme="getHeaderTheme" />
52 - <span className="text-gray-900">{{ nickName }}</span>  
53 <!-- <SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" /> --> 52 <!-- <SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" /> -->
54 </div> 53 </div>
55 </Header> 54 </Header>
src/router/routes/modules/project/system.ts
@@ -2,6 +2,7 @@ import type { AppRouteModule } from &#39;/@/router/types&#39;; @@ -2,6 +2,7 @@ import type { AppRouteModule } from &#39;/@/router/types&#39;;
2 2
3 import { LAYOUT } from '/@/router/constant'; 3 import { LAYOUT } from '/@/router/constant';
4 import { t } from '/@/hooks/web/useI18n'; 4 import { t } from '/@/hooks/web/useI18n';
  5 +import { RoleEnum } from '/@/enums/roleEnum';
5 6
6 const system: AppRouteModule = { 7 const system: AppRouteModule = {
7 path: '/system', 8 path: '/system',
@@ -19,21 +20,41 @@ const system: AppRouteModule = { @@ -19,21 +20,41 @@ const system: AppRouteModule = {
19 name: 'AccountManagement', 20 name: 'AccountManagement',
20 meta: { 21 meta: {
21 title: t('routes.demo.system.account'), 22 title: t('routes.demo.system.account'),
  23 + roles: [RoleEnum.ADMIN],
22 ignoreKeepAlive: false, 24 ignoreKeepAlive: false,
23 }, 25 },
24 component: () => import('/@/views/project/account/index.vue'), 26 component: () => import('/@/views/project/account/index.vue'),
25 }, 27 },
  28 + // {
  29 + // path: 'account_detail/:id',
  30 + // name: 'AccountDetail',
  31 + // meta: {
  32 + // hideMenu: true,
  33 + // title: t('routes.demo.system.account_detail'),
  34 + // ignoreKeepAlive: true,
  35 + // showMenu: false,
  36 + // currentActiveMenu: '/system/account',
  37 + // },
  38 + // component: () => import('/@/views/project/account/AccountDetail.vue'),
  39 + // },
  40 + {
  41 + path: 'changePassword',
  42 + name: 'ChangePassword',
  43 + meta: {
  44 + title: t('routes.demo.system.password'),
  45 + ignoreKeepAlive: true,
  46 + },
  47 + component: () => import('/@/views/demo/system/password/index.vue'),
  48 + },
26 { 49 {
27 - path: 'account_detail/:id',  
28 - name: 'AccountDetail', 50 + path: 'config',
  51 + name: 'config',
29 meta: { 52 meta: {
30 - hideMenu: true,  
31 - title: t('routes.demo.system.account_detail'), 53 + title: '系统配置',
32 ignoreKeepAlive: true, 54 ignoreKeepAlive: true,
33 - showMenu: false,  
34 - currentActiveMenu: '/system/account', 55 + roles: [RoleEnum.ADMIN],
35 }, 56 },
36 - component: () => import('/@/views/project/account/AccountDetail.vue'), 57 + component: () => import('/@/views/project/config/index.vue'),
37 }, 58 },
38 // { 59 // {
39 // path: 'role', 60 // path: 'role',
src/store/modules/order.ts
@@ -92,7 +92,7 @@ export const useOrderStore = defineStore({ @@ -92,7 +92,7 @@ export const useOrderStore = defineStore({
92 async getDict(): Promise<GetUserInfoModel | null> { 92 async getDict(): Promise<GetUserInfoModel | null> {
93 try { 93 try {
94 const data = await getInitDictData(); 94 const data = await getInitDictData();
95 - console.log('%c [ data ]-95', 'font-size:13px; background:pink; color:#bf2c9f;', data); 95 +
96 this.dicts = groupBy(data, 'dictCode'); 96 this.dicts = groupBy(data, 'dictCode');
97 } catch (error) { 97 } catch (error) {
98 return Promise.reject(error); 98 return Promise.reject(error);
src/store/modules/permission.ts
@@ -112,6 +112,11 @@ export const usePermissionStore = defineStore({ @@ -112,6 +112,11 @@ export const usePermissionStore = defineStore({
112 async buildRoutesAction(): Promise<AppRouteRecordRaw[]> { 112 async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
113 const { t } = useI18n(); 113 const { t } = useI18n();
114 const userStore = useUserStore(); 114 const userStore = useUserStore();
  115 + console.log(
  116 + '%c [ userStore ]-115',
  117 + 'font-size:13px; background:pink; color:#bf2c9f;',
  118 + userStore,
  119 + );
115 const appStore = useAppStoreWithOut(); 120 const appStore = useAppStoreWithOut();
116 121
117 let routes: AppRouteRecordRaw[] = []; 122 let routes: AppRouteRecordRaw[] = [];
@@ -127,7 +132,9 @@ export const usePermissionStore = defineStore({ @@ -127,7 +132,9 @@ export const usePermissionStore = defineStore({
127 const { roles } = meta || {}; 132 const { roles } = meta || {};
128 if (!roles) return true; 133 if (!roles) return true;
129 // 进行角色权限判断 134 // 进行角色权限判断
130 - return roleList.some((role) => roles.includes(role)); 135 + const user = userStore.getUserInfo;
  136 + return user?.roleSmallVO.code === 'admin';
  137 + // return roleList.some((role) => roles.includes(role));
131 }; 138 };
132 139
133 const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { 140 const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => {
@@ -195,6 +202,7 @@ export const usePermissionStore = defineStore({ @@ -195,6 +202,7 @@ export const usePermissionStore = defineStore({
195 routes = filter(routes, routeRemoveIgnoreFilter); 202 routes = filter(routes, routeRemoveIgnoreFilter);
196 // 移除掉 ignoreRoute: true 的路由 一级路由; 203 // 移除掉 ignoreRoute: true 的路由 一级路由;
197 routes = routes.filter(routeRemoveIgnoreFilter); 204 routes = routes.filter(routeRemoveIgnoreFilter);
  205 +
198 // 对菜单进行排序 206 // 对菜单进行排序
199 menuList.sort((a, b) => { 207 menuList.sort((a, b) => {
200 return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0); 208 return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0);
src/utils/dateUtil.ts
@@ -11,7 +11,7 @@ export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FOR @@ -11,7 +11,7 @@ export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FOR
11 } 11 }
12 12
13 export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string { 13 export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string {
14 - return dayjs(date).format(format); 14 + return date ? dayjs(date).format(format) : '';
15 } 15 }
16 16
17 export const dateUtil = dayjs; 17 export const dateUtil = dayjs;
src/utils/project.ts
1 -export const getDisable = (code, id) => {  
2 - return code === 'LOCKED' && !!id; 1 +export const getDisable = (code, id, value) => {
  2 + return code === 'LOCKED' && !!id && value;
  3 +};
  4 +
  5 +// 利润分析的权限校验
  6 +export const getProfitDisable = (field, code, id, value) => {
  7 + // 包装费用,汇率不允许修改
  8 + if (['packetPrice', 'exchangeRate'].includes(field)) {
  9 + return true;
  10 + }
  11 + // code是lock,编辑并且value存在,才需要审核
  12 + return code === 'LOCKED' && !!id && value;
  13 +};
  14 +
  15 +// 基本信息的权限校验 客户编码、项目号、生产科、内部编号、业务员 才需要审核
  16 +export const getBaseDisable = (field, code, id) => {
  17 + if (
  18 + [
  19 + 'customerCode',
  20 + 'projectNo',
  21 + 'productionDepartment',
  22 + 'innerNo',
  23 + 'orderCount',
  24 + 'businessPerson',
  25 + ].includes(field)
  26 + ) {
  27 + return code === 'LOCKED' && !!id;
  28 + }
  29 + return false;
3 }; 30 };
src/views/demo/system/password/index.vue
@@ -13,13 +13,17 @@ @@ -13,13 +13,17 @@
13 import { defineComponent } from 'vue'; 13 import { defineComponent } from 'vue';
14 import { PageWrapper } from '/@/components/Page'; 14 import { PageWrapper } from '/@/components/Page';
15 import { BasicForm, useForm } from '/@/components/Form'; 15 import { BasicForm, useForm } from '/@/components/Form';
  16 + import { useUserStoreWithOut } from '/@/store/modules/user';
16 17
17 import { formSchema } from './pwd.data'; 18 import { formSchema } from './pwd.data';
  19 + import { forgetPassword } from '/@/api/sys/user';
18 20
19 export default defineComponent({ 21 export default defineComponent({
20 name: 'ChangePassword', 22 name: 'ChangePassword',
21 components: { BasicForm, PageWrapper }, 23 components: { BasicForm, PageWrapper },
22 setup() { 24 setup() {
  25 + const userStore = useUserStoreWithOut();
  26 +
23 const [register, { validate, resetFields }] = useForm({ 27 const [register, { validate, resetFields }] = useForm({
24 size: 'large', 28 size: 'large',
25 baseColProps: { span: 24 }, 29 baseColProps: { span: 24 },
@@ -31,12 +35,10 @@ @@ -31,12 +35,10 @@
31 async function handleSubmit() { 35 async function handleSubmit() {
32 try { 36 try {
33 const values = await validate(); 37 const values = await validate();
34 - const { passwordOld, passwordNew } = values;  
35 38
36 - // TODO custom api  
37 - console.log(passwordOld, passwordNew);  
38 - // const { router } = useRouter();  
39 - // router.push(pageEnum.BASE_LOGIN); 39 + const userInfo = userStore.getUserInfo;
  40 +
  41 + await forgetPassword({ ...values, userId: userInfo.id });
40 } catch (error) {} 42 } catch (error) {}
41 } 43 }
42 44
src/views/demo/system/password/pwd.data.ts
1 import { FormSchema } from '/@/components/Form'; 1 import { FormSchema } from '/@/components/Form';
2 2
3 export const formSchema: FormSchema[] = [ 3 export const formSchema: FormSchema[] = [
  4 + // {
  5 + // field: 'passwordOld',
  6 + // label: '当前密码',
  7 + // component: 'InputPassword',
  8 + // required: true,
  9 + // },
4 { 10 {
5 - field: 'passwordOld',  
6 - label: '当前密码',  
7 - component: 'InputPassword',  
8 - required: true,  
9 - },  
10 - {  
11 - field: 'passwordNew', 11 + field: 'password',
12 label: '新密码', 12 label: '新密码',
13 component: 'StrengthMeter', 13 component: 'StrengthMeter',
14 componentProps: { 14 componentProps: {
@@ -34,7 +34,7 @@ export const formSchema: FormSchema[] = [ @@ -34,7 +34,7 @@ export const formSchema: FormSchema[] = [
34 if (!value) { 34 if (!value) {
35 return Promise.reject('密码不能为空'); 35 return Promise.reject('密码不能为空');
36 } 36 }
37 - if (value !== values.passwordNew) { 37 + if (value !== values.password) {
38 return Promise.reject('两次输入的密码不一致!'); 38 return Promise.reject('两次输入的密码不一致!');
39 } 39 }
40 return Promise.resolve(); 40 return Promise.resolve();
src/views/project/account/index.vue
@@ -70,6 +70,9 @@ @@ -70,6 +70,9 @@
70 }, 70 },
71 useSearchForm: true, 71 useSearchForm: true,
72 showTableSetting: true, 72 showTableSetting: true,
  73 + tableSetting: {
  74 + setting: false,
  75 + },
73 bordered: true, 76 bordered: true,
74 handleSearchInfoFn(info) { 77 handleSearchInfoFn(info) {
75 console.log('handleSearchInfoFn', info); 78 console.log('handleSearchInfoFn', info);
src/views/project/approve/FieldPanel.vue
@@ -51,14 +51,15 @@ @@ -51,14 +51,15 @@
51 <a-button @click="handleFalse"> 不通过</a-button> 51 <a-button @click="handleFalse"> 不通过</a-button>
52 </template> 52 </template>
53 </BasicDrawer> 53 </BasicDrawer>
  54 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
54 </PageWrapper> 55 </PageWrapper>
55 </template> 56 </template>
56 <script lang="ts"> 57 <script lang="ts">
  58 + import MsgModal from './MsgModal.vue';
57 import { computed, defineComponent, ref } from 'vue'; 59 import { computed, defineComponent, ref } from 'vue';
58 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 60 import { BasicTable, useTable, TableAction } from '/@/components/Table';
59 import { PageWrapper } from '/@/components/Page'; 61 import { PageWrapper } from '/@/components/Page';
60 import { BasicDrawer, useDrawer } from '/@/components/Drawer'; 62 import { BasicDrawer, useDrawer } from '/@/components/Drawer';
61 -  
62 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; 63 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve';
63 import { 64 import {
64 FIELDS_BASE_INFO, 65 FIELDS_BASE_INFO,
@@ -81,11 +82,15 @@ @@ -81,11 +82,15 @@
81 BasicDrawer, 82 BasicDrawer,
82 TableAction, 83 TableAction,
83 BaseInfo, 84 BaseInfo,
  85 + MsgModal,
84 }, 86 },
85 props: { 87 props: {
86 isApproved: { type: Boolean }, 88 isApproved: { type: Boolean },
87 }, 89 },
88 setup(props) { 90 setup(props) {
  91 + // visible 用于msgModal显示隐藏
  92 + const msgVisible = ref(false);
  93 +
89 const checkedKeys = ref<Array<string | number>>([]); 94 const checkedKeys = ref<Array<string | number>>([]);
90 const currentKey = ref('1'); 95 const currentKey = ref('1');
91 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer(); 96 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
@@ -99,17 +104,35 @@ @@ -99,17 +104,35 @@
99 const baseInfos = ref({}); 104 const baseInfos = ref({});
100 const id = ref(''); 105 const id = ref('');
101 106
102 - const [registerTable, { reload }] = useTable({  
103 - api: props.isApproved ? getApprovedListApi : getWaitListApi,  
104 - searchInfo: { type: 0 }, 107 + let columns = [
  108 + {
  109 + title: '申请人',
  110 + dataIndex: 'createBy',
  111 + width: 150,
  112 + },
  113 + ];
105 114
106 - columns: [ 115 + if (props.isApproved) {
  116 + columns = columns.concat([
107 { 117 {
108 - title: '申请人',  
109 - dataIndex: 'createBy', 118 + title: '状态',
  119 + dataIndex: 'status',
110 width: 150, 120 width: 150,
  121 + customRender: (column) => {
  122 + const { record } = column || {};
  123 +
  124 + return record.status === 10 ? '通过' : '拒绝';
  125 + },
111 }, 126 },
112 - ], 127 + { title: '拒绝原因', dataIndex: 'refuseRemark', width: 250 },
  128 + ]);
  129 + }
  130 +
  131 + const [registerTable, { reload }] = useTable({
  132 + api: props.isApproved ? getApprovedListApi : getWaitListApi,
  133 + searchInfo: { type: 0 },
  134 +
  135 + columns,
113 // useSearchForm: true, 136 // useSearchForm: true,
114 // formConfig: getFormConfig(), 137 // formConfig: getFormConfig(),
115 rowKey: 'id', 138 rowKey: 'id',
@@ -209,14 +232,23 @@ @@ -209,14 +232,23 @@
209 } 232 }
210 233
211 async function handleFalse() { 234 async function handleFalse() {
212 - await approveAuditApi({ status: 20, id: id.value });  
213 - reload();  
214 - closeDrawer(); 235 + msgVisible.value = true;
215 } 236 }
216 237
217 const role = computed(() => { 238 const role = computed(() => {
218 return userStore.getUserInfo?.roleSmallVO?.code; 239 return userStore.getUserInfo?.roleSmallVO?.code;
219 }); 240 });
  241 +
  242 + // 定义MsgModalClose的事件,方便子组件调用
  243 + const handleMsgModalClose = async (data) => {
  244 + if (data) {
  245 + await approveAuditApi({ status: 20, id: id.value, refuseRemark: data });
  246 + reload();
  247 + closeDrawer();
  248 + }
  249 + msgVisible.value = false;
  250 + };
  251 +
220 return { 252 return {
221 handleProfitModal, 253 handleProfitModal,
222 registerTable, 254 registerTable,
@@ -233,8 +265,9 @@ @@ -233,8 +265,9 @@
233 handleFalse, 265 handleFalse,
234 ROLE, 266 ROLE,
235 role, 267 role,
  268 + msgVisible,
  269 + handleMsgModalClose,
236 }; 270 };
237 }, 271 },
238 }); 272 });
239 </script> 273 </script>
240 -../order/constant  
src/views/project/approve/MsgModal.vue 0 → 100644
  1 +<!-- 通过vue的modal增加一个拒绝填写message -->
  2 +<template>
  3 + <!-- 一直显示 -->
  4 + <Modal title="拒绝原因" width="30%" @cancel="handleClose" @ok="handleOk" visible>
  5 + <div className="pa-5">
  6 + <a-textarea :rows="5" placeholder="请输入拒绝原因" v-model:value="message" />
  7 + </div>
  8 + </Modal>
  9 +</template>
  10 +
  11 +<script setup lang="ts">
  12 + import { ref, defineEmits } from 'vue';
  13 + import { Modal } from 'ant-design-vue';
  14 +
  15 + const emit = defineEmits(['msg-modal-close']);
  16 +
  17 + const message = ref('');
  18 +
  19 + const handleOk = () => {
  20 + // 修改父组件的状态
  21 + emit('msg-modal-close', message.value);
  22 + };
  23 +
  24 + const handleClose = () => {
  25 + // 修改父组件的状态
  26 + emit('msg-modal-close');
  27 + };
  28 +</script>
src/views/project/approve/ProfitPanel.vue
@@ -33,9 +33,11 @@ @@ -33,9 +33,11 @@
33 <a-button @click="handleFalse"> 不通过</a-button> 33 <a-button @click="handleFalse"> 不通过</a-button>
34 </template> 34 </template>
35 </BasicDrawer> 35 </BasicDrawer>
  36 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
36 </PageWrapper> 37 </PageWrapper>
37 </template> 38 </template>
38 <script lang="ts"> 39 <script lang="ts">
  40 + import MsgModal from './MsgModal.vue';
39 import { computed, defineComponent, ref } from 'vue'; 41 import { computed, defineComponent, ref } from 'vue';
40 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 42 import { BasicTable, useTable, TableAction } from '/@/components/Table';
41 import { PageWrapper } from '/@/components/Page'; 43 import { PageWrapper } from '/@/components/Page';
@@ -56,11 +58,14 @@ @@ -56,11 +58,14 @@
56 BasicDrawer, 58 BasicDrawer,
57 TableAction, 59 TableAction,
58 BaseInfo, 60 BaseInfo,
  61 + MsgModal,
59 }, 62 },
60 props: { 63 props: {
61 isApproved: { type: Boolean }, 64 isApproved: { type: Boolean },
62 }, 65 },
63 setup(props) { 66 setup(props) {
  67 + // visible 用于msgModal显示隐藏
  68 + const msgVisible = ref(false);
64 const checkedKeys = ref<Array<string | number>>([]); 69 const checkedKeys = ref<Array<string | number>>([]);
65 const currentKey = ref('1'); 70 const currentKey = ref('1');
66 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer(); 71 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
@@ -68,17 +73,35 @@ @@ -68,17 +73,35 @@
68 const baseInfos = ref({}); 73 const baseInfos = ref({});
69 const id = ref(''); 74 const id = ref('');
70 75
71 - const [registerTable, { reload }] = useTable({  
72 - api: props.isApproved ? getApprovedListApi : getWaitListApi,  
73 - searchInfo: { type: 10 }, 76 + let columns = [
  77 + {
  78 + title: '申请人',
  79 + dataIndex: 'createBy',
  80 + width: 150,
  81 + },
  82 + ];
74 83
75 - columns: [ 84 + if (props.isApproved) {
  85 + columns = columns.concat([
76 { 86 {
77 - title: '申请人',  
78 - dataIndex: 'createBy', 87 + title: '状态',
  88 + dataIndex: 'status',
79 width: 150, 89 width: 150,
  90 + customRender: (column) => {
  91 + const { record } = column || {};
  92 +
  93 + return record.status === 10 ? '通过' : '拒绝';
  94 + },
80 }, 95 },
81 - ], 96 + { title: '拒绝原因', dataIndex: 'refuseRemark', width: 250 },
  97 + ]);
  98 + }
  99 +
  100 + const [registerTable, { reload }] = useTable({
  101 + api: props.isApproved ? getApprovedListApi : getWaitListApi,
  102 + searchInfo: { type: 10 },
  103 +
  104 + columns,
82 // useSearchForm: true, 105 // useSearchForm: true,
83 // formConfig: getFormConfig(), 106 // formConfig: getFormConfig(),
84 rowKey: 'id', 107 rowKey: 'id',
@@ -118,6 +141,12 @@ @@ -118,6 +141,12 @@
118 openDrawer(true, { data }); 141 openDrawer(true, { data });
119 id.value = data.id; 142 id.value = data.id;
120 fieldInfos.value = FIELDS_PROFIT_INFO.map((field) => { 143 fieldInfos.value = FIELDS_PROFIT_INFO.map((field) => {
  144 + if (field.field === 'profitType') {
  145 + return {
  146 + label: field.label,
  147 + value: data.fieldInfos.profitAnalysisFields[field.field] == 0 ? '方式1' : '方式2',
  148 + };
  149 + }
121 return { 150 return {
122 label: field.label, 151 label: field.label,
123 value: data.fieldInfos.profitAnalysisFields[field.field], 152 value: data.fieldInfos.profitAnalysisFields[field.field],
@@ -138,14 +167,25 @@ @@ -138,14 +167,25 @@
138 } 167 }
139 168
140 async function handleFalse() { 169 async function handleFalse() {
141 - await approveAuditApi({ status: 20, id: id.value });  
142 - reload();  
143 - closeDrawer(); 170 + msgVisible.value = true;
  171 + // await approveAuditApi({ status: 20, id: id.value });
  172 + // reload();
  173 + // closeDrawer();
144 } 174 }
145 175
146 const role = computed(() => { 176 const role = computed(() => {
147 return userStore.getUserInfo?.roleSmallVO?.code; 177 return userStore.getUserInfo?.roleSmallVO?.code;
148 }); 178 });
  179 +
  180 + // 定义MsgModalClose的事件,方便子组件调用
  181 + const handleMsgModalClose = async (data) => {
  182 + if (data) {
  183 + await approveAuditApi({ status: 20, id: id.value, refuseRemark: data });
  184 + reload();
  185 + closeDrawer();
  186 + }
  187 + msgVisible.value = false;
  188 + };
149 return { 189 return {
150 handleProfitModal, 190 handleProfitModal,
151 registerTable, 191 registerTable,
@@ -162,8 +202,9 @@ @@ -162,8 +202,9 @@
162 handleFalse, 202 handleFalse,
163 role, 203 role,
164 ROLE, 204 ROLE,
  205 + msgVisible,
  206 + handleMsgModalClose,
165 }; 207 };
166 }, 208 },
167 }); 209 });
168 </script> 210 </script>
169 -../order/constant  
src/views/project/approve/ReportPanel.vue
@@ -33,9 +33,11 @@ @@ -33,9 +33,11 @@
33 <a-button @click="handleFalse"> 不通过</a-button> 33 <a-button @click="handleFalse"> 不通过</a-button>
34 </template> 34 </template>
35 </BasicDrawer> 35 </BasicDrawer>
  36 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
36 </PageWrapper> 37 </PageWrapper>
37 </template> 38 </template>
38 <script lang="ts"> 39 <script lang="ts">
  40 + import MsgModal from './MsgModal.vue';
39 import { computed, defineComponent, ref } from 'vue'; 41 import { computed, defineComponent, ref } from 'vue';
40 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 42 import { BasicTable, useTable, TableAction } from '/@/components/Table';
41 import { PageWrapper } from '/@/components/Page'; 43 import { PageWrapper } from '/@/components/Page';
@@ -56,29 +58,49 @@ @@ -56,29 +58,49 @@
56 BasicDrawer, 58 BasicDrawer,
57 BaseInfo, 59 BaseInfo,
58 TableAction, 60 TableAction,
  61 + MsgModal,
59 }, 62 },
60 props: { 63 props: {
61 isApproved: { type: Boolean }, 64 isApproved: { type: Boolean },
62 }, 65 },
63 setup(props) { 66 setup(props) {
  67 + // visible 用于msgModal显示隐藏
  68 + const msgVisible = ref(false);
64 const checkedKeys = ref<Array<string | number>>([]); 69 const checkedKeys = ref<Array<string | number>>([]);
65 const currentKey = ref('1'); 70 const currentKey = ref('1');
66 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer(); 71 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
67 const fieldInfos = ref({}); 72 const fieldInfos = ref({});
68 const baseInfos = ref({}); 73 const baseInfos = ref({});
69 const id = ref(''); 74 const id = ref('');
  75 + let columns = [
  76 + {
  77 + title: '申请人',
  78 + dataIndex: 'createBy',
  79 + width: 150,
  80 + },
  81 + ];
  82 +
  83 + if (props.isApproved) {
  84 + columns = columns.concat([
  85 + {
  86 + title: '状态',
  87 + dataIndex: 'status',
  88 + width: 150,
  89 + customRender: (column) => {
  90 + const { record } = column || {};
  91 +
  92 + return record.status === 10 ? '通过' : '拒绝';
  93 + },
  94 + },
  95 + { title: '拒绝原因', dataIndex: 'refuseRemark', width: 250 },
  96 + ]);
  97 + }
70 98
71 const [registerTable, { reload }] = useTable({ 99 const [registerTable, { reload }] = useTable({
72 api: props.isApproved ? getApprovedListApi : getWaitListApi, 100 api: props.isApproved ? getApprovedListApi : getWaitListApi,
73 searchInfo: { type: 20 }, 101 searchInfo: { type: 20 },
74 102
75 - columns: [  
76 - {  
77 - title: '申请人',  
78 - dataIndex: 'createBy',  
79 - width: 150,  
80 - },  
81 - ], 103 + columns,
82 // useSearchForm: true, 104 // useSearchForm: true,
83 // formConfig: getFormConfig(), 105 // formConfig: getFormConfig(),
84 rowKey: 'id', 106 rowKey: 'id',
@@ -138,11 +160,19 @@ @@ -138,11 +160,19 @@
138 } 160 }
139 161
140 async function handleFalse() { 162 async function handleFalse() {
141 - await approveAuditApi({ status: 20, id: id.value });  
142 - reload();  
143 - closeDrawer(); 163 + msgVisible.value = true;
144 } 164 }
145 165
  166 + // 定义MsgModalClose的事件,方便子组件调用
  167 + const handleMsgModalClose = async (data) => {
  168 + if (data) {
  169 + await approveAuditApi({ status: 20, id: id.value, refuseRemark: data });
  170 + reload();
  171 + closeDrawer();
  172 + }
  173 + msgVisible.value = false;
  174 + };
  175 +
146 const role = computed(() => { 176 const role = computed(() => {
147 return userStore.getUserInfo?.roleSmallVO?.code; 177 return userStore.getUserInfo?.roleSmallVO?.code;
148 }); 178 });
@@ -162,8 +192,9 @@ @@ -162,8 +192,9 @@
162 handleFalse, 192 handleFalse,
163 role, 193 role,
164 ROLE, 194 ROLE,
  195 + msgVisible,
  196 + handleMsgModalClose,
165 }; 197 };
166 }, 198 },
167 }); 199 });
168 </script> 200 </script>
169 -../order/constant  
src/views/project/approve/index.vue
@@ -136,8 +136,6 @@ @@ -136,8 +136,6 @@
136 return false; 136 return false;
137 } 137 }
138 138
139 - function handleProfitModal() {}  
140 -  
141 async function handleTrue(record) { 139 async function handleTrue(record) {
142 await approveAuditApi({ status: 10, id: record.id }); 140 await approveAuditApi({ status: 10, id: record.id });
143 reload(); 141 reload();
@@ -149,7 +147,6 @@ @@ -149,7 +147,6 @@
149 } 147 }
150 148
151 return { 149 return {
152 - handleProfitModal,  
153 registerTable1, 150 registerTable1,
154 registerTable2, 151 registerTable2,
155 checkedKeys, 152 checkedKeys,
@@ -163,3 +160,9 @@ @@ -163,3 +160,9 @@
163 }, 160 },
164 }); 161 });
165 </script> 162 </script>
  163 +
  164 +<style>
  165 + .ant-modal-wrap {
  166 + z-index: 99999999;
  167 + }
  168 +</style>
src/views/project/config/CreateModal.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + destroyOnClose
  5 + @register="register"
  6 + title="创建配置"
  7 + width="600px"
  8 + @visible-change="handleShow"
  9 + @ok="handleOk"
  10 + >
  11 + <BasicForm @register="registerForm" />
  12 + </BasicModal>
  13 +</template>
  14 +<script lang="ts">
  15 + import { defineComponent, ref, defineEmits } from 'vue';
  16 + import { BasicModal, useModalInner } from '/@/components/Modal';
  17 + import { orderGravity } from '/@/api/project/order';
  18 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  19 + import { useOrderInfo } from '/@/hooks/component/order';
  20 + import { BasicForm, useForm } from '/@/components/Form/index';
  21 + import { addConfig } from '/@/api/sys/config';
  22 +
  23 + export default defineComponent({
  24 + components: { BasicModal, BasicForm },
  25 + props: {
  26 + column: { type: Number },
  27 + },
  28 + emits: ['modal-success'],
  29 + setup(props, { emit }) {
  30 + const orderStore = useOrderStoreWithOut();
  31 + const { manualPreform, exchangeRate } = useOrderInfo(orderStore);
  32 + const loading = ref(true);
  33 + const activeUser = ref();
  34 + const info = ref();
  35 + const searchData = ref({});
  36 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  37 + searchData.value = data.data || {};
  38 + activeUser.value = undefined;
  39 + info.value = '';
  40 + });
  41 +
  42 + const { customerCode: customerCodeOptions } = useOrderInfo(orderStore);
  43 + var [registerForm, { getFieldsValue, validate }] = useForm({
  44 + labelWidth: 80,
  45 + schemas: [
  46 + {
  47 + field: 'settingValue',
  48 + component: 'Select',
  49 + label: '客户编码',
  50 + rules: [{ required: true }],
  51 + componentProps: {
  52 + options: customerCodeOptions,
  53 + },
  54 + colProps: {
  55 + span: 24,
  56 + },
  57 + },
  58 + {
  59 + field: 'relationValue',
  60 + component: 'InputNumber',
  61 + label: props.column === 1 ? '利润率' : '包装费用',
  62 + rules: [{ required: true }],
  63 + colProps: {
  64 + span: 24,
  65 + },
  66 + },
  67 + ],
  68 + showActionButtonGroup: false,
  69 + actionColOptions: {
  70 + span: 24,
  71 + },
  72 + });
  73 +
  74 + function handleShow(visible: boolean) {
  75 + if (visible) {
  76 + loading.value = true;
  77 + // setModalProps({ loading: true, confirmLoading: true });
  78 + setModalProps({ loading: false, confirmLoading: false });
  79 + }
  80 + }
  81 +
  82 + async function handleCalc() {
  83 + const res = await orderGravity({
  84 + ...searchData.value,
  85 + designer: activeUser.value,
  86 + });
  87 + info.value = res?.rate || 0;
  88 + }
  89 +
  90 + async function handleOk() {
  91 + try {
  92 + const values = getFieldsValue();
  93 + await validate();
  94 + const params = {
  95 + settingCode: 'customerCode',
  96 + settingName: '客户编码',
  97 + settingValue: values.settingValue,
  98 + settingType: 1,
  99 + relationCode: props.column === 1 ? 'profitRate' : 'packetPrice',
  100 + relationName: '包装费用',
  101 + relationValue: values.relationValue,
  102 + };
  103 +
  104 + await addConfig(params);
  105 + emit('modal-success');
  106 + closeModal();
  107 + } catch (error) {
  108 + console.log('%c [ error ]-108', 'font-size:13px; background:pink; color:#bf2c9f;', error);
  109 + }
  110 + }
  111 + return {
  112 + register,
  113 + loading,
  114 + handleShow,
  115 + info,
  116 + manualPreform,
  117 + handleCalc,
  118 + activeUser,
  119 + exchangeRate,
  120 + registerForm,
  121 + handleOk,
  122 + };
  123 + },
  124 + });
  125 +</script>
  126 +<style scoped>
  127 + .empty-tips {
  128 + height: 100px;
  129 + line-height: 100px;
  130 + text-align: center;
  131 + }
  132 +</style>
src/views/project/config/TablePanel.vue 0 → 100644
  1 +<template>
  2 + <BasicTable @register="registerTable">
  3 + <template #toolbar>
  4 + <a-button v-if="props.column !== 3" type="primary" @click="handleCreateModal">新建</a-button>
  5 + </template>
  6 + <template #bodyCell="{ column, record }">
  7 + <template v-if="column.key === 'action'">
  8 + <TableAction :actions="createActions(record)" />
  9 + </template>
  10 + </template>
  11 + </BasicTable>
  12 + <CreateModal
  13 + @register="createModalRegister"
  14 + @modal-success="handleModalSuccess"
  15 + :column="props.column"
  16 + />
  17 +</template>
  18 +<script setup lang="ts">
  19 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  20 + import CreateModal from './CreateModal.vue';
  21 + import { deleteConfig, getList, saveConfig } from '/@/api/sys/config';
  22 + import { COLUMNS } from './data';
  23 + import { useModal } from '/@/components/Modal';
  24 +
  25 + const props = defineProps({
  26 + searchInfo: {
  27 + type: Object,
  28 + },
  29 + column: {
  30 + type: Number,
  31 + },
  32 + });
  33 + const [createModalRegister, { openModal }] = useModal();
  34 +
  35 + const [registerTable, { reload }] = useTable({
  36 + api: getList,
  37 + searchInfo: props.searchInfo,
  38 +
  39 + columns: COLUMNS[props.column!],
  40 + rowKey: 'id',
  41 + actionColumn: {
  42 + width: 160,
  43 + title: 'Action',
  44 + dataIndex: 'action',
  45 + },
  46 + });
  47 +
  48 + function handleCreateModal() {
  49 + openModal(true);
  50 + }
  51 +
  52 + function createActions(record: any): any[] {
  53 + if (!record.editable) {
  54 + return [
  55 + {
  56 + label: '编辑',
  57 + onClick: handleEdit.bind(null, record),
  58 + },
  59 + {
  60 + ...(props.column !== 3 && {
  61 + label: '删除',
  62 + // onClick: handleDelete.bind(null, record),
  63 + popConfirm: {
  64 + title: '确认删除?',
  65 + confirm: handleDelete.bind(null, record),
  66 + },
  67 + }),
  68 + },
  69 + ];
  70 + }
  71 + return [
  72 + {
  73 + label: '保存',
  74 + onClick: handleSave.bind(null, record),
  75 + },
  76 + {
  77 + label: '取消',
  78 + popConfirm: {
  79 + title: '是否取消编辑',
  80 + confirm: handleCancel.bind(null, record),
  81 + },
  82 + },
  83 + ];
  84 + }
  85 +
  86 + async function handleSave(record) {
  87 + await saveConfig({ id: record.id, settingValue: record.settingValue });
  88 + handleCancel(record);
  89 + reload();
  90 + }
  91 +
  92 + function handleEdit(record: any) {
  93 + record.onEdit?.(true);
  94 + }
  95 +
  96 + function handleCancel(record) {
  97 + record.onEdit?.(false, false);
  98 + }
  99 +
  100 + function handleModalSuccess() {
  101 + reload();
  102 + }
  103 +
  104 + async function handleDelete(record) {
  105 + await deleteConfig({ ids: [record.id] });
  106 + reload();
  107 + }
  108 +</script>
  109 +<style></style>
src/views/project/config/data.ts 0 → 100644
  1 +export const COLUMNS = {
  2 + 1: [
  3 + {
  4 + title: '客户编码',
  5 + dataIndex: 'settingValue',
  6 + width: 150,
  7 + },
  8 + {
  9 + title: '利润率',
  10 + dataIndex: 'relationValue',
  11 + width: 150,
  12 + editComponent: 'InputNumber',
  13 + editRow: true,
  14 + },
  15 + ],
  16 + 2: [
  17 + {
  18 + title: '客户编码',
  19 + dataIndex: 'settingValue',
  20 + width: 150,
  21 + },
  22 + {
  23 + title: '包装费用',
  24 + dataIndex: 'relationValue',
  25 + width: 150,
  26 + editComponent: 'InputNumber',
  27 + editRow: true,
  28 + },
  29 + ],
  30 + 3: [
  31 + {
  32 + title: '名称',
  33 + dataIndex: 'settingName',
  34 + width: 150,
  35 + },
  36 + {
  37 + title: '值',
  38 + dataIndex: 'settingValue',
  39 + width: 150,
  40 + editComponent: 'InputNumber',
  41 + editRow: true,
  42 + },
  43 + ],
  44 +};
src/views/project/config/index.vue 0 → 100644
  1 +<template>
  2 + <PageWrapper contentBackground>
  3 + <div className="config-page">
  4 + <Tabs v-model:selectedKey="currentKey" className="ml-2 mb-0">
  5 + <Tabs.TabPane key="1" tab="利润率配置">
  6 + <TablePanel :searchInfo="{ relationCode: 'profitRate' }" :column="1" />
  7 + </Tabs.TabPane>
  8 + <Tabs.TabPane key="2" tab="包装费用配置">
  9 + <TablePanel :searchInfo="{ relationCode: 'packetPrice' }" :column="2" />
  10 + </Tabs.TabPane>
  11 + <Tabs.TabPane key="3" tab="汇率配置">
  12 + <TablePanel :searchInfo="{ settingCode: 'exchangeRate' }" :column="3"
  13 + /></Tabs.TabPane>
  14 + </Tabs>
  15 + </div>
  16 + </PageWrapper>
  17 +</template>
  18 +
  19 +<script setup lang="ts">
  20 + import { Tabs } from 'ant-design-vue';
  21 + import { PageWrapper } from '/@/components/Page';
  22 + import TablePanel from './TablePanel.vue';
  23 + import { onMounted } from 'vue';
  24 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  25 +
  26 + let currentKey = '1';
  27 + const orderStore = useOrderStoreWithOut();
  28 +
  29 + onMounted(async () => {
  30 + await orderStore.getDict();
  31 + });
  32 +</script>
  33 +
  34 +<style>
  35 + .config-page .ant-tabs-nav-operations ant-tabs-nav-operations-hidden {
  36 + display: none;
  37 + }
  38 +
  39 + .config-page .ant-tabs-nav {
  40 + margin-bottom: 0;
  41 + }
  42 +</style>
src/views/project/order/CheckDetail.vue
@@ -12,8 +12,10 @@ @@ -12,8 +12,10 @@
12 okText="申请" 12 okText="申请"
13 ><input /> 13 ><input />
14 <div> 14 <div>
15 - <h3>基本信息</h3>  
16 - <BasicForm @register="registerForm" /> 15 + <template v-if="role === ROLE.ADMIN || role === ROLE.TRACKER">
  16 + <h3>基本信息</h3>
  17 + <BasicForm @register="registerForm" />
  18 + </template>
17 <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS"> 19 <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">
18 <h3>利润分析</h3> 20 <h3>利润分析</h3>
19 <BasicForm @register="registerProfitForm" /> 21 <BasicForm @register="registerProfitForm" />
@@ -56,19 +58,21 @@ @@ -56,19 +58,21 @@
56 58
57 const userStore = useUserStoreWithOut(); 59 const userStore = useUserStoreWithOut();
58 const getSchema = (fields) => 60 const getSchema = (fields) =>
59 - fields.map((item) => ({  
60 - field: `${item.field}`,  
61 - dataIndex: `${item.field}`,  
62 - label: item.label,  
63 - component: 'Switch',  
64 - componentProps: {  
65 - checkedValue: 'UN_LOCKED',  
66 - unCheckedValue: 'LOCKED',  
67 - },  
68 - colProps: {  
69 - span: 6,  
70 - },  
71 - })); 61 + fields
  62 + .map((item) => ({
  63 + field: `${item.field}`,
  64 + dataIndex: `${item.field}`,
  65 + label: item.label,
  66 + component: 'Switch',
  67 + componentProps: {
  68 + checkedValue: 'UN_LOCKED',
  69 + unCheckedValue: 'LOCKED',
  70 + },
  71 + colProps: {
  72 + span: 6,
  73 + },
  74 + }))
  75 + .filter((item) => item.field !== 'packetPrice' && item.field !== 'exchangeRate');
72 76
73 export default defineComponent({ 77 export default defineComponent({
74 components: { BasicDrawer, BasicForm }, 78 components: { BasicDrawer, BasicForm },
src/views/project/order/ExportModal.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + destroyOnClose
  5 + @register="register"
  6 + title="利润分析表"
  7 + width="500px"
  8 + :height="100"
  9 + wrapClassName="h-[260px]"
  10 + @visible-change="handleShow"
  11 + :footer="null"
  12 + >
  13 + <CheckboxGroup v-model:value="checkedList" :options="options" />
  14 + <div className="mt-6">
  15 + <a-button type="primary" @click="handleCalc" className="ml-4">导出</a-button>
  16 + </div>
  17 + </BasicModal>
  18 +</template>
  19 +<script lang="ts">
  20 + import { defineComponent, ref, computed } from 'vue';
  21 + import { BasicModal, useModalInner } from '/@/components/Modal';
  22 + import { orderExport } from '/@/api/project/order';
  23 + import { ROLE } from './type.d';
  24 + import { CheckboxGroup } from 'ant-design-vue';
  25 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  26 + import { useOrderInfo } from '/@/hooks/component/order';
  27 + import { merge } from 'lodash-es';
  28 + import {
  29 + ORDER_LIST_BASE_FIELDS,
  30 + ORDER_LIST_REPORT_FIELDS,
  31 + ORDER_LIST_PROFIT_FIELDS,
  32 + ORDER_LIST_INSPECT_FIELDS,
  33 + ORDER_LIST_TRACK_FIELDS,
  34 + } from './tableData';
  35 +
  36 + export default defineComponent({
  37 + components: { BasicModal, CheckboxGroup },
  38 + props: {
  39 + role: {
  40 + type: String,
  41 + },
  42 + },
  43 + setup(props) {
  44 + const orderStore = useOrderStoreWithOut();
  45 + const { manualPreform, exchangeRate } = useOrderInfo(orderStore);
  46 + const checkedList = ref([
  47 + 'baseFields',
  48 + 'reportFields',
  49 + 'profitAnalysisFields',
  50 + 'trackStageFields',
  51 + 'inspectionStageFields',
  52 + ]);
  53 + const loading = ref(true);
  54 + const activeUser = ref();
  55 + const info = ref();
  56 + const searchData = ref({});
  57 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  58 + searchData.value = data.data || {};
  59 + activeUser.value = undefined;
  60 + info.value = '';
  61 + });
  62 +
  63 + const options = computed(() => {
  64 + if (props.role === ROLE.TRACKER) {
  65 + return [
  66 + { label: '基本信息', value: 'baseFields' },
  67 + { label: '利润分析', value: 'profitAnalysisFields' },
  68 + { label: '跟单信息', value: 'trackStageFields' },
  69 + { label: '质检信息', value: 'inspectionStageFields' },
  70 + ];
  71 + }
  72 + if (props.role === ROLE.INSPECT) {
  73 + return [
  74 + { label: '基本信息', value: 'baseFields' },
  75 + { label: '跟单信息', value: 'trackStageFields' },
  76 + { label: '质检信息', value: 'inspectionStageFields' },
  77 + ];
  78 + }
  79 + return [
  80 + { label: '基本信息', value: 'baseFields' },
  81 + { label: '项目报告', value: 'reportFields' },
  82 + { label: '利润分析', value: 'profitAnalysisFields' },
  83 + { label: '跟单信息', value: 'trackStageFields' },
  84 + { label: '质检信息', value: 'inspectionStageFields' },
  85 + ];
  86 + });
  87 +
  88 + function handleShow(visible: boolean) {
  89 + if (visible) {
  90 + loading.value = true;
  91 + setModalProps({ loading: false, confirmLoading: false });
  92 + }
  93 + }
  94 +
  95 + async function handleCalc() {
  96 + const fieldVO: any = {};
  97 + checkedList.value.forEach((item) => {
  98 + if (item === 'baseFields') {
  99 + fieldVO.baseFields = ORDER_LIST_BASE_FIELDS.map((item) => ({
  100 + [item.dataIndex]: 'selected',
  101 + }));
  102 + fieldVO.baseFields = merge({}, ...fieldVO.baseFields);
  103 + } else if (item === 'reportFields') {
  104 + fieldVO.reportFields = ORDER_LIST_REPORT_FIELDS[0].children.map((item) => ({
  105 + [item.dataIndex]: 'selected',
  106 + }));
  107 + fieldVO.reportFields = merge({}, ...fieldVO.reportFields);
  108 + } else if (item === 'profitAnalysisFields') {
  109 + if (props.role === ROLE.TRACKER) {
  110 + fieldVO.profitAnalysisFields = ORDER_LIST_PROFIT_FIELDS[0].children
  111 + .filter(
  112 + (k) => k.dataIndex === 'customerPrice' || k.dataIndex === 'customerTotalPrice',
  113 + )
  114 + .map((item) => ({
  115 + [item.dataIndex]: 'selected',
  116 + }));
  117 + } else {
  118 + fieldVO.profitAnalysisFields = ORDER_LIST_PROFIT_FIELDS[0].children.map((item) => ({
  119 + [item.dataIndex]: 'selected',
  120 + }));
  121 + }
  122 + fieldVO.profitAnalysisFields = merge({}, ...fieldVO.profitAnalysisFields);
  123 + } else if (item === 'trackStageFields') {
  124 + fieldVO.trackStageFields = ORDER_LIST_TRACK_FIELDS[0].children.map((item) => ({
  125 + [item.dataIndex]: 'selected',
  126 + }));
  127 + fieldVO.trackStageFields = merge({}, ...fieldVO.trackStageFields);
  128 + } else if (item === 'inspectionStageFields') {
  129 + fieldVO.inspectionStageFields = ORDER_LIST_INSPECT_FIELDS[0].children.map((item) => ({
  130 + [item.dataIndex]: 'selected',
  131 + }));
  132 + fieldVO.inspectionStageFields = merge({}, ...fieldVO.inspectionStageFields);
  133 + }
  134 + });
  135 +
  136 + await orderExport({ fieldVO });
  137 +
  138 + closeModal();
  139 + }
  140 + return {
  141 + register,
  142 + options,
  143 + loading,
  144 + handleShow,
  145 + info,
  146 + manualPreform,
  147 + handleCalc,
  148 + activeUser,
  149 + exchangeRate,
  150 + checkedList,
  151 + };
  152 + },
  153 + });
  154 +</script>
src/views/project/order/FieldDetail.vue
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <BasicDrawer 2 <BasicDrawer
3 @register="register" 3 @register="register"
4 v-bind="$attrs" 4 v-bind="$attrs"
5 - title="title" 5 + title="字段自定义"
6 :destroyOnClose="true" 6 :destroyOnClose="true"
7 width="60%" 7 width="60%"
8 :isDetail="true" 8 :isDetail="true"
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 setup() { 55 setup() {
56 const dataSource = ref([]); 56 const dataSource = ref([]);
57 const key = ref(''); 57 const key = ref('');
58 - const title = ref(''); 58 + const title = ref('12');
59 59
60 const [registerTable, { getDataSource, reload }] = useTable({ 60 const [registerTable, { getDataSource, reload }] = useTable({
61 columns: columns, 61 columns: columns,
@@ -72,11 +72,18 @@ @@ -72,11 +72,18 @@
72 }); 72 });
73 73
74 const [register] = useDrawerInner((data) => { 74 const [register] = useDrawerInner((data) => {
75 - const { dataIndex, customTitle } = data; 75 + let { dataIndex, customTitle } = data;
  76 +
  77 + // 如果dataIndex= 手工初型1或者2,则等于手工初型
  78 + if (dataIndex === 'manualPreform1' || dataIndex == 'manualPreform2') {
  79 + dataIndex = 'manualPreform';
  80 + }
76 const dicts = orderStore.getDictInfo; 81 const dicts = orderStore.getDictInfo;
77 const dict = dicts[dataIndex]; 82 const dict = dicts[dataIndex];
78 dataSource.value = dict; 83 dataSource.value = dict;
  84 +
79 title.value = customTitle; 85 title.value = customTitle;
  86 +
80 key.value = dataIndex; 87 key.value = dataIndex;
81 }); 88 });
82 89
@@ -95,13 +102,13 @@ @@ -95,13 +102,13 @@
95 102
96 async function handleSave(record: EditRecordRow) { 103 async function handleSave(record: EditRecordRow) {
97 if (record.id) { 104 if (record.id) {
98 - await dictUpdate({ dictCode: key.value, dictValue: record.dictValue }); 105 + await dictUpdate({ id: record.id, dictCode: key.value, dictValue: record.dictValue });
99 } else { 106 } else {
100 await dictCreate({ 107 await dictCreate({
101 dictName: title.value, 108 dictName: title.value,
102 dictCode: key.value, 109 dictCode: key.value,
103 dictValue: record.dictValue, 110 dictValue: record.dictValue,
104 - sort: dataSource.value.length + 1, 111 + sort: (dataSource.value?.length || 0) + 1,
105 }); 112 });
106 } 113 }
107 114
src/views/project/order/FormDetail/BaseFormPanel.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 import { computed, defineComponent, ref } from 'vue'; 5 import { computed, defineComponent, ref } from 'vue';
6 import { BasicForm, useForm } from '/@/components/Form/index'; 6 import { BasicForm, useForm } from '/@/components/Form/index';
7 import { FIELDS_BASE_INFO } from '../tableData'; 7 import { FIELDS_BASE_INFO } from '../tableData';
8 - import { getDisable } from '/@/utils/project'; 8 + import { getBaseDisable } from '/@/utils/project';
9 import { useOrderStoreWithOut } from '/@/store/modules/order'; 9 import { useOrderStoreWithOut } from '/@/store/modules/order';
10 10
11 import { useOrderInfo } from '/@/hooks/component/order'; 11 import { useOrderInfo } from '/@/hooks/component/order';
@@ -24,6 +24,9 @@ @@ -24,6 +24,9 @@
24 id: { 24 id: {
25 type: String, 25 type: String,
26 }, 26 },
  27 + businessUsers: {
  28 + type: Array,
  29 + },
27 }, 30 },
28 emits: ['success'], 31 emits: ['success'],
29 setup(props) { 32 setup(props) {
@@ -42,7 +45,14 @@ @@ -42,7 +45,14 @@
42 productStyle, 45 productStyle,
43 outboundType, 46 outboundType,
44 packetType, 47 packetType,
  48 +
  49 + // businessPerson,
45 } = useOrderInfo(orderStore); 50 } = useOrderInfo(orderStore);
  51 + console.log(
  52 + '%c [ productionDepartment ]-57',
  53 + 'font-size:13px; background:pink; color:#bf2c9f;',
  54 + productionDepartment,
  55 + );
46 56
47 var schemas = computed(() => { 57 var schemas = computed(() => {
48 const options = { 58 const options = {
@@ -55,14 +65,11 @@ @@ -55,14 +65,11 @@
55 productStyle, 65 productStyle,
56 outboundType, 66 outboundType,
57 packetType, 67 packetType,
  68 +
  69 + businessPerson: props.businessUsers,
58 }; 70 };
59 71
60 const res = FIELDS_BASE_INFO.map((item) => { 72 const res = FIELDS_BASE_INFO.map((item) => {
61 - console.log(  
62 - '%c [ ]-62',  
63 - 'font-size:13px; background:pink; color:#bf2c9f;',  
64 - getDisable(fields.value?.baseFields?.picUrl, props.id),  
65 - );  
66 if (item.field === 'picUrl') { 73 if (item.field === 'picUrl') {
67 return { 74 return {
68 field: 'picUrl', 75 field: 'picUrl',
@@ -74,7 +81,7 @@ @@ -74,7 +81,7 @@
74 }, 81 },
75 componentProps: { 82 componentProps: {
76 imgUrl: picUrl.value, 83 imgUrl: picUrl.value,
77 - disabled: getDisable(get(fields.value, 'picUrl'), props.id), 84 + // disabled: getDisable(get(fields.value, 'picUrl'), props.id),
78 onChange: (res) => { 85 onChange: (res) => {
79 if (res.file?.response?.data) { 86 if (res.file?.response?.data) {
80 picUrl.value = res.file?.response?.data?.picUrl; 87 picUrl.value = res.file?.response?.data?.picUrl;
@@ -87,12 +94,20 @@ @@ -87,12 +94,20 @@
87 }, 94 },
88 }; 95 };
89 } 96 }
  97 +
  98 + console.log(
  99 + '%c [ ]-98',
  100 + 'font-size:13px; background:pink; color:#bf2c9f;',
  101 + item.field,
  102 + options[item.field],
  103 + );
  104 +
90 return { 105 return {
91 ...item, 106 ...item,
92 field: `${item.field}`, 107 field: `${item.field}`,
93 componentProps: { 108 componentProps: {
94 ...(item.component === 'Select' && { options: options[item.field] }), 109 ...(item.component === 'Select' && { options: options[item.field] }),
95 - disabled: getDisable(get(fields.value, `${item.field}`), props.id), 110 + disabled: getBaseDisable(item.field, get(fields.value, `${item.field}`), props.id),
96 }, 111 },
97 colProps: { 112 colProps: {
98 span: 24, 113 span: 24,
src/views/project/order/FormDetail/InspectionFormPanel.vue
@@ -2,10 +2,8 @@ @@ -2,10 +2,8 @@
2 <BasicForm @register="registerForm" /> 2 <BasicForm @register="registerForm" />
3 </template> 3 </template>
4 <script lang="ts"> 4 <script lang="ts">
5 - import { computed, defineComponent, ref, toRaw } from 'vue'; 5 + import { computed, defineComponent, ref } from 'vue';
6 import { BasicForm, useForm } from '/@/components/Form/index'; 6 import { BasicForm, useForm } from '/@/components/Form/index';
7 - import { useDrawerInner } from '/@/components/Drawer';  
8 - import { dateUtil } from '/@/utils/dateUtil';  
9 import { FIELDS_INSPECTION_INFO } from '../tableData'; 7 import { FIELDS_INSPECTION_INFO } from '../tableData';
10 import { getDisable } from '/@/utils/project'; 8 import { getDisable } from '/@/utils/project';
11 import { useOrderStoreWithOut } from '/@/store/modules/order'; 9 import { useOrderStoreWithOut } from '/@/store/modules/order';
@@ -19,6 +17,9 @@ @@ -19,6 +17,9 @@
19 id: { 17 id: {
20 type: String, 18 type: String,
21 }, 19 },
  20 + inspectFormData: {
  21 + type: Object,
  22 + },
22 }, 23 },
23 emits: ['success'], 24 emits: ['success'],
24 setup(props, { emit }) { 25 setup(props, { emit }) {
@@ -37,7 +38,11 @@ @@ -37,7 +38,11 @@
37 ...item, 38 ...item,
38 componentProps: { 39 componentProps: {
39 ...(item.component === 'Select' && { options: options[item.field] }), 40 ...(item.component === 'Select' && { options: options[item.field] }),
40 - disabled: getDisable(get(fields.value, item.field), props.id), 41 + disabled: getDisable(
  42 + get(fields.value, item.field),
  43 + props.id,
  44 + get(props.inspectFormData, `${item.field}`),
  45 + ),
41 }, 46 },
42 colProps: { 47 colProps: {
43 span: 24, 48 span: 24,
src/views/project/order/FormDetail/ProfitFormPanel.vue
@@ -4,37 +4,52 @@ @@ -4,37 +4,52 @@
4 <script lang="ts"> 4 <script lang="ts">
5 import { computed, defineComponent, reactive, ref, toRaw } from 'vue'; 5 import { computed, defineComponent, reactive, ref, toRaw } from 'vue';
6 import { BasicForm, useForm } from '/@/components/Form/index'; 6 import { BasicForm, useForm } from '/@/components/Form/index';
7 - import { dateUtil } from '/@/utils/dateUtil';  
8 import { FIELDS_PROFIT_INFO } from '../tableData'; 7 import { FIELDS_PROFIT_INFO } from '../tableData';
9 - import { getDisable } from '/@/utils/project'; 8 + import { getProfitDisable } from '/@/utils/project';
10 import { get } from 'lodash-es'; 9 import { get } from 'lodash-es';
  10 + import { useOrderInfo } from '/@/hooks/component/order';
  11 + import { useOrderStoreWithOut } from '/@/store/modules/order';
11 12
12 export default defineComponent({ 13 export default defineComponent({
13 components: { BasicForm }, 14 components: { BasicForm },
14 15
15 props: { 16 props: {
16 - detailData: {  
17 - type: Object,  
18 - },  
19 onGoCheckDetail: { 17 onGoCheckDetail: {
20 type: Function, 18 type: Function,
21 }, 19 },
22 id: { 20 id: {
23 type: String, 21 type: String,
24 }, 22 },
  23 + profitFormData: {
  24 + type: Object,
  25 + },
25 }, 26 },
26 emits: ['success'], 27 emits: ['success'],
27 setup(props, { emit }) { 28 setup(props, { emit }) {
28 let fields = ref({}); 29 let fields = ref({});
  30 + const orderStore = useOrderStoreWithOut();
  31 +
  32 + const { exchangeRate } = useOrderInfo(orderStore);
29 33
30 const schemas = computed(() => { 34 const schemas = computed(() => {
  35 + const options = {
  36 + exchangeRate,
  37 + };
  38 +
31 return FIELDS_PROFIT_INFO.map((item) => { 39 return FIELDS_PROFIT_INFO.map((item) => {
32 return { 40 return {
33 ...item, 41 ...item,
34 field: `${item.field}`, 42 field: `${item.field}`,
35 componentProps: { 43 componentProps: {
36 ...item.componentProps, 44 ...item.componentProps,
37 - disabled: getDisable(get(fields.value, `${item.field}`), props.id), 45 + ...(item.component === 'Select' &&
  46 + !item.componentProps?.options?.length && { options: options[item.field] }),
  47 + disabled: getProfitDisable(
  48 + item.field,
  49 + get(fields.value, `${item.field}`),
  50 + props.id,
  51 + get(props.profitFormData, `${item.field}`),
  52 + ),
38 }, 53 },
39 colProps: { 54 colProps: {
40 span: 24, 55 span: 24,
@@ -43,7 +58,7 @@ @@ -43,7 +58,7 @@
43 }); 58 });
44 }); 59 });
45 60
46 - const [registerForm, { setFieldsValue, getFieldsValue, resetFields }] = useForm({ 61 + const [registerForm, { setFieldsValue, getFieldsValue, resetFields, validate }] = useForm({
47 labelWidth: 120, 62 labelWidth: 120,
48 schemas, 63 schemas,
49 layout: 'vertical', 64 layout: 'vertical',
@@ -52,7 +67,16 @@ @@ -52,7 +67,16 @@
52 span: 24, 67 span: 24,
53 }, 68 },
54 }); 69 });
55 - return { fields, schemas, registerForm, getFieldsValue, setFieldsValue, resetFields }; 70 +
  71 + return {
  72 + fields,
  73 + schemas,
  74 + validate,
  75 + registerForm,
  76 + getFieldsValue,
  77 + setFieldsValue,
  78 + resetFields,
  79 + };
56 }, 80 },
57 }); 81 });
58 </script> 82 </script>
src/views/project/order/FormDetail/ReportFormPanel.vue
@@ -24,6 +24,9 @@ @@ -24,6 +24,9 @@
24 id: { 24 id: {
25 type: String, 25 type: String,
26 }, 26 },
  27 + reportFormData: {
  28 + type: Object,
  29 + },
27 }, 30 },
28 emits: ['success'], 31 emits: ['success'],
29 setup(props) { 32 setup(props) {
@@ -39,12 +42,20 @@ @@ -39,12 +42,20 @@
39 }; 42 };
40 43
41 const res = FIELDS_REPORT_INFO.map((item) => { 44 const res = FIELDS_REPORT_INFO.map((item) => {
  45 + let optionsField = item.field;
  46 + if (optionsField === 'manualPreform1' || optionsField === 'manualPreform2') {
  47 + optionsField = 'manualPreform';
  48 + }
42 return { 49 return {
43 ...item, 50 ...item,
44 field: `${item.field}`, 51 field: `${item.field}`,
45 componentProps: { 52 componentProps: {
46 - ...(item.component === 'Select' && { options: options[item.optionField] }),  
47 - disabled: getDisable(get(fields.value, `${item.field}`), props.id), 53 + ...(item.component === 'Select' && { options: options[optionsField] }),
  54 + disabled: getDisable(
  55 + get(fields.value, `${item.field}`),
  56 + props.id,
  57 + get(props.reportFormData, `${item.field}`),
  58 + ),
48 }, 59 },
49 colProps: { 60 colProps: {
50 span: 24, 61 span: 24,
@@ -54,7 +65,7 @@ @@ -54,7 +65,7 @@
54 return res; 65 return res;
55 }); 66 });
56 67
57 - const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({ 68 + const [registerForm, { setFieldsValue, getFieldsValue, resetFields, validate }] = useForm({
58 labelWidth: 120, 69 labelWidth: 120,
59 schemas, 70 schemas,
60 layout: 'vertical', 71 layout: 'vertical',
@@ -64,7 +75,15 @@ @@ -64,7 +75,15 @@
64 }, 75 },
65 }); 76 });
66 77
67 - return { fields, schemas, registerForm, getFieldsValue, setFieldsValue }; 78 + return {
  79 + fields,
  80 + schemas,
  81 + validate,
  82 + registerForm,
  83 + getFieldsValue,
  84 + setFieldsValue,
  85 + resetFields,
  86 + };
68 }, 87 },
69 }); 88 });
70 </script> 89 </script>
src/views/project/order/FormDetail/TrackFormPanel.vue
@@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
17 id: { 17 id: {
18 type: String, 18 type: String,
19 }, 19 },
  20 + trackFormData: {
  21 + type: Object,
  22 + },
20 }, 23 },
21 emits: ['success'], 24 emits: ['success'],
22 setup(props, { emit }) { 25 setup(props, { emit }) {
@@ -27,7 +30,11 @@ @@ -27,7 +30,11 @@
27 ...item, 30 ...item,
28 componentProps: { 31 componentProps: {
29 ...item.componentProps, 32 ...item.componentProps,
30 - disabled: getDisable(get(fields.value, `${item.field}`), props.id), 33 + disabled: getDisable(
  34 + get(fields.value, `${item.field}`),
  35 + props.id,
  36 + get(props.trackFormData, `${item.field}`),
  37 + ),
31 }, 38 },
32 colProps: { 39 colProps: {
33 span: 24, 40 span: 24,
src/views/project/order/FormDetail/index.vue
@@ -14,10 +14,15 @@ @@ -14,10 +14,15 @@
14 :mask="false" 14 :mask="false"
15 class="z-20" 15 class="z-20"
16 > 16 >
17 - <div className="mt-[-16px]"> 17 + <div className="mt-[-16px] order-drawer-panel">
18 <Tabs v-model:activeKey="activeKey"> 18 <Tabs v-model:activeKey="activeKey">
19 - <TabPanel key="1" tab="基本信息" :forceRender="true" v-if="role !== ROLE.INSPECT">  
20 - <BaseFormPanel ref="baseFormPanelRef" :id="id" /> 19 + <TabPanel
  20 + key="1"
  21 + tab="基本信息"
  22 + :forceRender="true"
  23 + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER"
  24 + >
  25 + <BaseFormPanel ref="baseFormPanelRef" :id="id" :businessUsers="businessUsers" />
21 </TabPanel> 26 </TabPanel>
22 <TabPanel 27 <TabPanel
23 key="2" 28 key="2"
@@ -25,7 +30,7 @@ @@ -25,7 +30,7 @@
25 :forceRender="true" 30 :forceRender="true"
26 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.BUSINESS)" 31 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.BUSINESS)"
27 > 32 >
28 - <ProfitFormPanel ref="profitFormPanelRef" :id="id" /> 33 + <ProfitFormPanel ref="profitFormPanelRef" :id="id" :profitFormData="profitFormData" />
29 </TabPanel> 34 </TabPanel>
30 <TabPanel 35 <TabPanel
31 key="3" 36 key="3"
@@ -33,7 +38,7 @@ @@ -33,7 +38,7 @@
33 :forceRender="true" 38 :forceRender="true"
34 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.BUSINESS)" 39 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.BUSINESS)"
35 > 40 >
36 - <ReportFormPanel ref="reportFormPanelRef" :id="id" /> 41 + <ReportFormPanel ref="reportFormPanelRef" :id="id" :reportFormData="reportFormData" />
37 </TabPanel> 42 </TabPanel>
38 <TabPanel 43 <TabPanel
39 key="4" 44 key="4"
@@ -41,7 +46,7 @@ @@ -41,7 +46,7 @@
41 :forceRender="true" 46 :forceRender="true"
42 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.TRACKER)" 47 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.TRACKER)"
43 > 48 >
44 - <TrackFormPanel ref="trackFormPanelRef" :id="id" /> 49 + <TrackFormPanel ref="trackFormPanelRef" :id="id" :trackFormData="trackFormData" />
45 </TabPanel> 50 </TabPanel>
46 <TabPanel 51 <TabPanel
47 key="5" 52 key="5"
@@ -49,7 +54,11 @@ @@ -49,7 +54,11 @@
49 :forceRender="true" 54 :forceRender="true"
50 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.INSPECT)" 55 v-if="!!id && (role === ROLE.ADMIN || role === ROLE.INSPECT)"
51 > 56 >
52 - <InspectionFormPanel ref="inspectionFormPanelRef" :id="id" /> 57 + <InspectionFormPanel
  58 + ref="inspectionFormPanelRef"
  59 + :id="id"
  60 + :inspectFormData="inspectFormData"
  61 + />
53 </TabPanel> 62 </TabPanel>
54 </Tabs> 63 </Tabs>
55 </div> 64 </div>
@@ -61,7 +70,7 @@ @@ -61,7 +70,7 @@
61 </BasicDrawer> 70 </BasicDrawer>
62 </template> 71 </template>
63 <script lang="ts"> 72 <script lang="ts">
64 - import { computed, defineComponent, reactive, ref, toRaw, watch, toRefs } from 'vue'; 73 + import { computed, defineComponent, reactive, ref, toRaw, watch, toRefs, onMounted } from 'vue';
65 import { FormActionType, FormSchema, useForm } from '/@/components/Form/index'; 74 import { FormActionType, FormSchema, useForm } from '/@/components/Form/index';
66 import { orderCreate, orderUpdate, uploadImg } from '/@/api/project/order'; 75 import { orderCreate, orderUpdate, uploadImg } from '/@/api/project/order';
67 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 76 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
@@ -73,8 +82,12 @@ @@ -73,8 +82,12 @@
73 import BaseFormPanel from './BaseFormPanel.vue'; 82 import BaseFormPanel from './BaseFormPanel.vue';
74 import { useUserStoreWithOut } from '/@/store/modules/user'; 83 import { useUserStoreWithOut } from '/@/store/modules/user';
75 import { ROLE } from '../type.d'; 84 import { ROLE } from '../type.d';
  85 + import { getList as getConfigList } from '/@/api/sys/config';
76 86
77 import { Tabs } from 'ant-design-vue'; 87 import { Tabs } from 'ant-design-vue';
  88 + import { find } from 'lodash-es';
  89 + import { getUserList } from '/@/api/project/account';
  90 + import message from '/@/views/form-design/utils/message';
78 91
79 const userStore = useUserStoreWithOut(); 92 const userStore = useUserStoreWithOut();
80 93
@@ -109,8 +122,33 @@ @@ -109,8 +122,33 @@
109 const trackFormPanelRef = ref(); 122 const trackFormPanelRef = ref();
110 const inspectionFormPanelRef = ref(); 123 const inspectionFormPanelRef = ref();
111 124
  125 + // 编辑从接口获取的value
  126 + const baseFormData = ref();
  127 + const profitFormData = ref();
  128 + const reportFormData = ref();
  129 + const trackFormData = ref();
  130 + const inspectFormData = ref();
  131 +
112 const formRef = ref<FormActionType | null>(null); 132 const formRef = ref<FormActionType | null>(null);
113 const id = ref(''); 133 const id = ref('');
  134 + const configList = ref([]);
  135 + const businessUsers = ref([]);
  136 +
  137 + onMounted(async () => {
  138 + // 获取包装费用和客户编码的关联关系
  139 + const res = await getConfigList({
  140 + page: 1,
  141 + pageSize: 1000,
  142 + // relationCode: 'packetPrice',
  143 + });
  144 + configList.value = res || [];
  145 +
  146 + // 获取业务员
  147 + const res1 = await getUserList({ page: 1, pageSize: 1000 });
  148 + businessUsers.value = res1.items
  149 + .filter((item) => item.roleCode === ROLE.BUSINESS)
  150 + .map((item) => ({ value: item.userName, label: item.userName }));
  151 + });
114 152
115 const role = computed(() => { 153 const role = computed(() => {
116 return userStore.getUserInfo?.roleSmallVO?.code; 154 return userStore.getUserInfo?.roleSmallVO?.code;
@@ -120,6 +158,8 @@ @@ -120,6 +158,8 @@
120 let fields = reactive({ baseFields: {} }); 158 let fields = reactive({ baseFields: {} });
121 159
122 const [register, { closeDrawer }] = useDrawerInner((data) => { 160 const [register, { closeDrawer }] = useDrawerInner((data) => {
  161 + activeKey.value =
  162 + role.value === ROLE.INSPECT ? '5' : role.value === ROLE.BUSINESS ? '2' : '1';
123 if (!data.id) { 163 if (!data.id) {
124 id.value = ''; 164 id.value = '';
125 picUrl.value = ''; 165 picUrl.value = '';
@@ -133,6 +173,10 @@ @@ -133,6 +173,10 @@
133 return; 173 return;
134 } 174 }
135 id.value = data.id; 175 id.value = data.id;
  176 + profitFormData.value = data.profitAnalysisInfo;
  177 + inspectFormData.value = data.inspectionStageInfo;
  178 + reportFormData.value = data.reportInfo;
  179 + trackFormData.value = data.trackStageInfo;
136 180
137 // 方式1 181 // 方式1
138 picUrl.value = data.picUrl; 182 picUrl.value = data.picUrl;
@@ -159,10 +203,22 @@ @@ -159,10 +203,22 @@
159 } 203 }
160 204
161 if (profitFormPanelRef.value) { 205 if (profitFormPanelRef.value) {
  206 + // 包装费用通过客户编码去查
  207 + const packetPrice = find(configList.value, (item) => {
  208 + return (
  209 + data.customerCode === item.settingValue && item.relationCode === 'packetPrice'
  210 + );
  211 + });
  212 +
  213 + const exchangeRate = find(configList.value, (item) => {
  214 + return item.settingCode === 'exchangeRate';
  215 + });
162 // 利润分析 216 // 利润分析
163 profitFormPanelRef.value.fields = { ...data.lockFields?.profitAnalysisFields } || {}; 217 profitFormPanelRef.value.fields = { ...data.lockFields?.profitAnalysisFields } || {};
164 profitFormPanelRef?.value?.setFieldsValue({ 218 profitFormPanelRef?.value?.setFieldsValue({
165 ...toRaw(data.profitAnalysisInfo), 219 ...toRaw(data.profitAnalysisInfo),
  220 + packetPrice: packetPrice?.relationValue || 0,
  221 + exchangeRate: exchangeRate?.settingValue,
166 }); 222 });
167 } 223 }
168 224
@@ -186,7 +242,7 @@ @@ -186,7 +242,7 @@
186 inspectionFormPanelRef.value.fields = 242 inspectionFormPanelRef.value.fields =
187 { ...data.lockFields?.inspectionStageFields } || {}; 243 { ...data.lockFields?.inspectionStageFields } || {};
188 inspectionFormPanelRef?.value?.setFieldsValue({ 244 inspectionFormPanelRef?.value?.setFieldsValue({
189 - ...toRaw(data.trackStageInfo), 245 + ...toRaw(data.inspectionStageInfo),
190 }); 246 });
191 } 247 }
192 }, 100); 248 }, 100);
@@ -196,10 +252,10 @@ @@ -196,10 +252,10 @@
196 }); 252 });
197 253
198 const handleSubmit = async () => { 254 const handleSubmit = async () => {
199 - if (id.value) {  
200 - const forms = { orderId: id.value } as any;  
201 - if (activeKey.value === '1') {  
202 - try { 255 + try {
  256 + if (id.value) {
  257 + const forms = { orderId: id.value } as any;
  258 + if (activeKey.value === '1') {
203 await baseFormPanelRef?.value?.validate(); 259 await baseFormPanelRef?.value?.validate();
204 260
205 forms.baseInfo = baseFormPanelRef?.value?.getFieldsValue() || {}; 261 forms.baseInfo = baseFormPanelRef?.value?.getFieldsValue() || {};
@@ -211,25 +267,36 @@ @@ -211,25 +267,36 @@
211 await orderUpdate(forms); 267 await orderUpdate(forms);
212 closeDrawer(); 268 closeDrawer();
213 emit('success', {}); 269 emit('success', {});
214 - } catch (error) {  
215 - console.log(error); 270 + } else {
  271 + if (activeKey.value === '2') {
  272 + await profitFormPanelRef?.value?.validate();
  273 + forms.profitAnalysisInfo = profitFormPanelRef?.value?.getFieldsValue() || {};
  274 + // 方式如果没有变化,默认方式1
  275 + if (!forms.profitAnalysisInfo.profitType) {
  276 + forms.profitAnalysisInfo.profitType = '0';
  277 + }
  278 + } else if (activeKey.value === '3') {
  279 + await reportFormPanelRef?.value?.validate();
  280 + // 比重相加等于1
  281 + const values = reportFormPanelRef?.value?.getFieldsValue() || {};
  282 + if (
  283 + values.ideaSourceRate + values.manualPreform1Rate + values.manualPreform2Rate !==
  284 + 1
  285 + ) {
  286 + return message.error('占比相加不等于1');
  287 + }
  288 +
  289 + forms.reportInfo = values;
  290 + } else if (activeKey.value === '4') {
  291 + forms.trackStageInfo = trackFormPanelRef?.value?.getFieldsValue() || {};
  292 + } else if (activeKey.value === '5') {
  293 + forms.inspectionStageInfo = inspectionFormPanelRef?.value?.getFieldsValue() || {};
  294 + }
  295 + await orderUpdate(forms);
  296 + closeDrawer();
  297 + emit('success', {});
216 } 298 }
217 } else { 299 } else {
218 - if (activeKey.value === '2') {  
219 - forms.profitAnalysisInfo = profitFormPanelRef?.value?.getFieldsValue() || {};  
220 - } else if (activeKey.value === '3') {  
221 - forms.reportInfo = reportFormPanelRef?.value?.getFieldsValue() || {};  
222 - } else if (activeKey.value === '4') {  
223 - forms.trackStageInfo = trackFormPanelRef?.value?.getFieldsValue() || {};  
224 - } else if (activeKey.value === '5') {  
225 - forms.inspectionStageInfo = inspectionFormPanelRef?.value?.getFieldsValue() || {};  
226 - }  
227 - await orderUpdate(forms);  
228 - closeDrawer();  
229 - emit('success', {});  
230 - }  
231 - } else {  
232 - try {  
233 await baseFormPanelRef?.value?.validate(); 300 await baseFormPanelRef?.value?.validate();
234 301
235 // 新建只有基本信息 302 // 新建只有基本信息
@@ -245,9 +312,9 @@ @@ -245,9 +312,9 @@
245 await orderCreate(forms); 312 await orderCreate(forms);
246 closeDrawer(); 313 closeDrawer();
247 emit('success', {}); 314 emit('success', {});
248 - } catch (error) {  
249 - console.log(error);  
250 } 315 }
  316 + } catch (error) {
  317 + console.log(error);
251 } 318 }
252 }; 319 };
253 return { 320 return {
@@ -261,16 +328,25 @@ @@ -261,16 +328,25 @@
261 formRef, 328 formRef,
262 ROLE, 329 ROLE,
263 role, 330 role,
  331 + profitFormData,
  332 + inspectFormData,
  333 + reportFormData,
  334 + trackFormData,
264 register, 335 register,
265 handleSubmit, 336 handleSubmit,
  337 + businessUsers,
266 }; 338 };
267 }, 339 },
268 }); 340 });
269 </script> 341 </script>
270 342
271 -<style scoped> 343 +<style>
272 .ant-drawer { 344 .ant-drawer {
273 position: fixed; 345 position: fixed;
274 z-index: 9999; 346 z-index: 9999;
275 } 347 }
  348 +
  349 + .order-drawer-panel .ant-picker {
  350 + width: 100% !important;
  351 + }
276 </style> 352 </style>
src/views/project/order/ProfitAnalysis.vue
@@ -4,9 +4,31 @@ @@ -4,9 +4,31 @@
4 destroyOnClose 4 destroyOnClose
5 @register="register" 5 @register="register"
6 title="利润分析表" 6 title="利润分析表"
  7 + width="600px"
7 @visible-change="handleShow" 8 @visible-change="handleShow"
8 :footer="null" 9 :footer="null"
9 > 10 >
  11 + <div className="mb-2">
  12 + 公示:
  13 + <Select
  14 + className="w-[200px]"
  15 + :options="[
  16 + { label: '公示1:1 -(LOCAL总金额 / 汇率 + 包装总金额)/客户总金额', value: '0' },
  17 + { label: '公示2:1 -(LOCAL总金额/汇率 / (客户总金额-包装费用总金额)', value: '1' },
  18 + ]"
  19 + v-model:value="profitType"
  20 + placeholder="请选择"
  21 + default-value="0"
  22 + />
  23 + </div>
  24 + <Space>
  25 + <span>
  26 + 汇率:
  27 + {{ activeRate }}
  28 + </span>
  29 + <a-button type="primary" @click="handleCalc" className="ml-4">计算</a-button>
  30 + </Space>
  31 + <!-- <Button @click="handleCalc">计算</Button> -->
10 <!-- :helpMessage="['提示1', '提示2']" --> 32 <!-- :helpMessage="['提示1', '提示2']" -->
11 <!-- <template #insertFooter> 33 <!-- <template #insertFooter>
12 <a-button type="primary" danger @click="setLines" :disabled="loading">点我更新内容</a-button> 34 <a-button type="primary" danger @click="setLines" :disabled="loading">点我更新内容</a-button>
@@ -25,24 +47,34 @@ @@ -25,24 +47,34 @@
25 </BasicModal> 47 </BasicModal>
26 </template> 48 </template>
27 <script lang="ts"> 49 <script lang="ts">
28 - import { defineComponent, ref, toRaw, watch } from 'vue'; 50 + import { computed, defineComponent, onMounted, ref, toRaw, watch } from 'vue';
29 import { BasicModal, useModalInner } from '/@/components/Modal'; 51 import { BasicModal, useModalInner } from '/@/components/Modal';
30 import { Description, DescItem, useDescription } from '/@/components/Description/index'; 52 import { Description, DescItem, useDescription } from '/@/components/Description/index';
31 import { orderAnalysis } from '/@/api/project/order'; 53 import { orderAnalysis } from '/@/api/project/order';
  54 + import { Select, Space } from 'ant-design-vue';
  55 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  56 + import { getList } from '/@/api/sys/config';
  57 + import { useOrderInfo } from '/@/hooks/component/order';
32 58
33 export default defineComponent({ 59 export default defineComponent({
34 - components: { BasicModal, Description }, 60 + components: { BasicModal, Description, Select, Space },
35 setup() { 61 setup() {
  62 + const orderStore = useOrderStoreWithOut();
  63 + const { exchangeRate } = useOrderInfo(orderStore);
  64 + const orderIds = ref([]);
36 const loading = ref(true); 65 const loading = ref(true);
37 const lines = ref(10); 66 const lines = ref(10);
  67 + const activeRate = ref();
  68 + const profitType = ref('1');
38 const info = ref({}); 69 const info = ref({});
39 const [register, { setModalProps, redoModalHeight }] = useModalInner(async (data) => { 70 const [register, { setModalProps, redoModalHeight }] = useModalInner(async (data) => {
40 - const orderIds = toRaw(data.data);  
41 - const res = await orderAnalysis({ orderIds }); 71 + orderIds.value = toRaw(data.data);
  72 + info.value = {};
  73 + });
42 74
43 - info.value = {  
44 - ...(res || {}),  
45 - }; 75 + onMounted(async () => {
  76 + const res = await getList({ settingCode: 'exchangeRate', page: 1, pageSize: 10 });
  77 + activeRate.value = res?.[0]?.settingValue;
46 }); 78 });
47 79
48 const schema: DescItem[] = [ 80 const schema: DescItem[] = [
@@ -75,18 +107,37 @@ @@ -75,18 +107,37 @@
75 if (visible) { 107 if (visible) {
76 loading.value = true; 108 loading.value = true;
77 // setModalProps({ loading: true, confirmLoading: true }); 109 // setModalProps({ loading: true, confirmLoading: true });
78 - setTimeout(() => {  
79 - lines.value = Math.round(Math.random() * 30 + 5);  
80 - loading.value = false;  
81 - setModalProps({ loading: false, confirmLoading: false });  
82 - }, 3000); 110 + setModalProps({ loading: false, confirmLoading: false });
83 } 111 }
84 } 112 }
85 113
86 function setLines() { 114 function setLines() {
87 lines.value = Math.round(Math.random() * 20 + 10); 115 lines.value = Math.round(Math.random() * 20 + 10);
88 } 116 }
89 - return { register, loading, handleShow, lines, setLines, info, schema }; 117 +
  118 + async function handleCalc() {
  119 + const res = await orderAnalysis({
  120 + orderIds: orderIds.value,
  121 + profitType: profitType.value,
  122 + exchangeRate: activeRate.value,
  123 + });
  124 + info.value = {
  125 + ...(res || {}),
  126 + };
  127 + }
  128 + return {
  129 + register,
  130 + loading,
  131 + handleShow,
  132 + lines,
  133 + setLines,
  134 + info,
  135 + schema,
  136 + exchangeRate,
  137 + handleCalc,
  138 + activeRate,
  139 + profitType,
  140 + };
90 }, 141 },
91 }); 142 });
92 </script> 143 </script>
src/views/project/order/RateModal.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + destroyOnClose
  5 + @register="register"
  6 + title="利润分析表"
  7 + width="600px"
  8 + @visible-change="handleShow"
  9 + :footer="null"
  10 + >
  11 + <Space>
  12 + <span>
  13 + 设计师:
  14 + <Select :options="manualPreform" placeholder="请选择" v-model:value="activeUser" />
  15 + </span>
  16 + <a-button type="primary" @click="handleCalc" className="ml-4">计算</a-button>
  17 + </Space>
  18 + <div className="mt-2">比重结果:{{ info }}</div>
  19 + </BasicModal>
  20 +</template>
  21 +<script lang="ts">
  22 + import { defineComponent, ref } from 'vue';
  23 + import { BasicModal, useModalInner } from '/@/components/Modal';
  24 + import { orderGravity } from '/@/api/project/order';
  25 + import { Select, Space } from 'ant-design-vue';
  26 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  27 + import { useOrderInfo } from '/@/hooks/component/order';
  28 +
  29 + export default defineComponent({
  30 + components: { BasicModal, Select, Space },
  31 + setup() {
  32 + const orderStore = useOrderStoreWithOut();
  33 + const { manualPreform, exchangeRate } = useOrderInfo(orderStore);
  34 +
  35 + const loading = ref(true);
  36 + const activeUser = ref();
  37 + const info = ref();
  38 + const searchData = ref({});
  39 + const [register, { setModalProps }] = useModalInner(async (data) => {
  40 + searchData.value = data.data || {};
  41 + activeUser.value = undefined;
  42 + info.value = '';
  43 + });
  44 +
  45 + function handleShow(visible: boolean) {
  46 + if (visible) {
  47 + loading.value = true;
  48 + // setModalProps({ loading: true, confirmLoading: true });
  49 + setModalProps({ loading: false, confirmLoading: false });
  50 + }
  51 + }
  52 +
  53 + async function handleCalc() {
  54 + const res = await orderGravity({
  55 + ...searchData.value,
  56 + designer: activeUser.value,
  57 + });
  58 + info.value = res?.rate || 0;
  59 + }
  60 + return {
  61 + register,
  62 + loading,
  63 + handleShow,
  64 + info,
  65 + manualPreform,
  66 + handleCalc,
  67 + activeUser,
  68 + exchangeRate,
  69 + };
  70 + },
  71 + });
  72 +</script>
  73 +<style scoped>
  74 + .empty-tips {
  75 + height: 100px;
  76 + line-height: 100px;
  77 + text-align: center;
  78 + }
  79 +</style>
src/views/project/order/index.vue
@@ -33,41 +33,56 @@ @@ -33,41 +33,56 @@
33 <TableAction 33 <TableAction
34 :actions="[ 34 :actions="[
35 { 35 {
36 - label: '编辑',  
37 - // icon: 'ic:outline-delete-outline',  
38 - onClick: handleEdit.bind(null, record), 36 + // 数据分析没有编辑权限
  37 + ...(role !== ROLE.DATA_REPORT_USER && {
  38 + label: '编辑',
  39 + // icon: 'ic:outline-delete-outline',
  40 + onClick: handleEdit.bind(null, record),
  41 + }),
39 }, 42 },
40 { 43 {
41 - label: '申请权限',  
42 - // icon: 'ic:outline-delete-outline',  
43 - onClick: handleCheck.bind(null, record),  
44 - },  
45 - ]"  
46 - :dropDownActions="[  
47 - {  
48 - label: '历史记录',  
49 - onClick: handleHistory.bind(null, record), 44 + ...(role !== ROLE.DATA_REPORT_USER && {
  45 + label: '申请权限',
  46 + // icon: 'ic:outline-delete-outline',
  47 + onClick: handleCheck.bind(null, record),
  48 + }),
50 }, 49 },
51 ]" 50 ]"
  51 + :dropDownActions="
  52 + role !== ROLE.DATA_REPORT_USER
  53 + ? [
  54 + {
  55 + label: '历史记录',
  56 + onClick: handleHistory.bind(null, record),
  57 + },
  58 + ]
  59 + : []
  60 + "
52 /> 61 />
53 </template> 62 </template>
54 <template v-if="column.key === 'picUrl'"> 63 <template v-if="column.key === 'picUrl'">
55 <img 64 <img
56 :width="100" 65 :width="100"
57 :height="100" 66 :height="100"
58 - :src="record.picUrl"  
59 - :key="record.picUrl" 67 + :src="record.smallPicUrl"
  68 + :key="record.smallPicUrl"
60 @click="handlePreview(record.picUrl)" 69 @click="handlePreview(record.picUrl)"
61 /> 70 />
62 </template> 71 </template>
63 </template> 72 </template>
64 73
65 <template #toolbar> 74 <template #toolbar>
66 - <a-button type="primary" @click="handleExport">导出</a-button> 75 + <a-button type="primary" @click="handleRateModal">比重计算</a-button>
  76 + <a-button type="primary" @click="handleExportModal">导出</a-button>
67 <a-button type="primary" @click="handleProfitModal" :disabled="!checkedKeys.length" 77 <a-button type="primary" @click="handleProfitModal" :disabled="!checkedKeys.length"
68 >分析利润</a-button 78 >分析利润</a-button
69 > 79 >
70 - <a-button type="primary" @click="handleAdd">创建订单</a-button> 80 + <a-button
  81 + type="primary"
  82 + @click="handleAdd"
  83 + v-if="role !== ROLE.INSPECT && role !== ROLE.DATA_REPORT_USER"
  84 + >创建订单</a-button
  85 + >
71 </template> 86 </template>
72 </BasicTable> 87 </BasicTable>
73 <FormDetail 88 <FormDetail
@@ -76,13 +91,15 @@ @@ -76,13 +91,15 @@
76 @success="handleFormSuccess" 91 @success="handleFormSuccess"
77 /> 92 />
78 <ProfitAnalysis @register="profitModalRegister" /> 93 <ProfitAnalysis @register="profitModalRegister" />
  94 + <RateModal @register="rateModalRegister" />
  95 + <ExportModal @register="exportModalRegister" :role="role" />
79 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> 96 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" />
80 <HistoryDetail @register="historyDetailRegister" /> 97 <HistoryDetail @register="historyDetailRegister" />
81 <FieldDetail @register="fieldDetailRegister" /> 98 <FieldDetail @register="fieldDetailRegister" />
82 </div> 99 </div>
83 </template> 100 </template>
84 <script lang="ts"> 101 <script lang="ts">
85 - import { defineComponent, onMounted, ref, toRaw, toRefs, unref } from 'vue'; 102 + import { defineComponent, onMounted, ref, toRaw, computed } from 'vue';
86 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 103 import { BasicTable, useTable, TableAction } from '/@/components/Table';
87 import { FormOutlined } from '@ant-design/icons-vue'; 104 import { FormOutlined } from '@ant-design/icons-vue';
88 import HeaderCell from '/@/components/Table/src/components/HeaderCell.vue'; 105 import HeaderCell from '/@/components/Table/src/components/HeaderCell.vue';
@@ -90,6 +107,8 @@ @@ -90,6 +107,8 @@
90 107
91 import { useDrawer } from '/@/components/Drawer'; 108 import { useDrawer } from '/@/components/Drawer';
92 import ProfitAnalysis from './ProfitAnalysis.vue'; 109 import ProfitAnalysis from './ProfitAnalysis.vue';
  110 + import RateModal from './RateModal.vue';
  111 + import ExportModal from './ExportModal.vue';
93 import { useModal } from '/@/components/Modal'; 112 import { useModal } from '/@/components/Modal';
94 113
95 import { getFormConfig, getOrderColumns, SELECT_FIELD_COLUMNS } from './tableData'; 114 import { getFormConfig, getOrderColumns, SELECT_FIELD_COLUMNS } from './tableData';
@@ -98,10 +117,10 @@ @@ -98,10 +117,10 @@
98 import HistoryDetail from './HistoryDetail.vue'; 117 import HistoryDetail from './HistoryDetail.vue';
99 import FieldDetail from './FieldDetail.vue'; 118 import FieldDetail from './FieldDetail.vue';
100 import { createImgPreview } from '/@/components/Preview/index'; 119 import { createImgPreview } from '/@/components/Preview/index';
101 - import { getOrderList, orderExport } from '/@/api/project/order'; 120 + import { getOrderList } from '/@/api/project/order';
102 import { useOrderStoreWithOut } from '/@/store/modules/order'; 121 import { useOrderStoreWithOut } from '/@/store/modules/order';
103 - import { keyBy, reduce } from 'lodash-es';  
104 import { useUserStoreWithOut } from '/@/store/modules/user'; 122 import { useUserStoreWithOut } from '/@/store/modules/user';
  123 + import { ROLE } from './type.d';
105 124
106 const orderStore = useOrderStoreWithOut(); 125 const orderStore = useOrderStoreWithOut();
107 const userStore = useUserStoreWithOut(); 126 const userStore = useUserStoreWithOut();
@@ -118,16 +137,24 @@ @@ -118,16 +137,24 @@
118 CheckDetail, 137 CheckDetail,
119 HistoryDetail, 138 HistoryDetail,
120 FieldDetail, 139 FieldDetail,
  140 + RateModal,
  141 + ExportModal,
121 }, 142 },
122 setup() { 143 setup() {
123 const checkedKeys = ref<Array<string | number>>([]); 144 const checkedKeys = ref<Array<string | number>>([]);
124 const [profitModalRegister, { openModal: openProfitModal }] = useModal(); 145 const [profitModalRegister, { openModal: openProfitModal }] = useModal();
  146 + const [rateModalRegister, { openModal: openRateModal }] = useModal();
  147 + const [exportModalRegister, { openModal: openExportModal }] = useModal();
  148 +
125 const tooltipVisible = ref(false); 149 const tooltipVisible = ref(false);
126 const [formDetailRegister, { openDrawer: openFormDetailDrawer }] = useDrawer(); 150 const [formDetailRegister, { openDrawer: openFormDetailDrawer }] = useDrawer();
127 const [historyDetailRegister, { openDrawer: openHistoryDetailDrawer }] = useDrawer(); 151 const [historyDetailRegister, { openDrawer: openHistoryDetailDrawer }] = useDrawer();
128 const [fieldDetailRegister, { openDrawer: openFieldDetailDrawer }] = useDrawer(); 152 const [fieldDetailRegister, { openDrawer: openFieldDetailDrawer }] = useDrawer();
129 153
130 const user = userStore.getUserInfo; 154 const user = userStore.getUserInfo;
  155 + const role = computed(() => {
  156 + return user?.roleSmallVO?.code;
  157 + });
131 158
132 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); 159 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
133 onMounted(async () => { 160 onMounted(async () => {
@@ -211,6 +238,15 @@ @@ -211,6 +238,15 @@
211 }); 238 });
212 } 239 }
213 240
  241 + function handleRateModal() {
  242 + const form = getForm();
  243 + const values = form.getFieldsValue();
  244 +
  245 + openRateModal(true, {
  246 + data: values,
  247 + });
  248 + }
  249 +
214 function handleFieldVisible(record) { 250 function handleFieldVisible(record) {
215 openFieldDetailDrawer(true, record); 251 openFieldDetailDrawer(true, record);
216 } 252 }
@@ -225,74 +261,15 @@ @@ -225,74 +261,15 @@
225 openFormDetailDrawer(true); 261 openFormDetailDrawer(true);
226 } 262 }
227 263
228 - function handlePreview(url, e) { 264 + function handlePreview(url) {
229 createImgPreview({ imageList: [url], defaultWidth: 500 }); 265 createImgPreview({ imageList: [url], defaultWidth: 500 });
230 // e?.stopPropagation(); 266 // e?.stopPropagation();
231 // e?.preventDefault(); 267 // e?.preventDefault();
232 return false; 268 return false;
233 } 269 }
234 270
235 - async function handleExport() {  
236 - const columns = getColumns();  
237 - const colObj = keyBy(columns, 'dataIndex');  
238 - const {  
239 - trackStageInfo,  
240 - reportInfo,  
241 - profitAnalysisInfo,  
242 - inspectionStageInfo,  
243 - ...baseFields  
244 - } = colObj;  
245 -  
246 - for (const key in baseFields) {  
247 - baseFields[key] = 'selected';  
248 - }  
249 - delete baseFields.action;  
250 -  
251 - const fieldVO = {  
252 - baseFields,  
253 - profitAnalysisFields: profitAnalysisInfo?.children?.length  
254 - ? reduce(  
255 - profitAnalysisInfo.children,  
256 - (result, item) => {  
257 - result[item.dataIndex] = 'selected';  
258 - return result;  
259 - },  
260 - {},  
261 - )  
262 - : {},  
263 - reportFields: reportInfo?.children?.length  
264 - ? reduce(  
265 - reportInfo.children,  
266 - (result, item) => {  
267 - result[item.dataIndex] = 'selected';  
268 - return result;  
269 - },  
270 - {},  
271 - )  
272 - : {},  
273 - trackStageFields: trackStageInfo?.children?.length  
274 - ? reduce(  
275 - trackStageInfo.children,  
276 - (result, item) => {  
277 - result[item.dataIndex] = 'selected';  
278 - return result;  
279 - },  
280 - {},  
281 - )  
282 - : {},  
283 - inspectionStageFields: inspectionStageInfo?.children?.length  
284 - ? reduce(  
285 - inspectionStageInfo.children,  
286 - (result, item) => {  
287 - result[item.dataIndex] = 'selected';  
288 - return result;  
289 - },  
290 - {},  
291 - )  
292 - : {},  
293 - };  
294 -  
295 - await orderExport({ fieldVO }); 271 + async function handleExportModal() {
  272 + openExportModal(true);
296 } 273 }
297 274
298 const handleFormSuccess = () => { 275 const handleFormSuccess = () => {
@@ -300,9 +277,12 @@ @@ -300,9 +277,12 @@
300 }; 277 };
301 278
302 return { 279 return {
  280 + user,
303 SELECT_FIELD_COLUMNS, 281 SELECT_FIELD_COLUMNS,
304 fieldDetailRegister, 282 fieldDetailRegister,
305 profitModalRegister, 283 profitModalRegister,
  284 + rateModalRegister,
  285 + exportModalRegister,
306 historyDetailRegister, 286 historyDetailRegister,
307 formDetailRegister, 287 formDetailRegister,
308 handleProfitModal, 288 handleProfitModal,
@@ -321,9 +301,13 @@ @@ -321,9 +301,13 @@
321 handleHistory, 301 handleHistory,
322 handleAdd, 302 handleAdd,
323 createImgPreview, 303 createImgPreview,
324 - handleExport, 304 + handleExportModal,
325 handlePreview, 305 handlePreview,
326 handleFormSuccess, 306 handleFormSuccess,
  307 + handleRateModal,
  308 + openExportModal,
  309 + role,
  310 + ROLE,
327 }; 311 };
328 }, 312 },
329 }); 313 });
@@ -337,12 +321,17 @@ @@ -337,12 +321,17 @@
337 } 321 }
338 322
339 .ant-table-cell img { 323 .ant-table-cell img {
340 - width: 100px;  
341 - height: 100px; 324 + width: 40px;
  325 + height: 40px;
342 } 326 }
343 327
344 .order-page .vben-basic-table .ant-form-item .ant-picker { 328 .order-page .vben-basic-table .ant-form-item .ant-picker {
345 width: 100%; 329 width: 100%;
346 } 330 }
  331 +
  332 + .order-page .ant-table.ant-table-middle .ant-table-tbody > tr > td {
  333 + padding-top: 0;
  334 + padding-bottom: 0;
  335 + }
347 </style> 336 </style>
348 ./constant 337 ./constant
src/views/project/order/tableData.tsx
1 import { ROLE } from './type.d'; 1 import { ROLE } from './type.d';
2 import { useOrderInfo } from '/@/hooks/component/order'; 2 import { useOrderInfo } from '/@/hooks/component/order';
3 import { useOrderStoreWithOut } from '/@/store/modules/order'; 3 import { useOrderStoreWithOut } from '/@/store/modules/order';
  4 +import { formatToDate } from '/@/utils/dateUtil';
4 5
5 // 角色 6 // 角色
6 // 业务员- 查看all,编辑-利润分析,报告书 7 // 业务员- 查看all,编辑-利润分析,报告书
@@ -11,21 +12,27 @@ import { useOrderStoreWithOut } from &#39;/@/store/modules/order&#39;; @@ -11,21 +12,27 @@ import { useOrderStoreWithOut } from &#39;/@/store/modules/order&#39;;
11 export const SELECT_FIELD_COLUMNS = [ 12 export const SELECT_FIELD_COLUMNS = [
12 'projectNo', 13 'projectNo',
13 'customerCode', 14 'customerCode',
  15 + 'productionDepartment',
14 'innerNo', 16 'innerNo',
15 'poColor', 17 'poColor',
16 'cnColor', 18 'cnColor',
17 'productStyle', 19 'productStyle',
18 'outboundType', 20 'outboundType',
19 'packetType', 21 'packetType',
  22 + 'ideaSource',
  23 + 'manualPreform1',
  24 + 'manualPreform2',
20 'midCheckResult', 25 'midCheckResult',
21 'endCheckResult', 26 'endCheckResult',
  27 + // 'exchangeRate',
  28 + 'businessPerson',
22 ]; 29 ];
23 30
24 /** 31 /**
25 * 32 *
26 * @returns 订单列表数据 33 * @returns 订单列表数据
27 */ 34 */
28 -const ORDER_LIST_BASE_FIELDS = [ 35 +export const ORDER_LIST_BASE_FIELDS = [
29 { 36 {
30 title: '客户编码', 37 title: '客户编码',
31 width: 150, 38 width: 150,
@@ -110,11 +117,19 @@ const ORDER_LIST_BASE_FIELDS = [ @@ -110,11 +117,19 @@ const ORDER_LIST_BASE_FIELDS = [
110 title: '生成科拖货时间', 117 title: '生成科拖货时间',
111 width: 150, 118 width: 150,
112 dataIndex: 'productionDepartmentConsignTime', 119 dataIndex: 'productionDepartmentConsignTime',
  120 + customRender: (column) => {
  121 + const { record } = column || {};
  122 + return formatToDate(record?.productionDepartmentConsignTime);
  123 + },
113 }, 124 },
114 { 125 {
115 title: '订单上HOD时间', 126 title: '订单上HOD时间',
116 width: 150, 127 width: 150,
117 dataIndex: 'orderHodTime', 128 dataIndex: 'orderHodTime',
  129 + customRender: (column) => {
  130 + const { record } = column || {};
  131 + return formatToDate(record?.orderHodTime);
  132 + },
118 }, 133 },
119 { 134 {
120 title: '出库类型', 135 title: '出库类型',
@@ -126,9 +141,14 @@ const ORDER_LIST_BASE_FIELDS = [ @@ -126,9 +141,14 @@ const ORDER_LIST_BASE_FIELDS = [
126 width: 150, 141 width: 150,
127 dataIndex: 'packetType', 142 dataIndex: 'packetType',
128 }, 143 },
  144 + {
  145 + title: '业务员',
  146 + width: 150,
  147 + dataIndex: 'businessPerson',
  148 + },
129 ]; 149 ];
130 150
131 -const ORDER_LIST_REPORT_FIELDS = [ 151 +export const ORDER_LIST_REPORT_FIELDS = [
132 { 152 {
133 title: '项目完成报告信息', 153 title: '项目完成报告信息',
134 width: 150, 154 width: 150,
@@ -137,35 +157,62 @@ const ORDER_LIST_REPORT_FIELDS = [ @@ -137,35 +157,62 @@ const ORDER_LIST_REPORT_FIELDS = [
137 { 157 {
138 title: '想法来源', 158 title: '想法来源',
139 width: 150, 159 width: 150,
140 - dataIndex: 'reportInfo.ideaSource', 160 + dataIndex: 'ideaSource',
141 customRender: (column) => { 161 customRender: (column) => {
142 const { record } = column || {}; 162 const { record } = column || {};
143 return record?.reportInfo?.ideaSource; 163 return record?.reportInfo?.ideaSource;
144 }, 164 },
145 }, 165 },
146 { 166 {
147 - title: '手工初型', 167 + title: '想法来源占比',
  168 + width: 150,
  169 + dataIndex: 'ideaSourceRate',
  170 + customRender: (column) => {
  171 + const { record } = column || {};
  172 + return record?.reportInfo?.ideaSourceRate;
  173 + },
  174 + },
  175 + {
  176 + title: '手工初型1',
  177 + width: 150,
  178 + dataIndex: 'manualPreform1',
  179 + customRender: (column) => {
  180 + const { record } = column || {};
  181 + return record?.reportInfo?.manualPreform1;
  182 + },
  183 + },
  184 + {
  185 + title: '手工初型1占比',
  186 + width: 150,
  187 + dataIndex: 'manualPreform1Rate',
  188 + customRender: (column) => {
  189 + const { record } = column || {};
  190 + return record?.reportInfo?.manualPreform1Rate;
  191 + },
  192 + },
  193 + {
  194 + title: '手工初型2',
148 width: 150, 195 width: 150,
149 - dataIndex: 'reportInfo.manualPreform', 196 + dataIndex: 'manualPreform2',
150 customRender: (column) => { 197 customRender: (column) => {
151 const { record } = column || {}; 198 const { record } = column || {};
152 - return record?.reportInfo?.manualPreform; 199 + return record?.reportInfo?.manualPreform2;
153 }, 200 },
154 }, 201 },
155 { 202 {
156 - title: '想法和手工比例分配', 203 + title: '手工初型2占比',
157 width: 150, 204 width: 150,
158 - dataIndex: 'reportInfo.ideaManualRate', 205 + dataIndex: 'manualPreform2Rate',
159 customRender: (column) => { 206 customRender: (column) => {
160 const { record } = column || {}; 207 const { record } = column || {};
161 - return record?.reportInfo?.ideaManualRate; 208 + return record?.reportInfo?.manualPreform2Rate;
162 }, 209 },
163 }, 210 },
164 ], 211 ],
165 }, 212 },
166 ]; 213 ];
167 214
168 -const ORDER_LIST_PROFIT_FIELDS = [ 215 +export const ORDER_LIST_PROFIT_FIELDS = [
169 { 216 {
170 title: '利润分析信息', 217 title: '利润分析信息',
171 width: 150, 218 width: 150,
@@ -177,7 +224,9 @@ const ORDER_LIST_PROFIT_FIELDS = [ @@ -177,7 +224,9 @@ const ORDER_LIST_PROFIT_FIELDS = [
177 dataIndex: 'customerPrice', 224 dataIndex: 'customerPrice',
178 customRender: (column) => { 225 customRender: (column) => {
179 const { record } = column || {}; 226 const { record } = column || {};
180 - return record?.profitAnalysisInfo?.customerPrice; 227 + return `${record?.profitAnalysisInfo?.customerCurrency || ''} ${
  228 + record?.profitAnalysisInfo?.customerPrice || ''
  229 + }`;
181 }, 230 },
182 }, 231 },
183 { 232 {
@@ -195,7 +244,18 @@ const ORDER_LIST_PROFIT_FIELDS = [ @@ -195,7 +244,18 @@ const ORDER_LIST_PROFIT_FIELDS = [
195 dataIndex: 'productionDepartmentPrice', 244 dataIndex: 'productionDepartmentPrice',
196 customRender: (column) => { 245 customRender: (column) => {
197 const { record } = column || {}; 246 const { record } = column || {};
198 - return record?.profitAnalysisInfo?.productionDepartmentPrice; 247 + return `${record?.profitAnalysisInfo?.productionDepartmentCurrency || ''} ${
  248 + record?.profitAnalysisInfo?.productionDepartmentPrice || ''
  249 + }`;
  250 + },
  251 + },
  252 + {
  253 + title: '生成科总价',
  254 + width: 150,
  255 + dataIndex: 'productionDepartmentTotalPrice',
  256 + customRender: (column) => {
  257 + const { record } = column || {};
  258 + return record?.profitAnalysisInfo?.productionDepartmentTotalPrice;
199 }, 259 },
200 }, 260 },
201 { 261 {
@@ -204,7 +264,9 @@ const ORDER_LIST_PROFIT_FIELDS = [ @@ -204,7 +264,9 @@ const ORDER_LIST_PROFIT_FIELDS = [
204 dataIndex: 'packetPrice', 264 dataIndex: 'packetPrice',
205 customRender: (column) => { 265 customRender: (column) => {
206 const { record } = column || {}; 266 const { record } = column || {};
207 - return record?.profitAnalysisInfo?.packetPrice; 267 + return `${record?.profitAnalysisInfo?.packetCurrency || ''} ${
  268 + record?.profitAnalysisInfo?.packetPrice || ''
  269 + }`;
208 }, 270 },
209 }, 271 },
210 { 272 {
@@ -234,11 +296,24 @@ const ORDER_LIST_PROFIT_FIELDS = [ @@ -234,11 +296,24 @@ const ORDER_LIST_PROFIT_FIELDS = [
234 return record?.profitAnalysisInfo?.profitRate; 296 return record?.profitAnalysisInfo?.profitRate;
235 }, 297 },
236 }, 298 },
  299 + {
  300 + title: '利润率计算方式',
  301 + width: 150,
  302 + dataIndex: 'profitRate',
  303 + customRender: (column) => {
  304 + const { record } = column || {};
  305 + return record?.profitAnalysisInfo?.profitType === '0'
  306 + ? '方式1'
  307 + : record?.profitAnalysisInfo?.profitType === '1'
  308 + ? '方式2'
  309 + : '';
  310 + },
  311 + },
237 ], 312 ],
238 }, 313 },
239 ]; 314 ];
240 315
241 -const ORDER_LIST_TRACK_FIELDS = [ 316 +export const ORDER_LIST_TRACK_FIELDS = [
242 { 317 {
243 title: '跟单信息', 318 title: '跟单信息',
244 width: 150, 319 width: 150,
@@ -250,7 +325,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -250,7 +325,7 @@ const ORDER_LIST_TRACK_FIELDS = [
250 dataIndex: 'ppTime', 325 dataIndex: 'ppTime',
251 customRender: (column) => { 326 customRender: (column) => {
252 const { record } = column || {}; 327 const { record } = column || {};
253 - return record?.trackStageInfo?.ppTime; 328 + return formatToDate(record?.trackStageInfo?.ppTime);
254 }, 329 },
255 }, 330 },
256 { 331 {
@@ -268,7 +343,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -268,7 +343,7 @@ const ORDER_LIST_TRACK_FIELDS = [
268 dataIndex: 'esoSampleSendTime', 343 dataIndex: 'esoSampleSendTime',
269 customRender: (column) => { 344 customRender: (column) => {
270 const { record } = column || {}; 345 const { record } = column || {};
271 - return record?.trackStageInfo?.esoSampleSendTime; 346 + return formatToDate(record?.trackStageInfo?.esoSampleSendTime);
272 }, 347 },
273 }, 348 },
274 { 349 {
@@ -277,7 +352,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -277,7 +352,7 @@ const ORDER_LIST_TRACK_FIELDS = [
277 dataIndex: 'shippmentSampleSendTime', 352 dataIndex: 'shippmentSampleSendTime',
278 customRender: (column) => { 353 customRender: (column) => {
279 const { record } = column || {}; 354 const { record } = column || {};
280 - return record?.trackStageInfo?.shippmentSampleSendTime; 355 + return formatToDate(record?.trackStageInfo?.shippmentSampleSendTime);
281 }, 356 },
282 }, 357 },
283 { 358 {
@@ -295,7 +370,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -295,7 +370,7 @@ const ORDER_LIST_TRACK_FIELDS = [
295 dataIndex: 'selfTestPassTime', 370 dataIndex: 'selfTestPassTime',
296 customRender: (column) => { 371 customRender: (column) => {
297 const { record } = column || {}; 372 const { record } = column || {};
298 - return record?.trackStageInfo?.selfTestPassTime; 373 + return formatToDate(record?.trackStageInfo?.selfTestPassTime);
299 }, 374 },
300 }, 375 },
301 { 376 {
@@ -304,7 +379,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -304,7 +379,7 @@ const ORDER_LIST_TRACK_FIELDS = [
304 dataIndex: 'aitexTestSendTime', 379 dataIndex: 'aitexTestSendTime',
305 customRender: (column) => { 380 customRender: (column) => {
306 const { record } = column || {}; 381 const { record } = column || {};
307 - return record?.trackStageInfo?.aitexTestSendTime; 382 + return formatToDate(record?.trackStageInfo?.aitexTestSendTime);
308 }, 383 },
309 }, 384 },
310 { 385 {
@@ -322,7 +397,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -322,7 +397,7 @@ const ORDER_LIST_TRACK_FIELDS = [
322 dataIndex: 'sgsTestSendTime', 397 dataIndex: 'sgsTestSendTime',
323 customRender: (column) => { 398 customRender: (column) => {
324 const { record } = column || {}; 399 const { record } = column || {};
325 - return record?.trackStageInfo?.sgsTestSendTime; 400 + return formatToDate(record?.trackStageInfo?.sgsTestSendTime);
326 }, 401 },
327 }, 402 },
328 { 403 {
@@ -349,7 +424,7 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -349,7 +424,7 @@ const ORDER_LIST_TRACK_FIELDS = [
349 dataIndex: 'latestArrivalTime', 424 dataIndex: 'latestArrivalTime',
350 customRender: (column) => { 425 customRender: (column) => {
351 const { record } = column || {}; 426 const { record } = column || {};
352 - return record?.trackStageInfo?.latestArrivalTime; 427 + return formatToDate(record?.trackStageInfo?.latestArrivalTime);
353 }, 428 },
354 }, 429 },
355 { 430 {
@@ -358,14 +433,14 @@ const ORDER_LIST_TRACK_FIELDS = [ @@ -358,14 +433,14 @@ const ORDER_LIST_TRACK_FIELDS = [
358 dataIndex: 'latestBkTime', 433 dataIndex: 'latestBkTime',
359 customRender: (column) => { 434 customRender: (column) => {
360 const { record } = column || {}; 435 const { record } = column || {};
361 - return record?.trackStageInfo?.latestBkTime; 436 + return formatToDate(record?.trackStageInfo?.latestBkTime);
362 }, 437 },
363 }, 438 },
364 ], 439 ],
365 }, 440 },
366 ]; 441 ];
367 442
368 -const ORDER_LIST_INSPECT_FIELDS = [ 443 +export const ORDER_LIST_INSPECT_FIELDS = [
369 { 444 {
370 title: '质检信息', 445 title: '质检信息',
371 width: 150, 446 width: 150,
@@ -378,7 +453,7 @@ const ORDER_LIST_INSPECT_FIELDS = [ @@ -378,7 +453,7 @@ const ORDER_LIST_INSPECT_FIELDS = [
378 dataIndex: 'midCheckApplyTime', 453 dataIndex: 'midCheckApplyTime',
379 customRender: (column) => { 454 customRender: (column) => {
380 const { record } = column || {}; 455 const { record } = column || {};
381 - return record?.inspectionStageInfo?.midCheckApplyTime; 456 + return formatToDate(record?.inspectionStageInfo?.midCheckApplyTime);
382 }, 457 },
383 }, 458 },
384 { 459 {
@@ -405,7 +480,7 @@ const ORDER_LIST_INSPECT_FIELDS = [ @@ -405,7 +480,7 @@ const ORDER_LIST_INSPECT_FIELDS = [
405 dataIndex: 'endCheckApplyTime', 480 dataIndex: 'endCheckApplyTime',
406 customRender: (column) => { 481 customRender: (column) => {
407 const { record } = column || {}; 482 const { record } = column || {};
408 - return record?.inspectionStageInfo?.endCheckApplyTime; 483 + return formatToDate(record?.inspectionStageInfo?.endCheckApplyTime);
409 }, 484 },
410 }, 485 },
411 { 486 {
@@ -493,7 +568,9 @@ const ORDER_LIST_SCHEDULE = [ @@ -493,7 +568,9 @@ const ORDER_LIST_SCHEDULE = [
493 }, 568 },
494 ]; 569 ];
495 570
  571 +// 订单列表,也就是读权限
496 export function getOrderColumns(role: ROLE) { 572 export function getOrderColumns(role: ROLE) {
  573 + // 管理员/业务员看到所有列
497 if (role === ROLE.ADMIN || role === ROLE.BUSINESS) { 574 if (role === ROLE.ADMIN || role === ROLE.BUSINESS) {
498 return [ 575 return [
499 ...ORDER_LIST_BASE_FIELDS, 576 ...ORDER_LIST_BASE_FIELDS,
@@ -504,15 +581,16 @@ export function getOrderColumns(role: ROLE) { @@ -504,15 +581,16 @@ export function getOrderColumns(role: ROLE) {
504 ...ORDER_LIST_SCHEDULE, 581 ...ORDER_LIST_SCHEDULE,
505 ]; 582 ];
506 } 583 }
507 - 584 + // 跟单 -基本信息-利润分析(单价,总价),跟单,质检
508 if (role === ROLE.TRACKER) { 585 if (role === ROLE.TRACKER) {
509 return [ 586 return [
510 ...ORDER_LIST_BASE_FIELDS, 587 ...ORDER_LIST_BASE_FIELDS,
511 ...ORDER_LIST_PROFIT_FIELDS.map((item) => { 588 ...ORDER_LIST_PROFIT_FIELDS.map((item) => {
512 const children = item.children.filter( 589 const children = item.children.filter(
513 - (k) => k.dataIndex !== 'exchangeRate' && k.dataIndex !== 'profitRate', 590 + (k) => k.dataIndex === 'customerPrice' || k.dataIndex === 'customerTotalPrice',
514 ); 591 );
515 item.children = children; 592 item.children = children;
  593 +
516 return item; 594 return item;
517 }), 595 }),
518 ...ORDER_LIST_TRACK_FIELDS, 596 ...ORDER_LIST_TRACK_FIELDS,
@@ -521,7 +599,8 @@ export function getOrderColumns(role: ROLE) { @@ -521,7 +599,8 @@ export function getOrderColumns(role: ROLE) {
521 ]; 599 ];
522 } 600 }
523 601
524 - if (role === ROLE.INSPECT) { 602 + // 质检-基本,跟单,质检
  603 + if (role === ROLE.INSPECT || role === ROLE.DATA_REPORT_USER) {
525 return [ 604 return [
526 ...ORDER_LIST_BASE_FIELDS, 605 ...ORDER_LIST_BASE_FIELDS,
527 ...ORDER_LIST_TRACK_FIELDS, 606 ...ORDER_LIST_TRACK_FIELDS,
@@ -532,7 +611,9 @@ export function getOrderColumns(role: ROLE) { @@ -532,7 +611,9 @@ export function getOrderColumns(role: ROLE) {
532 611
533 return []; 612 return [];
534 } 613 }
535 - 614 +/**
  615 + * drawer面板的字段
  616 + */
536 // 基本信息 617 // 基本信息
537 export const FIELDS_BASE_INFO = [ 618 export const FIELDS_BASE_INFO = [
538 { 619 {
@@ -670,6 +751,13 @@ export const FIELDS_BASE_INFO = [ @@ -670,6 +751,13 @@ export const FIELDS_BASE_INFO = [
670 label: '包装类型', 751 label: '包装类型',
671 rules: [{ required: true }], 752 rules: [{ required: true }],
672 }, 753 },
  754 + {
  755 + field: 'businessPerson',
  756 + component: 'Select',
  757 + labelWidth: 150,
  758 + label: '业务员',
  759 + rules: [{ required: true }],
  760 + },
673 ]; 761 ];
674 762
675 //项目完成报告信息 763 //项目完成报告信息
@@ -680,22 +768,44 @@ export const FIELDS_REPORT_INFO = [ @@ -680,22 +768,44 @@ export const FIELDS_REPORT_INFO = [
680 optionField: 'ideaSource', 768 optionField: 'ideaSource',
681 labelWidth: 150, 769 labelWidth: 150,
682 label: '想法来源', 770 label: '想法来源',
683 - // rules: [{ required: true }], 771 + rules: [{ required: true }],
  772 + },
  773 + {
  774 + field: 'ideaSourceRate',
  775 + component: 'InputNumber',
  776 + optionField: 'ideaSourceRate',
  777 + labelWidth: 150,
  778 + label: '想法来源占比',
  779 + rules: [{ required: true }],
684 }, 780 },
685 { 781 {
686 - field: 'manualPreform', 782 + field: 'manualPreform1',
687 component: 'Select', 783 component: 'Select',
688 - optionField: 'manualPreform', 784 + optionField: 'manualPreform1',
689 labelWidth: 150, 785 labelWidth: 150,
690 - label: '手工初型',  
691 - // rules: [{ required: true }], 786 + label: '手工初型1',
  787 + rules: [{ required: true }],
692 }, 788 },
693 { 789 {
694 - field: 'ideaManualRate',  
695 - component: 'Input', 790 + field: 'manualPreform1Rate',
  791 + component: 'InputNumber',
696 labelWidth: 150, 792 labelWidth: 150,
697 - label: '想法和手工比例分配',  
698 - // rules: [{ required: true }], 793 + label: '手工初型1占比',
  794 + rules: [{ required: true }],
  795 + },
  796 + {
  797 + field: 'manualPreform2',
  798 + component: 'Select',
  799 + labelWidth: 150,
  800 + label: '手工初型2',
  801 + rules: [{ required: true }],
  802 + },
  803 + {
  804 + field: 'manualPreform2Rate',
  805 + component: 'InputNumber',
  806 + labelWidth: 150,
  807 + label: '手工初型2占比',
  808 + rules: [{ required: true }],
699 }, 809 },
700 ]; 810 ];
701 811
@@ -836,7 +946,7 @@ export const FIELDS_PROFIT_INFO = [ @@ -836,7 +946,7 @@ export const FIELDS_PROFIT_INFO = [
836 field: 'customerPrice', 946 field: 'customerPrice',
837 component: 'InputNumber', 947 component: 'InputNumber',
838 label: '客户单价', 948 label: '客户单价',
839 - // rules: [{ required: true }], 949 + rules: [{ required: true }],
840 }, 950 },
841 // { 951 // {
842 // field: 'customerTotalPrice', 952 // field: 'customerTotalPrice',
@@ -848,7 +958,8 @@ export const FIELDS_PROFIT_INFO = [ @@ -848,7 +958,8 @@ export const FIELDS_PROFIT_INFO = [
848 field: 'customerCurrency', 958 field: 'customerCurrency',
849 component: 'Select', 959 component: 'Select',
850 label: '客户单价货币单位', 960 label: '客户单价货币单位',
851 - // rules: [{ required: true }], 961 + labelWidth: 400,
  962 + rules: [{ required: true }],
852 componentProps: { 963 componentProps: {
853 options: [ 964 options: [
854 { label: '$', value: '$' }, 965 { label: '$', value: '$' },
@@ -860,13 +971,13 @@ export const FIELDS_PROFIT_INFO = [ @@ -860,13 +971,13 @@ export const FIELDS_PROFIT_INFO = [
860 field: 'productionDepartmentPrice', 971 field: 'productionDepartmentPrice',
861 component: 'InputNumber', 972 component: 'InputNumber',
862 label: '生成科单价', 973 label: '生成科单价',
863 - // rules: [{ required: true }], 974 + rules: [{ required: true }],
864 }, 975 },
865 { 976 {
866 field: 'productionDepartmentCurrency', 977 field: 'productionDepartmentCurrency',
867 component: 'Select', 978 component: 'Select',
868 label: '生成科货币单位', 979 label: '生成科货币单位',
869 - // rules: [{ required: true }], 980 + rules: [{ required: true }],
870 componentProps: { 981 componentProps: {
871 options: [ 982 options: [
872 { label: '$', value: '$' }, 983 { label: '$', value: '$' },
@@ -884,6 +995,14 @@ export const FIELDS_PROFIT_INFO = [ @@ -884,6 +995,14 @@ export const FIELDS_PROFIT_INFO = [
884 label: '包装费用', 995 label: '包装费用',
885 component: 'InputNumber', 996 component: 'InputNumber',
886 field: 'packetPrice', 997 field: 'packetPrice',
  998 + fieldComponent: { disabled: true },
  999 + // rules: [{ required: true }],
  1000 + },
  1001 + {
  1002 + label: '汇率',
  1003 + component: 'InputNumber',
  1004 + field: 'exchangeRate',
  1005 + fieldComponent: { disabled: true },
887 // rules: [{ required: true }], 1006 // rules: [{ required: true }],
888 }, 1007 },
889 // { 1008 // {
@@ -892,30 +1011,39 @@ export const FIELDS_PROFIT_INFO = [ @@ -892,30 +1011,39 @@ export const FIELDS_PROFIT_INFO = [
892 // field: 'packetTotalPrice', 1011 // field: 'packetTotalPrice',
893 // rules: [{ required: true }], 1012 // rules: [{ required: true }],
894 // }, 1013 // },
  1014 + // {
  1015 + // label: '包装费用货币单位',
  1016 + // component: 'Input',
  1017 + // field: 'packetCurrency',
  1018 + // value: '$',
  1019 + // // rules: [{ required: true }],
  1020 + // componentProps: {
  1021 + // disblaed: true,
  1022 + // // options: [
  1023 + // // { label: '$', value: '$' },
  1024 + // // { label: '¥', value: '¥' },
  1025 + // // ],
  1026 + // },
  1027 + // },
  1028 + // {
  1029 + // label: '汇率',
  1030 + // component: 'Select',
  1031 + // field: 'exchangeRate',
  1032 + // // rules: [{ required: true }],
  1033 + // },
895 { 1034 {
896 - label: '包装费用货币单位', 1035 + label: '计算利润方式',
897 component: 'Select', 1036 component: 'Select',
898 - field: 'packetCurrency',  
899 - // rules: [{ required: true }], 1037 + field: 'profitType',
900 componentProps: { 1038 componentProps: {
  1039 + defaultValue: '0',
901 options: [ 1040 options: [
902 - { label: '$', value: '$' },  
903 - { label: '¥', value: '¥' }, 1041 + { label: '方式一: 1 -(LOCAL单价 / 汇率 + 包装费用)/ 客户单价', value: '0' },
  1042 + { label: '方式二: 1 -(LOCAL单价/汇率 / (客户单价-包装费用)', value: '1' },
904 ], 1043 ],
905 }, 1044 },
906 - },  
907 - {  
908 - label: '汇率',  
909 - component: 'InputNumber',  
910 - field: 'exchangeRate',  
911 // rules: [{ required: true }], 1045 // rules: [{ required: true }],
912 }, 1046 },
913 - // {  
914 - // label: '利润率',  
915 - // component: 'Input',  
916 - // field: 'profitRate',  
917 - // rules: [{ required: true }],  
918 - // },  
919 ]; 1047 ];
920 1048
921 //质量检测信息 1049 //质量检测信息
@@ -1196,14 +1324,25 @@ export function getFormConfig(): Partial&lt;FormProps&gt; { @@ -1196,14 +1324,25 @@ export function getFormConfig(): Partial&lt;FormProps&gt; {
1196 }, 1324 },
1197 }, 1325 },
1198 { 1326 {
1199 - field: `manualPreform`,  
1200 - label: `手工初型`, 1327 + field: `manualPreform1`,
  1328 + label: `手工初型1`,
  1329 + component: 'Select',
  1330 + colProps: {
  1331 + span: 6,
  1332 + },
  1333 + labelWidth: 150,
  1334 + componentProps: {
  1335 + options: manualPreform,
  1336 + },
  1337 + },
  1338 + {
  1339 + field: `manualPreform2`,
  1340 + label: `手工初型2`,
1201 component: 'Select', 1341 component: 'Select',
1202 colProps: { 1342 colProps: {
1203 span: 6, 1343 span: 6,
1204 }, 1344 },
1205 labelWidth: 150, 1345 labelWidth: 150,
1206 -  
1207 componentProps: { 1346 componentProps: {
1208 options: manualPreform, 1347 options: manualPreform,
1209 }, 1348 },
src/views/project/order/type.d.ts
1 export enum ROLE { 1 export enum ROLE {
2 ADMIN = 'admin', // 超管 2 ADMIN = 'admin', // 超管
  3 + CUSTOM_ADMIN = 'custom_admin', // 客户管理员
  4 + DATA_REPORT_USER = 'data_report_user', //数据分析员
3 BUSINESS = 'business_user', // 业务员 5 BUSINESS = 'business_user', // 业务员
4 TRACKER = 'tracker_user', // 跟单员 6 TRACKER = 'tracker_user', // 跟单员
5 INSPECT = 'inspect_user', // 质检员 7 INSPECT = 'inspect_user', // 质检员
src/views/sys/login/ForgetPasswordForm.vue
@@ -2,21 +2,49 @@ @@ -2,21 +2,49 @@
2 <template v-if="getShow"> 2 <template v-if="getShow">
3 <LoginFormTitle class="enter-x" /> 3 <LoginFormTitle class="enter-x" />
4 <Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef"> 4 <Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef">
5 - <FormItem name="account" class="enter-x"> 5 + <!-- <FormItem name="account" class="enter-x">
6 <Input 6 <Input
7 size="large" 7 size="large"
8 v-model:value="formData.account" 8 v-model:value="formData.account"
9 :placeholder="t('sys.login.userName')" 9 :placeholder="t('sys.login.userName')"
10 /> 10 />
  11 + </FormItem> -->
  12 + <FormItem name="phone" class="enter-x">
  13 + <Input size="large" v-model:value="formData.phone" :placeholder="t('sys.login.mobile')" />
  14 + </FormItem>
  15 + <FormItem name="password" class="enter-x">
  16 + <Input
  17 + size="large"
  18 + visibilityToggle
  19 + v-model:value="formData.password"
  20 + placeholder="请输入密码"
  21 + />
  22 + </FormItem>
  23 + <FormItem name="confirmPassword" class="enter-x">
  24 + <Input
  25 + size="large"
  26 + visibilityToggle
  27 + v-model:value="formData.confirmPassword"
  28 + placeholder="请输入确认密码"
  29 + />
11 </FormItem> 30 </FormItem>
12 31
13 - <FormItem name="mobile" class="enter-x">  
14 - <Input size="large" v-model:value="formData.mobile" :placeholder="t('sys.login.mobile')" /> 32 + <FormItem name="imgCaptchaCode" class="enter-x">
  33 + <div className="flex">
  34 + <img :src="imgCaptcha" class="cursor-pointer" @click="getImgCaptcha" />
  35 + <Input
  36 + size="large"
  37 + visibilityToggle
  38 + v-model:value="imgCaptchaCode"
  39 + placeholder="请输入图片验证码"
  40 + />
  41 + </div>
15 </FormItem> 42 </FormItem>
16 - <FormItem name="sms" class="enter-x"> 43 + <FormItem name="smsCaptchaCode" class="enter-x">
17 <CountdownInput 44 <CountdownInput
18 size="large" 45 size="large"
19 - v-model:value="formData.sms" 46 + v-model:value="formData.smsCaptchaCode"
  47 + :sendCodeApi="handleSendMsg"
20 :placeholder="t('sys.login.smsCode')" 48 :placeholder="t('sys.login.smsCode')"
21 /> 49 />
22 </FormItem> 50 </FormItem>
@@ -33,12 +61,14 @@ @@ -33,12 +61,14 @@
33 </template> 61 </template>
34 </template> 62 </template>
35 <script lang="ts" setup> 63 <script lang="ts" setup>
36 - import { reactive, ref, computed, unref } from 'vue'; 64 + import { reactive, ref, computed, unref, onMounted } from 'vue';
37 import LoginFormTitle from './LoginFormTitle.vue'; 65 import LoginFormTitle from './LoginFormTitle.vue';
38 - import { Form, Input, Button } from 'ant-design-vue'; 66 + import { Form, Input, Button, message } from 'ant-design-vue';
39 import { CountdownInput } from '/@/components/CountDown'; 67 import { CountdownInput } from '/@/components/CountDown';
40 import { useI18n } from '/@/hooks/web/useI18n'; 68 import { useI18n } from '/@/hooks/web/useI18n';
41 import { useLoginState, useFormRules, LoginStateEnum } from './useLogin'; 69 import { useLoginState, useFormRules, LoginStateEnum } from './useLogin';
  70 + import { forgetPassword, getSms } from '/@/api/sys/user';
  71 + import { useUserStore } from '/@/store/modules/user';
42 72
43 const FormItem = Form.Item; 73 const FormItem = Form.Item;
44 const { t } = useI18n(); 74 const { t } = useI18n();
@@ -49,16 +79,56 @@ @@ -49,16 +79,56 @@
49 const loading = ref(false); 79 const loading = ref(false);
50 80
51 const formData = reactive({ 81 const formData = reactive({
52 - account: '',  
53 - mobile: '',  
54 - sms: '', 82 + phone: '',
  83 + smsCaptchaCode: '',
  84 + password: '',
  85 + confirmPassword: '',
  86 + });
  87 +
  88 + const imgCaptchaCode = ref('');
  89 + const imgCaptcha = ref('');
  90 + const imgCaptchaUuid = ref('');
  91 + const userStore = useUserStore();
  92 +
  93 + onMounted(async () => {
  94 + getImgCaptcha();
55 }); 95 });
56 96
  97 + const getImgCaptcha = async () => {
  98 + const data = await userStore.getImageCaptcha();
  99 + imgCaptcha.value = data?.img;
  100 + imgCaptchaUuid.value = data?.uuid;
  101 + };
  102 +
  103 + const handleSendMsg = async () => {
  104 + if (!formData.phone) {
  105 + message.error('请输入手机号');
  106 + return false;
  107 + }
  108 + if (!imgCaptchaCode.value) {
  109 + message.error('请输入验证码');
  110 + return false;
  111 + }
  112 + if (formData.password !== formData.confirmPassword) {
  113 + message.error('密码和确认密码不一样');
  114 + return false;
  115 + }
  116 + return await getSms({
  117 + phone: formData.phone,
  118 + imgCaptchaCode: imgCaptchaCode.value,
  119 + imgCaptchaUuid: imgCaptchaUuid.value,
  120 + });
  121 + };
  122 +
57 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD); 123 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD);
58 124
59 async function handleReset() { 125 async function handleReset() {
60 - const form = unref(formRef);  
61 - if (!form) return;  
62 - await form.resetFields(); 126 + try {
  127 + await formRef.value.validate();
  128 + const form = unref(formRef);
  129 + if (!form) return;
  130 + await forgetPassword({ ...formData });
  131 + handleBackLogin();
  132 + } catch (error) {}
63 } 133 }
64 </script> 134 </script>
src/views/sys/login/LoginForm.vue
@@ -34,13 +34,15 @@ @@ -34,13 +34,15 @@
34 /> 34 />
35 </FormItem> 35 </FormItem>
36 <FormItem name="imgCaptchaCode" class="enter-x" label="验证码"> 36 <FormItem name="imgCaptchaCode" class="enter-x" label="验证码">
37 - <img :src="imgCaptcha" class="cursor-pointer" @click="getImgCaptcha" /> 37 + <img :src="imgCaptcha" class="cursor-pointer mr-40" @click="getImgCaptcha" />
  38 + <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
  39 + {{ t('sys.login.forgetPassword') }}
  40 + </Button>
38 </FormItem> 41 </FormItem>
39 42
40 - <ARow class="enter-x"> 43 + <!-- <ARow class="enter-x">
41 <ACol :span="12"> 44 <ACol :span="12">
42 <FormItem> 45 <FormItem>
43 - <!-- No logic, you need to deal with it yourself -->  
44 <Checkbox v-model:checked="rememberMe" size="small"> 46 <Checkbox v-model:checked="rememberMe" size="small">
45 {{ t('sys.login.rememberMe') }} 47 {{ t('sys.login.rememberMe') }}
46 </Checkbox> 48 </Checkbox>
@@ -48,13 +50,12 @@ @@ -48,13 +50,12 @@
48 </ACol> 50 </ACol>
49 <ACol :span="12"> 51 <ACol :span="12">
50 <FormItem :style="{ 'text-align': 'right' }"> 52 <FormItem :style="{ 'text-align': 'right' }">
51 - <!-- No logic, you need to deal with it yourself -->  
52 <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)"> 53 <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
53 {{ t('sys.login.forgetPassword') }} 54 {{ t('sys.login.forgetPassword') }}
54 </Button> 55 </Button>
55 </FormItem> 56 </FormItem>
56 </ACol> 57 </ACol>
57 - </ARow> 58 + </ARow> -->
58 59
59 <FormItem class="enter-x"> 60 <FormItem class="enter-x">
60 <Button type="primary" size="large" block @click="handleLogin" :loading="loading"> 61 <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
@@ -64,23 +65,23 @@ @@ -64,23 +65,23 @@
64 {{ t('sys.login.registerButton') }} 65 {{ t('sys.login.registerButton') }}
65 </Button> --> 66 </Button> -->
66 </FormItem> 67 </FormItem>
67 - <ARow class="enter-x">  
68 - <!-- <ACol :md="8" :xs="24"> 68 + <!-- <ARow class="enter-x"> -->
  69 + <!-- <ACol :md="8" :xs="24">
69 <Button block @click="setLoginState(LoginStateEnum.MOBILE)"> 70 <Button block @click="setLoginState(LoginStateEnum.MOBILE)">
70 {{ t('sys.login.mobileSignInFormTitle') }} 71 {{ t('sys.login.mobileSignInFormTitle') }}
71 </Button> 72 </Button>
72 </ACol> --> 73 </ACol> -->
73 - <!-- <ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2"> 74 + <!-- <ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2">
74 <Button block @click="setLoginState(LoginStateEnum.QR_CODE)"> 75 <Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
75 {{ t('sys.login.qrSignInFormTitle') }} 76 {{ t('sys.login.qrSignInFormTitle') }}
76 </Button> 77 </Button>
77 </ACol> --> 78 </ACol> -->
78 - <!-- <ACol :md="6" :xs="24"> 79 + <!-- <ACol :md="6" :xs="24">
79 <Button block @click="setLoginState(LoginStateEnum.REGISTER)"> 80 <Button block @click="setLoginState(LoginStateEnum.REGISTER)">
80 {{ t('sys.login.registerButton') }} 81 {{ t('sys.login.registerButton') }}
81 </Button> 82 </Button>
82 </ACol> --> 83 </ACol> -->
83 - </ARow> 84 + <!-- </ARow> -->
84 <!-- 85 <!--
85 <Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider> 86 <Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
86 87
@@ -133,8 +134,8 @@ @@ -133,8 +134,8 @@
133 const imgCaptchaUuid = ref(''); 134 const imgCaptchaUuid = ref('');
134 135
135 const formData = reactive({ 136 const formData = reactive({
136 - userName: 'admin',  
137 - password: '123456', 137 + userName: '',
  138 + password: '',
138 imgCaptchaCode: '', 139 imgCaptchaCode: '',
139 imgCaptchaUuid: '', 140 imgCaptchaUuid: '',
140 }); 141 });
src/views/sys/login/useLogin.ts
@@ -53,6 +53,7 @@ export function useFormRules(formData?: Recordable) { @@ -53,6 +53,7 @@ export function useFormRules(formData?: Recordable) {
53 const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); 53 const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder')));
54 const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); 54 const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder')));
55 const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder'))); 55 const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder')));
  56 + const getConfirmPasswordFormRule = computed(() => createRule(t('请输入确认密码')));
56 57
57 const validatePolicy = async (_: RuleObject, value: boolean) => { 58 const validatePolicy = async (_: RuleObject, value: boolean) => {
58 return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); 59 return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve();
@@ -75,10 +76,11 @@ export function useFormRules(formData?: Recordable) { @@ -75,10 +76,11 @@ export function useFormRules(formData?: Recordable) {
75 const passwordFormRule = unref(getPasswordFormRule); 76 const passwordFormRule = unref(getPasswordFormRule);
76 const smsFormRule = unref(getSmsFormRule); 77 const smsFormRule = unref(getSmsFormRule);
77 const mobileFormRule = unref(getMobileFormRule); 78 const mobileFormRule = unref(getMobileFormRule);
  79 + const confirmPasswordFormRule = unref(getConfirmPasswordFormRule);
78 80
79 const mobileRule = { 81 const mobileRule = {
80 sms: smsFormRule, 82 sms: smsFormRule,
81 - mobile: mobileFormRule, 83 + phone: mobileFormRule,
82 }; 84 };
83 switch (unref(currentState)) { 85 switch (unref(currentState)) {
84 // register form rules 86 // register form rules
@@ -97,6 +99,8 @@ export function useFormRules(formData?: Recordable) { @@ -97,6 +99,8 @@ export function useFormRules(formData?: Recordable) {
97 case LoginStateEnum.RESET_PASSWORD: 99 case LoginStateEnum.RESET_PASSWORD:
98 return { 100 return {
99 userName: accountFormRule, 101 userName: accountFormRule,
  102 + password: passwordFormRule,
  103 + confirmPassword: confirmPasswordFormRule,
100 ...mobileRule, 104 ...mobileRule,
101 }; 105 };
102 106
vite.config.ts
@@ -20,15 +20,15 @@ export default defineApplicationConfig({ @@ -20,15 +20,15 @@ export default defineApplicationConfig({
20 server: { 20 server: {
21 proxy: { 21 proxy: {
22 '/basic-api/order': { 22 '/basic-api/order': {
23 - target: 'http://39.108.227.113:8010', 23 + target: 'http://39.108.227.113:8000',
24 // target: 'http://39.108.227.113:3000/mock/35', 24 // target: 'http://39.108.227.113:3000/mock/35',
25 - // http://39.108.227.113:8010/order/erp/captcha/get_img_captcha_code 25 + // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code
26 changeOrigin: true, 26 changeOrigin: true,
27 ws: true, 27 ws: true,
28 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), 28 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''),
29 }, 29 },
30 '/api/localStorage/upload': { 30 '/api/localStorage/upload': {
31 - target: 'http://39.108.227.113:8010', 31 + target: 'http://39.108.227.113:8000',
32 changeOrigin: true, 32 changeOrigin: true,
33 ws: true, 33 ws: true,
34 // rewrite: (path) => { 34 // rewrite: (path) => {