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 1 import { defHttp } from '/@/utils/http/axios';
2 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 4 enum Api {
7 5 DEMO_LIST = '/table/getDemoList',
... ... @@ -39,8 +37,8 @@ export const demoApproveListApi = async (params: DemoParams) => {
39 37 item.fields = [];
40 38 Object.entries(item.fieldInfos.baseFields).map(([key, value]) => {
41 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 44 item.fields = item.fields.join(',');
... ...
src/api/project/order.ts
... ... @@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
3 3 import { useUserStoreWithOut } from '/@/store/modules/user';
4 4 import { useOrderStoreWithOut } from '/@/store/modules/order';
5 5 import { formatToDate } from '/@/utils/dateUtil';
  6 +import message from '/@/views/form-design/utils/message';
6 7  
7 8 enum Api {
8 9 ORDER_CREATE = '/order/erp/order/add',
... ... @@ -19,11 +20,37 @@ enum Api {
19 20 DICT_LIST = '/order/erp/dictionary/list_by_page',
20 21  
21 22 ANALYSIS = '/order/erp/profit/analysis',
  23 + GRAVITY = '/order/erp/report/analysis',
22 24  
23 25 OPT_LOG = '/order/erp/opt/log/list_by_page', // 操作日志
24 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 54 export const orderCreate = async (data: any) => {
28 55 const res = await defHttp.post<any>({ url: Api.ORDER_CREATE, data }, { message: '保存成功' });
29 56 return res;
... ... @@ -50,6 +77,13 @@ export const orderAnalysis = async (data: any) =&gt; {
50 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 87 export const orderExport = async (data: any = {}) => {
54 88 // const res = await defHttp.post<any>({ url: Api.EXPORT, data });
55 89 const userStore = useUserStoreWithOut();
... ... @@ -60,7 +94,7 @@ export const orderExport = async (data: any = {}) =&gt; {
60 94 url: '/basic-api' + Api.EXPORT,
61 95 method: 'post',
62 96 responseType: 'blob',
63   - headers: { Authorization: `Bearer ${token}` },
  97 + headers: { Authorization: `${token}` },
64 98 data,
65 99 })
66 100 .then((response) => {
... ... @@ -74,6 +108,8 @@ export const orderExport = async (data: any = {}) =&gt; {
74 108 a.click(); // 模拟点击操作来下载文件
75 109 URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存
76 110 document.body.removeChild(a);
  111 +
  112 + message.success('导出成功');
77 113 })
78 114 .catch((error) => {
79 115 // 处理错误
... ... @@ -104,28 +140,7 @@ export async function uploadImg(params, onUploadProgress: (progressEvent: Progre
104 140 }
105 141  
106 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 144 const res = await defHttp.post<DemoListGetResultModel>({
130 145 url: Api.ORDER,
131 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 10 GetUserInfo = '/getUserInfo',
11 11 GetPermCode = '/getPermCode',
12 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 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 49 * @description: getUserInfo
32 50 */
... ... @@ -56,5 +74,18 @@ export function testRetry() {
56 74 }
57 75  
58 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 2 // basic login path
3 3 BASE_LOGIN = '/login',
4 4 // basic home path
5   - BASE_HOME = '/',
  5 + BASE_HOME = '/home',
6 6 // error page path
7 7 ERROR_PAGE = '/exception',
8 8 // error log page path
... ...
src/enums/roleEnum.ts
1 1 export enum RoleEnum {
2 2 // super admin
3 3 SUPER = 'super',
4   -
  4 + ADMIN = 'admin',
5 5 // tester
6 6 TEST = 'test',
7 7 }
... ...
src/hooks/component/order.ts
... ... @@ -9,6 +9,11 @@ export function useOrderInfo(orderStore) {
9 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 17 const customerCode = computed(() => {
13 18 const dictInfo = orderStore.getDictInfo;
14 19  
... ... @@ -75,7 +80,11 @@ export function useOrderInfo(orderStore) {
75 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 88 return {
80 89 customerCode,
81 90 projectNo,
... ... @@ -90,5 +99,7 @@ export function useOrderInfo(orderStore) {
90 99 manualPreform,
91 100 midCheckResult,
92 101 endCheckResult,
  102 + exchangeRate,
  103 + businessPerson,
93 104 };
94 105 }
... ...
src/layouts/default/header/components/user-dropdown/index.vue
1 1 <template>
2 2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`">
3 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 5 <span :class="`${prefixCls}__info hidden md:block`">
6 6 <span :class="`${prefixCls}__name `" class="truncate">
7   - {{ getUserInfo.realName }}
  7 + {{ getUserInfo.nickName }}
8 8 </span>
9 9 </span>
10 10 </span>
... ... @@ -76,8 +76,13 @@
76 76 const userStore = useUserStore();
77 77  
78 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 88 const [register, { openModal }] = useModal();
... ...
src/layouts/default/header/index.less
... ... @@ -104,7 +104,7 @@
104 104 display: flex;
105 105 // padding-right: 12px;
106 106 align-items: center;
107   - min-width: 180px;
  107 + min-width: 120px;
108 108  
109 109 &__item {
110 110 display: flex !important;
... ...
src/layouts/default/header/index.vue
... ... @@ -49,7 +49,6 @@
49 49 /> -->
50 50  
51 51 <UserDropDown :theme="getHeaderTheme" />
52   - <span className="text-gray-900">{{ nickName }}</span>
53 52 <!-- <SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" /> -->
54 53 </div>
55 54 </Header>
... ...
src/router/routes/modules/project/system.ts
... ... @@ -2,6 +2,7 @@ import type { AppRouteModule } from &#39;/@/router/types&#39;;
2 2  
3 3 import { LAYOUT } from '/@/router/constant';
4 4 import { t } from '/@/hooks/web/useI18n';
  5 +import { RoleEnum } from '/@/enums/roleEnum';
5 6  
6 7 const system: AppRouteModule = {
7 8 path: '/system',
... ... @@ -19,21 +20,41 @@ const system: AppRouteModule = {
19 20 name: 'AccountManagement',
20 21 meta: {
21 22 title: t('routes.demo.system.account'),
  23 + roles: [RoleEnum.ADMIN],
22 24 ignoreKeepAlive: false,
23 25 },
24 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 52 meta: {
30   - hideMenu: true,
31   - title: t('routes.demo.system.account_detail'),
  53 + title: '系统配置',
32 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 60 // path: 'role',
... ...
src/store/modules/order.ts
... ... @@ -92,7 +92,7 @@ export const useOrderStore = defineStore({
92 92 async getDict(): Promise<GetUserInfoModel | null> {
93 93 try {
94 94 const data = await getInitDictData();
95   - console.log('%c [ data ]-95', 'font-size:13px; background:pink; color:#bf2c9f;', data);
  95 +
96 96 this.dicts = groupBy(data, 'dictCode');
97 97 } catch (error) {
98 98 return Promise.reject(error);
... ...
src/store/modules/permission.ts
... ... @@ -112,6 +112,11 @@ export const usePermissionStore = defineStore({
112 112 async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
113 113 const { t } = useI18n();
114 114 const userStore = useUserStore();
  115 + console.log(
  116 + '%c [ userStore ]-115',
  117 + 'font-size:13px; background:pink; color:#bf2c9f;',
  118 + userStore,
  119 + );
115 120 const appStore = useAppStoreWithOut();
116 121  
117 122 let routes: AppRouteRecordRaw[] = [];
... ... @@ -127,7 +132,9 @@ export const usePermissionStore = defineStore({
127 132 const { roles } = meta || {};
128 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 140 const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => {
... ... @@ -195,6 +202,7 @@ export const usePermissionStore = defineStore({
195 202 routes = filter(routes, routeRemoveIgnoreFilter);
196 203 // 移除掉 ignoreRoute: true 的路由 一级路由;
197 204 routes = routes.filter(routeRemoveIgnoreFilter);
  205 +
198 206 // 对菜单进行排序
199 207 menuList.sort((a, b) => {
200 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 11 }
12 12  
13 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 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 import { defineComponent } from 'vue';
14 14 import { PageWrapper } from '/@/components/Page';
15 15 import { BasicForm, useForm } from '/@/components/Form';
  16 + import { useUserStoreWithOut } from '/@/store/modules/user';
16 17  
17 18 import { formSchema } from './pwd.data';
  19 + import { forgetPassword } from '/@/api/sys/user';
18 20  
19 21 export default defineComponent({
20 22 name: 'ChangePassword',
21 23 components: { BasicForm, PageWrapper },
22 24 setup() {
  25 + const userStore = useUserStoreWithOut();
  26 +
23 27 const [register, { validate, resetFields }] = useForm({
24 28 size: 'large',
25 29 baseColProps: { span: 24 },
... ... @@ -31,12 +35,10 @@
31 35 async function handleSubmit() {
32 36 try {
33 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 42 } catch (error) {}
41 43 }
42 44  
... ...
src/views/demo/system/password/pwd.data.ts
1 1 import { FormSchema } from '/@/components/Form';
2 2  
3 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 12 label: '新密码',
13 13 component: 'StrengthMeter',
14 14 componentProps: {
... ... @@ -34,7 +34,7 @@ export const formSchema: FormSchema[] = [
34 34 if (!value) {
35 35 return Promise.reject('密码不能为空');
36 36 }
37   - if (value !== values.passwordNew) {
  37 + if (value !== values.password) {
38 38 return Promise.reject('两次输入的密码不一致!');
39 39 }
40 40 return Promise.resolve();
... ...
src/views/project/account/index.vue
... ... @@ -70,6 +70,9 @@
70 70 },
71 71 useSearchForm: true,
72 72 showTableSetting: true,
  73 + tableSetting: {
  74 + setting: false,
  75 + },
73 76 bordered: true,
74 77 handleSearchInfoFn(info) {
75 78 console.log('handleSearchInfoFn', info);
... ...
src/views/project/approve/FieldPanel.vue
... ... @@ -51,14 +51,15 @@
51 51 <a-button @click="handleFalse"> 不通过</a-button>
52 52 </template>
53 53 </BasicDrawer>
  54 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
54 55 </PageWrapper>
55 56 </template>
56 57 <script lang="ts">
  58 + import MsgModal from './MsgModal.vue';
57 59 import { computed, defineComponent, ref } from 'vue';
58 60 import { BasicTable, useTable, TableAction } from '/@/components/Table';
59 61 import { PageWrapper } from '/@/components/Page';
60 62 import { BasicDrawer, useDrawer } from '/@/components/Drawer';
61   -
62 63 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve';
63 64 import {
64 65 FIELDS_BASE_INFO,
... ... @@ -81,11 +82,15 @@
81 82 BasicDrawer,
82 83 TableAction,
83 84 BaseInfo,
  85 + MsgModal,
84 86 },
85 87 props: {
86 88 isApproved: { type: Boolean },
87 89 },
88 90 setup(props) {
  91 + // visible 用于msgModal显示隐藏
  92 + const msgVisible = ref(false);
  93 +
89 94 const checkedKeys = ref<Array<string | number>>([]);
90 95 const currentKey = ref('1');
91 96 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
... ... @@ -99,17 +104,35 @@
99 104 const baseInfos = ref({});
100 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 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 136 // useSearchForm: true,
114 137 // formConfig: getFormConfig(),
115 138 rowKey: 'id',
... ... @@ -209,14 +232,23 @@
209 232 }
210 233  
211 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 238 const role = computed(() => {
218 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 252 return {
221 253 handleProfitModal,
222 254 registerTable,
... ... @@ -233,8 +265,9 @@
233 265 handleFalse,
234 266 ROLE,
235 267 role,
  268 + msgVisible,
  269 + handleMsgModalClose,
236 270 };
237 271 },
238 272 });
239 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 33 <a-button @click="handleFalse"> 不通过</a-button>
34 34 </template>
35 35 </BasicDrawer>
  36 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
36 37 </PageWrapper>
37 38 </template>
38 39 <script lang="ts">
  40 + import MsgModal from './MsgModal.vue';
39 41 import { computed, defineComponent, ref } from 'vue';
40 42 import { BasicTable, useTable, TableAction } from '/@/components/Table';
41 43 import { PageWrapper } from '/@/components/Page';
... ... @@ -56,11 +58,14 @@
56 58 BasicDrawer,
57 59 TableAction,
58 60 BaseInfo,
  61 + MsgModal,
59 62 },
60 63 props: {
61 64 isApproved: { type: Boolean },
62 65 },
63 66 setup(props) {
  67 + // visible 用于msgModal显示隐藏
  68 + const msgVisible = ref(false);
64 69 const checkedKeys = ref<Array<string | number>>([]);
65 70 const currentKey = ref('1');
66 71 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
... ... @@ -68,17 +73,35 @@
68 73 const baseInfos = ref({});
69 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 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 105 // useSearchForm: true,
83 106 // formConfig: getFormConfig(),
84 107 rowKey: 'id',
... ... @@ -118,6 +141,12 @@
118 141 openDrawer(true, { data });
119 142 id.value = data.id;
120 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 150 return {
122 151 label: field.label,
123 152 value: data.fieldInfos.profitAnalysisFields[field.field],
... ... @@ -138,14 +167,25 @@
138 167 }
139 168  
140 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 176 const role = computed(() => {
147 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 189 return {
150 190 handleProfitModal,
151 191 registerTable,
... ... @@ -162,8 +202,9 @@
162 202 handleFalse,
163 203 role,
164 204 ROLE,
  205 + msgVisible,
  206 + handleMsgModalClose,
165 207 };
166 208 },
167 209 });
168 210 </script>
169   -../order/constant
... ...
src/views/project/approve/ReportPanel.vue
... ... @@ -33,9 +33,11 @@
33 33 <a-button @click="handleFalse"> 不通过</a-button>
34 34 </template>
35 35 </BasicDrawer>
  36 + <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
36 37 </PageWrapper>
37 38 </template>
38 39 <script lang="ts">
  40 + import MsgModal from './MsgModal.vue';
39 41 import { computed, defineComponent, ref } from 'vue';
40 42 import { BasicTable, useTable, TableAction } from '/@/components/Table';
41 43 import { PageWrapper } from '/@/components/Page';
... ... @@ -56,29 +58,49 @@
56 58 BasicDrawer,
57 59 BaseInfo,
58 60 TableAction,
  61 + MsgModal,
59 62 },
60 63 props: {
61 64 isApproved: { type: Boolean },
62 65 },
63 66 setup(props) {
  67 + // visible 用于msgModal显示隐藏
  68 + const msgVisible = ref(false);
64 69 const checkedKeys = ref<Array<string | number>>([]);
65 70 const currentKey = ref('1');
66 71 const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
67 72 const fieldInfos = ref({});
68 73 const baseInfos = ref({});
69 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 99 const [registerTable, { reload }] = useTable({
72 100 api: props.isApproved ? getApprovedListApi : getWaitListApi,
73 101 searchInfo: { type: 20 },
74 102  
75   - columns: [
76   - {
77   - title: '申请人',
78   - dataIndex: 'createBy',
79   - width: 150,
80   - },
81   - ],
  103 + columns,
82 104 // useSearchForm: true,
83 105 // formConfig: getFormConfig(),
84 106 rowKey: 'id',
... ... @@ -138,11 +160,19 @@
138 160 }
139 161  
140 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 176 const role = computed(() => {
147 177 return userStore.getUserInfo?.roleSmallVO?.code;
148 178 });
... ... @@ -162,8 +192,9 @@
162 192 handleFalse,
163 193 role,
164 194 ROLE,
  195 + msgVisible,
  196 + handleMsgModalClose,
165 197 };
166 198 },
167 199 });
168 200 </script>
169   -../order/constant
... ...
src/views/project/approve/index.vue
... ... @@ -136,8 +136,6 @@
136 136 return false;
137 137 }
138 138  
139   - function handleProfitModal() {}
140   -
141 139 async function handleTrue(record) {
142 140 await approveAuditApi({ status: 10, id: record.id });
143 141 reload();
... ... @@ -149,7 +147,6 @@
149 147 }
150 148  
151 149 return {
152   - handleProfitModal,
153 150 registerTable1,
154 151 registerTable2,
155 152 checkedKeys,
... ... @@ -163,3 +160,9 @@
163 160 },
164 161 });
165 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 12 okText="申请"
13 13 ><input />
14 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 19 <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">
18 20 <h3>利润分析</h3>
19 21 <BasicForm @register="registerProfitForm" />
... ... @@ -56,19 +58,21 @@
56 58  
57 59 const userStore = useUserStoreWithOut();
58 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 77 export default defineComponent({
74 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 2 <BasicDrawer
3 3 @register="register"
4 4 v-bind="$attrs"
5   - title="title"
  5 + title="字段自定义"
6 6 :destroyOnClose="true"
7 7 width="60%"
8 8 :isDetail="true"
... ... @@ -55,7 +55,7 @@
55 55 setup() {
56 56 const dataSource = ref([]);
57 57 const key = ref('');
58   - const title = ref('');
  58 + const title = ref('12');
59 59  
60 60 const [registerTable, { getDataSource, reload }] = useTable({
61 61 columns: columns,
... ... @@ -72,11 +72,18 @@
72 72 });
73 73  
74 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 81 const dicts = orderStore.getDictInfo;
77 82 const dict = dicts[dataIndex];
78 83 dataSource.value = dict;
  84 +
79 85 title.value = customTitle;
  86 +
80 87 key.value = dataIndex;
81 88 });
82 89  
... ... @@ -95,13 +102,13 @@
95 102  
96 103 async function handleSave(record: EditRecordRow) {
97 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 106 } else {
100 107 await dictCreate({
101 108 dictName: title.value,
102 109 dictCode: key.value,
103 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 5 import { computed, defineComponent, ref } from 'vue';
6 6 import { BasicForm, useForm } from '/@/components/Form/index';
7 7 import { FIELDS_BASE_INFO } from '../tableData';
8   - import { getDisable } from '/@/utils/project';
  8 + import { getBaseDisable } from '/@/utils/project';
9 9 import { useOrderStoreWithOut } from '/@/store/modules/order';
10 10  
11 11 import { useOrderInfo } from '/@/hooks/component/order';
... ... @@ -24,6 +24,9 @@
24 24 id: {
25 25 type: String,
26 26 },
  27 + businessUsers: {
  28 + type: Array,
  29 + },
27 30 },
28 31 emits: ['success'],
29 32 setup(props) {
... ... @@ -42,7 +45,14 @@
42 45 productStyle,
43 46 outboundType,
44 47 packetType,
  48 +
  49 + // businessPerson,
45 50 } = useOrderInfo(orderStore);
  51 + console.log(
  52 + '%c [ productionDepartment ]-57',
  53 + 'font-size:13px; background:pink; color:#bf2c9f;',
  54 + productionDepartment,
  55 + );
46 56  
47 57 var schemas = computed(() => {
48 58 const options = {
... ... @@ -55,14 +65,11 @@
55 65 productStyle,
56 66 outboundType,
57 67 packetType,
  68 +
  69 + businessPerson: props.businessUsers,
58 70 };
59 71  
60 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 73 if (item.field === 'picUrl') {
67 74 return {
68 75 field: 'picUrl',
... ... @@ -74,7 +81,7 @@
74 81 },
75 82 componentProps: {
76 83 imgUrl: picUrl.value,
77   - disabled: getDisable(get(fields.value, 'picUrl'), props.id),
  84 + // disabled: getDisable(get(fields.value, 'picUrl'), props.id),
78 85 onChange: (res) => {
79 86 if (res.file?.response?.data) {
80 87 picUrl.value = res.file?.response?.data?.picUrl;
... ... @@ -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 105 return {
91 106 ...item,
92 107 field: `${item.field}`,
93 108 componentProps: {
94 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 112 colProps: {
98 113 span: 24,
... ...
src/views/project/order/FormDetail/InspectionFormPanel.vue
... ... @@ -2,10 +2,8 @@
2 2 <BasicForm @register="registerForm" />
3 3 </template>
4 4 <script lang="ts">
5   - import { computed, defineComponent, ref, toRaw } from 'vue';
  5 + import { computed, defineComponent, ref } from 'vue';
6 6 import { BasicForm, useForm } from '/@/components/Form/index';
7   - import { useDrawerInner } from '/@/components/Drawer';
8   - import { dateUtil } from '/@/utils/dateUtil';
9 7 import { FIELDS_INSPECTION_INFO } from '../tableData';
10 8 import { getDisable } from '/@/utils/project';
11 9 import { useOrderStoreWithOut } from '/@/store/modules/order';
... ... @@ -19,6 +17,9 @@
19 17 id: {
20 18 type: String,
21 19 },
  20 + inspectFormData: {
  21 + type: Object,
  22 + },
22 23 },
23 24 emits: ['success'],
24 25 setup(props, { emit }) {
... ... @@ -37,7 +38,11 @@
37 38 ...item,
38 39 componentProps: {
39 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 47 colProps: {
43 48 span: 24,
... ...
src/views/project/order/FormDetail/ProfitFormPanel.vue
... ... @@ -4,37 +4,52 @@
4 4 <script lang="ts">
5 5 import { computed, defineComponent, reactive, ref, toRaw } from 'vue';
6 6 import { BasicForm, useForm } from '/@/components/Form/index';
7   - import { dateUtil } from '/@/utils/dateUtil';
8 7 import { FIELDS_PROFIT_INFO } from '../tableData';
9   - import { getDisable } from '/@/utils/project';
  8 + import { getProfitDisable } from '/@/utils/project';
10 9 import { get } from 'lodash-es';
  10 + import { useOrderInfo } from '/@/hooks/component/order';
  11 + import { useOrderStoreWithOut } from '/@/store/modules/order';
11 12  
12 13 export default defineComponent({
13 14 components: { BasicForm },
14 15  
15 16 props: {
16   - detailData: {
17   - type: Object,
18   - },
19 17 onGoCheckDetail: {
20 18 type: Function,
21 19 },
22 20 id: {
23 21 type: String,
24 22 },
  23 + profitFormData: {
  24 + type: Object,
  25 + },
25 26 },
26 27 emits: ['success'],
27 28 setup(props, { emit }) {
28 29 let fields = ref({});
  30 + const orderStore = useOrderStoreWithOut();
  31 +
  32 + const { exchangeRate } = useOrderInfo(orderStore);
29 33  
30 34 const schemas = computed(() => {
  35 + const options = {
  36 + exchangeRate,
  37 + };
  38 +
31 39 return FIELDS_PROFIT_INFO.map((item) => {
32 40 return {
33 41 ...item,
34 42 field: `${item.field}`,
35 43 componentProps: {
36 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 54 colProps: {
40 55 span: 24,
... ... @@ -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 62 labelWidth: 120,
48 63 schemas,
49 64 layout: 'vertical',
... ... @@ -52,7 +67,16 @@
52 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 82 </script>
... ...
src/views/project/order/FormDetail/ReportFormPanel.vue
... ... @@ -24,6 +24,9 @@
24 24 id: {
25 25 type: String,
26 26 },
  27 + reportFormData: {
  28 + type: Object,
  29 + },
27 30 },
28 31 emits: ['success'],
29 32 setup(props) {
... ... @@ -39,12 +42,20 @@
39 42 };
40 43  
41 44 const res = FIELDS_REPORT_INFO.map((item) => {
  45 + let optionsField = item.field;
  46 + if (optionsField === 'manualPreform1' || optionsField === 'manualPreform2') {
  47 + optionsField = 'manualPreform';
  48 + }
42 49 return {
43 50 ...item,
44 51 field: `${item.field}`,
45 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 60 colProps: {
50 61 span: 24,
... ... @@ -54,7 +65,7 @@
54 65 return res;
55 66 });
56 67  
57   - const [registerForm, { setFieldsValue, getFieldsValue }] = useForm({
  68 + const [registerForm, { setFieldsValue, getFieldsValue, resetFields, validate }] = useForm({
58 69 labelWidth: 120,
59 70 schemas,
60 71 layout: 'vertical',
... ... @@ -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 89 </script>
... ...
src/views/project/order/FormDetail/TrackFormPanel.vue
... ... @@ -17,6 +17,9 @@
17 17 id: {
18 18 type: String,
19 19 },
  20 + trackFormData: {
  21 + type: Object,
  22 + },
20 23 },
21 24 emits: ['success'],
22 25 setup(props, { emit }) {
... ... @@ -27,7 +30,11 @@
27 30 ...item,
28 31 componentProps: {
29 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 39 colProps: {
33 40 span: 24,
... ...
src/views/project/order/FormDetail/index.vue
... ... @@ -14,10 +14,15 @@
14 14 :mask="false"
15 15 class="z-20"
16 16 >
17   - <div className="mt-[-16px]">
  17 + <div className="mt-[-16px] order-drawer-panel">
18 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 26 </TabPanel>
22 27 <TabPanel
23 28 key="2"
... ... @@ -25,7 +30,7 @@
25 30 :forceRender="true"
26 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 34 </TabPanel>
30 35 <TabPanel
31 36 key="3"
... ... @@ -33,7 +38,7 @@
33 38 :forceRender="true"
34 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 42 </TabPanel>
38 43 <TabPanel
39 44 key="4"
... ... @@ -41,7 +46,7 @@
41 46 :forceRender="true"
42 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 50 </TabPanel>
46 51 <TabPanel
47 52 key="5"
... ... @@ -49,7 +54,11 @@
49 54 :forceRender="true"
50 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 62 </TabPanel>
54 63 </Tabs>
55 64 </div>
... ... @@ -61,7 +70,7 @@
61 70 </BasicDrawer>
62 71 </template>
63 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 74 import { FormActionType, FormSchema, useForm } from '/@/components/Form/index';
66 75 import { orderCreate, orderUpdate, uploadImg } from '/@/api/project/order';
67 76 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
... ... @@ -73,8 +82,12 @@
73 82 import BaseFormPanel from './BaseFormPanel.vue';
74 83 import { useUserStoreWithOut } from '/@/store/modules/user';
75 84 import { ROLE } from '../type.d';
  85 + import { getList as getConfigList } from '/@/api/sys/config';
76 86  
77 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 92 const userStore = useUserStoreWithOut();
80 93  
... ... @@ -109,8 +122,33 @@
109 122 const trackFormPanelRef = ref();
110 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 132 const formRef = ref<FormActionType | null>(null);
113 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 153 const role = computed(() => {
116 154 return userStore.getUserInfo?.roleSmallVO?.code;
... ... @@ -120,6 +158,8 @@
120 158 let fields = reactive({ baseFields: {} });
121 159  
122 160 const [register, { closeDrawer }] = useDrawerInner((data) => {
  161 + activeKey.value =
  162 + role.value === ROLE.INSPECT ? '5' : role.value === ROLE.BUSINESS ? '2' : '1';
123 163 if (!data.id) {
124 164 id.value = '';
125 165 picUrl.value = '';
... ... @@ -133,6 +173,10 @@
133 173 return;
134 174 }
135 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 181 // 方式1
138 182 picUrl.value = data.picUrl;
... ... @@ -159,10 +203,22 @@
159 203 }
160 204  
161 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 217 profitFormPanelRef.value.fields = { ...data.lockFields?.profitAnalysisFields } || {};
164 218 profitFormPanelRef?.value?.setFieldsValue({
165 219 ...toRaw(data.profitAnalysisInfo),
  220 + packetPrice: packetPrice?.relationValue || 0,
  221 + exchangeRate: exchangeRate?.settingValue,
166 222 });
167 223 }
168 224  
... ... @@ -186,7 +242,7 @@
186 242 inspectionFormPanelRef.value.fields =
187 243 { ...data.lockFields?.inspectionStageFields } || {};
188 244 inspectionFormPanelRef?.value?.setFieldsValue({
189   - ...toRaw(data.trackStageInfo),
  245 + ...toRaw(data.inspectionStageInfo),
190 246 });
191 247 }
192 248 }, 100);
... ... @@ -196,10 +252,10 @@
196 252 });
197 253  
198 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 259 await baseFormPanelRef?.value?.validate();
204 260  
205 261 forms.baseInfo = baseFormPanelRef?.value?.getFieldsValue() || {};
... ... @@ -211,25 +267,36 @@
211 267 await orderUpdate(forms);
212 268 closeDrawer();
213 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 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 300 await baseFormPanelRef?.value?.validate();
234 301  
235 302 // 新建只有基本信息
... ... @@ -245,9 +312,9 @@
245 312 await orderCreate(forms);
246 313 closeDrawer();
247 314 emit('success', {});
248   - } catch (error) {
249   - console.log(error);
250 315 }
  316 + } catch (error) {
  317 + console.log(error);
251 318 }
252 319 };
253 320 return {
... ... @@ -261,16 +328,25 @@
261 328 formRef,
262 329 ROLE,
263 330 role,
  331 + profitFormData,
  332 + inspectFormData,
  333 + reportFormData,
  334 + trackFormData,
264 335 register,
265 336 handleSubmit,
  337 + businessUsers,
266 338 };
267 339 },
268 340 });
269 341 </script>
270 342  
271   -<style scoped>
  343 +<style>
272 344 .ant-drawer {
273 345 position: fixed;
274 346 z-index: 9999;
275 347 }
  348 +
  349 + .order-drawer-panel .ant-picker {
  350 + width: 100% !important;
  351 + }
276 352 </style>
... ...
src/views/project/order/ProfitAnalysis.vue
... ... @@ -4,9 +4,31 @@
4 4 destroyOnClose
5 5 @register="register"
6 6 title="利润分析表"
  7 + width="600px"
7 8 @visible-change="handleShow"
8 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 32 <!-- :helpMessage="['提示1', '提示2']" -->
11 33 <!-- <template #insertFooter>
12 34 <a-button type="primary" danger @click="setLines" :disabled="loading">点我更新内容</a-button>
... ... @@ -25,24 +47,34 @@
25 47 </BasicModal>
26 48 </template>
27 49 <script lang="ts">
28   - import { defineComponent, ref, toRaw, watch } from 'vue';
  50 + import { computed, defineComponent, onMounted, ref, toRaw, watch } from 'vue';
29 51 import { BasicModal, useModalInner } from '/@/components/Modal';
30 52 import { Description, DescItem, useDescription } from '/@/components/Description/index';
31 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 59 export default defineComponent({
34   - components: { BasicModal, Description },
  60 + components: { BasicModal, Description, Select, Space },
35 61 setup() {
  62 + const orderStore = useOrderStoreWithOut();
  63 + const { exchangeRate } = useOrderInfo(orderStore);
  64 + const orderIds = ref([]);
36 65 const loading = ref(true);
37 66 const lines = ref(10);
  67 + const activeRate = ref();
  68 + const profitType = ref('1');
38 69 const info = ref({});
39 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 80 const schema: DescItem[] = [
... ... @@ -75,18 +107,37 @@
75 107 if (visible) {
76 108 loading.value = true;
77 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 114 function setLines() {
87 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 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 33 <TableAction
34 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 62 </template>
54 63 <template v-if="column.key === 'picUrl'">
55 64 <img
56 65 :width="100"
57 66 :height="100"
58   - :src="record.picUrl"
59   - :key="record.picUrl"
  67 + :src="record.smallPicUrl"
  68 + :key="record.smallPicUrl"
60 69 @click="handlePreview(record.picUrl)"
61 70 />
62 71 </template>
63 72 </template>
64 73  
65 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 77 <a-button type="primary" @click="handleProfitModal" :disabled="!checkedKeys.length"
68 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 86 </template>
72 87 </BasicTable>
73 88 <FormDetail
... ... @@ -76,13 +91,15 @@
76 91 @success="handleFormSuccess"
77 92 />
78 93 <ProfitAnalysis @register="profitModalRegister" />
  94 + <RateModal @register="rateModalRegister" />
  95 + <ExportModal @register="exportModalRegister" :role="role" />
79 96 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" />
80 97 <HistoryDetail @register="historyDetailRegister" />
81 98 <FieldDetail @register="fieldDetailRegister" />
82 99 </div>
83 100 </template>
84 101 <script lang="ts">
85   - import { defineComponent, onMounted, ref, toRaw, toRefs, unref } from 'vue';
  102 + import { defineComponent, onMounted, ref, toRaw, computed } from 'vue';
86 103 import { BasicTable, useTable, TableAction } from '/@/components/Table';
87 104 import { FormOutlined } from '@ant-design/icons-vue';
88 105 import HeaderCell from '/@/components/Table/src/components/HeaderCell.vue';
... ... @@ -90,6 +107,8 @@
90 107  
91 108 import { useDrawer } from '/@/components/Drawer';
92 109 import ProfitAnalysis from './ProfitAnalysis.vue';
  110 + import RateModal from './RateModal.vue';
  111 + import ExportModal from './ExportModal.vue';
93 112 import { useModal } from '/@/components/Modal';
94 113  
95 114 import { getFormConfig, getOrderColumns, SELECT_FIELD_COLUMNS } from './tableData';
... ... @@ -98,10 +117,10 @@
98 117 import HistoryDetail from './HistoryDetail.vue';
99 118 import FieldDetail from './FieldDetail.vue';
100 119 import { createImgPreview } from '/@/components/Preview/index';
101   - import { getOrderList, orderExport } from '/@/api/project/order';
  120 + import { getOrderList } from '/@/api/project/order';
102 121 import { useOrderStoreWithOut } from '/@/store/modules/order';
103   - import { keyBy, reduce } from 'lodash-es';
104 122 import { useUserStoreWithOut } from '/@/store/modules/user';
  123 + import { ROLE } from './type.d';
105 124  
106 125 const orderStore = useOrderStoreWithOut();
107 126 const userStore = useUserStoreWithOut();
... ... @@ -118,16 +137,24 @@
118 137 CheckDetail,
119 138 HistoryDetail,
120 139 FieldDetail,
  140 + RateModal,
  141 + ExportModal,
121 142 },
122 143 setup() {
123 144 const checkedKeys = ref<Array<string | number>>([]);
124 145 const [profitModalRegister, { openModal: openProfitModal }] = useModal();
  146 + const [rateModalRegister, { openModal: openRateModal }] = useModal();
  147 + const [exportModalRegister, { openModal: openExportModal }] = useModal();
  148 +
125 149 const tooltipVisible = ref(false);
126 150 const [formDetailRegister, { openDrawer: openFormDetailDrawer }] = useDrawer();
127 151 const [historyDetailRegister, { openDrawer: openHistoryDetailDrawer }] = useDrawer();
128 152 const [fieldDetailRegister, { openDrawer: openFieldDetailDrawer }] = useDrawer();
129 153  
130 154 const user = userStore.getUserInfo;
  155 + const role = computed(() => {
  156 + return user?.roleSmallVO?.code;
  157 + });
131 158  
132 159 const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer();
133 160 onMounted(async () => {
... ... @@ -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 250 function handleFieldVisible(record) {
215 251 openFieldDetailDrawer(true, record);
216 252 }
... ... @@ -225,74 +261,15 @@
225 261 openFormDetailDrawer(true);
226 262 }
227 263  
228   - function handlePreview(url, e) {
  264 + function handlePreview(url) {
229 265 createImgPreview({ imageList: [url], defaultWidth: 500 });
230 266 // e?.stopPropagation();
231 267 // e?.preventDefault();
232 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 275 const handleFormSuccess = () => {
... ... @@ -300,9 +277,12 @@
300 277 };
301 278  
302 279 return {
  280 + user,
303 281 SELECT_FIELD_COLUMNS,
304 282 fieldDetailRegister,
305 283 profitModalRegister,
  284 + rateModalRegister,
  285 + exportModalRegister,
306 286 historyDetailRegister,
307 287 formDetailRegister,
308 288 handleProfitModal,
... ... @@ -321,9 +301,13 @@
321 301 handleHistory,
322 302 handleAdd,
323 303 createImgPreview,
324   - handleExport,
  304 + handleExportModal,
325 305 handlePreview,
326 306 handleFormSuccess,
  307 + handleRateModal,
  308 + openExportModal,
  309 + role,
  310 + ROLE,
327 311 };
328 312 },
329 313 });
... ... @@ -337,12 +321,17 @@
337 321 }
338 322  
339 323 .ant-table-cell img {
340   - width: 100px;
341   - height: 100px;
  324 + width: 40px;
  325 + height: 40px;
342 326 }
343 327  
344 328 .order-page .vben-basic-table .ant-form-item .ant-picker {
345 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 336 </style>
348 337 ./constant
... ...
src/views/project/order/tableData.tsx
1 1 import { ROLE } from './type.d';
2 2 import { useOrderInfo } from '/@/hooks/component/order';
3 3 import { useOrderStoreWithOut } from '/@/store/modules/order';
  4 +import { formatToDate } from '/@/utils/dateUtil';
4 5  
5 6 // 角色
6 7 // 业务员- 查看all,编辑-利润分析,报告书
... ... @@ -11,21 +12,27 @@ import { useOrderStoreWithOut } from &#39;/@/store/modules/order&#39;;
11 12 export const SELECT_FIELD_COLUMNS = [
12 13 'projectNo',
13 14 'customerCode',
  15 + 'productionDepartment',
14 16 'innerNo',
15 17 'poColor',
16 18 'cnColor',
17 19 'productStyle',
18 20 'outboundType',
19 21 'packetType',
  22 + 'ideaSource',
  23 + 'manualPreform1',
  24 + 'manualPreform2',
20 25 'midCheckResult',
21 26 'endCheckResult',
  27 + // 'exchangeRate',
  28 + 'businessPerson',
22 29 ];
23 30  
24 31 /**
25 32 *
26 33 * @returns 订单列表数据
27 34 */
28   -const ORDER_LIST_BASE_FIELDS = [
  35 +export const ORDER_LIST_BASE_FIELDS = [
29 36 {
30 37 title: '客户编码',
31 38 width: 150,
... ... @@ -110,11 +117,19 @@ const ORDER_LIST_BASE_FIELDS = [
110 117 title: '生成科拖货时间',
111 118 width: 150,
112 119 dataIndex: 'productionDepartmentConsignTime',
  120 + customRender: (column) => {
  121 + const { record } = column || {};
  122 + return formatToDate(record?.productionDepartmentConsignTime);
  123 + },
113 124 },
114 125 {
115 126 title: '订单上HOD时间',
116 127 width: 150,
117 128 dataIndex: 'orderHodTime',
  129 + customRender: (column) => {
  130 + const { record } = column || {};
  131 + return formatToDate(record?.orderHodTime);
  132 + },
118 133 },
119 134 {
120 135 title: '出库类型',
... ... @@ -126,9 +141,14 @@ const ORDER_LIST_BASE_FIELDS = [
126 141 width: 150,
127 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 153 title: '项目完成报告信息',
134 154 width: 150,
... ... @@ -137,35 +157,62 @@ const ORDER_LIST_REPORT_FIELDS = [
137 157 {
138 158 title: '想法来源',
139 159 width: 150,
140   - dataIndex: 'reportInfo.ideaSource',
  160 + dataIndex: 'ideaSource',
141 161 customRender: (column) => {
142 162 const { record } = column || {};
143 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 195 width: 150,
149   - dataIndex: 'reportInfo.manualPreform',
  196 + dataIndex: 'manualPreform2',
150 197 customRender: (column) => {
151 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 204 width: 150,
158   - dataIndex: 'reportInfo.ideaManualRate',
  205 + dataIndex: 'manualPreform2Rate',
159 206 customRender: (column) => {
160 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 217 title: '利润分析信息',
171 218 width: 150,
... ... @@ -177,7 +224,9 @@ const ORDER_LIST_PROFIT_FIELDS = [
177 224 dataIndex: 'customerPrice',
178 225 customRender: (column) => {
179 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 244 dataIndex: 'productionDepartmentPrice',
196 245 customRender: (column) => {
197 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 264 dataIndex: 'packetPrice',
205 265 customRender: (column) => {
206 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 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 318 title: '跟单信息',
244 319 width: 150,
... ... @@ -250,7 +325,7 @@ const ORDER_LIST_TRACK_FIELDS = [
250 325 dataIndex: 'ppTime',
251 326 customRender: (column) => {
252 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 343 dataIndex: 'esoSampleSendTime',
269 344 customRender: (column) => {
270 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 352 dataIndex: 'shippmentSampleSendTime',
278 353 customRender: (column) => {
279 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 370 dataIndex: 'selfTestPassTime',
296 371 customRender: (column) => {
297 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 379 dataIndex: 'aitexTestSendTime',
305 380 customRender: (column) => {
306 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 397 dataIndex: 'sgsTestSendTime',
323 398 customRender: (column) => {
324 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 424 dataIndex: 'latestArrivalTime',
350 425 customRender: (column) => {
351 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 433 dataIndex: 'latestBkTime',
359 434 customRender: (column) => {
360 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 445 title: '质检信息',
371 446 width: 150,
... ... @@ -378,7 +453,7 @@ const ORDER_LIST_INSPECT_FIELDS = [
378 453 dataIndex: 'midCheckApplyTime',
379 454 customRender: (column) => {
380 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 480 dataIndex: 'endCheckApplyTime',
406 481 customRender: (column) => {
407 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 568 },
494 569 ];
495 570  
  571 +// 订单列表,也就是读权限
496 572 export function getOrderColumns(role: ROLE) {
  573 + // 管理员/业务员看到所有列
497 574 if (role === ROLE.ADMIN || role === ROLE.BUSINESS) {
498 575 return [
499 576 ...ORDER_LIST_BASE_FIELDS,
... ... @@ -504,15 +581,16 @@ export function getOrderColumns(role: ROLE) {
504 581 ...ORDER_LIST_SCHEDULE,
505 582 ];
506 583 }
507   -
  584 + // 跟单 -基本信息-利润分析(单价,总价),跟单,质检
508 585 if (role === ROLE.TRACKER) {
509 586 return [
510 587 ...ORDER_LIST_BASE_FIELDS,
511 588 ...ORDER_LIST_PROFIT_FIELDS.map((item) => {
512 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 592 item.children = children;
  593 +
516 594 return item;
517 595 }),
518 596 ...ORDER_LIST_TRACK_FIELDS,
... ... @@ -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 604 return [
526 605 ...ORDER_LIST_BASE_FIELDS,
527 606 ...ORDER_LIST_TRACK_FIELDS,
... ... @@ -532,7 +611,9 @@ export function getOrderColumns(role: ROLE) {
532 611  
533 612 return [];
534 613 }
535   -
  614 +/**
  615 + * drawer面板的字段
  616 + */
536 617 // 基本信息
537 618 export const FIELDS_BASE_INFO = [
538 619 {
... ... @@ -670,6 +751,13 @@ export const FIELDS_BASE_INFO = [
670 751 label: '包装类型',
671 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 768 optionField: 'ideaSource',
681 769 labelWidth: 150,
682 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 783 component: 'Select',
688   - optionField: 'manualPreform',
  784 + optionField: 'manualPreform1',
689 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 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 946 field: 'customerPrice',
837 947 component: 'InputNumber',
838 948 label: '客户单价',
839   - // rules: [{ required: true }],
  949 + rules: [{ required: true }],
840 950 },
841 951 // {
842 952 // field: 'customerTotalPrice',
... ... @@ -848,7 +958,8 @@ export const FIELDS_PROFIT_INFO = [
848 958 field: 'customerCurrency',
849 959 component: 'Select',
850 960 label: '客户单价货币单位',
851   - // rules: [{ required: true }],
  961 + labelWidth: 400,
  962 + rules: [{ required: true }],
852 963 componentProps: {
853 964 options: [
854 965 { label: '$', value: '$' },
... ... @@ -860,13 +971,13 @@ export const FIELDS_PROFIT_INFO = [
860 971 field: 'productionDepartmentPrice',
861 972 component: 'InputNumber',
862 973 label: '生成科单价',
863   - // rules: [{ required: true }],
  974 + rules: [{ required: true }],
864 975 },
865 976 {
866 977 field: 'productionDepartmentCurrency',
867 978 component: 'Select',
868 979 label: '生成科货币单位',
869   - // rules: [{ required: true }],
  980 + rules: [{ required: true }],
870 981 componentProps: {
871 982 options: [
872 983 { label: '$', value: '$' },
... ... @@ -884,6 +995,14 @@ export const FIELDS_PROFIT_INFO = [
884 995 label: '包装费用',
885 996 component: 'InputNumber',
886 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 1006 // rules: [{ required: true }],
888 1007 },
889 1008 // {
... ... @@ -892,30 +1011,39 @@ export const FIELDS_PROFIT_INFO = [
892 1011 // field: 'packetTotalPrice',
893 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 1036 component: 'Select',
898   - field: 'packetCurrency',
899   - // rules: [{ required: true }],
  1037 + field: 'profitType',
900 1038 componentProps: {
  1039 + defaultValue: '0',
901 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 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 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 1341 component: 'Select',
1202 1342 colProps: {
1203 1343 span: 6,
1204 1344 },
1205 1345 labelWidth: 150,
1206   -
1207 1346 componentProps: {
1208 1347 options: manualPreform,
1209 1348 },
... ...
src/views/project/order/type.d.ts
1 1 export enum ROLE {
2 2 ADMIN = 'admin', // 超管
  3 + CUSTOM_ADMIN = 'custom_admin', // 客户管理员
  4 + DATA_REPORT_USER = 'data_report_user', //数据分析员
3 5 BUSINESS = 'business_user', // 业务员
4 6 TRACKER = 'tracker_user', // 跟单员
5 7 INSPECT = 'inspect_user', // 质检员
... ...
src/views/sys/login/ForgetPasswordForm.vue
... ... @@ -2,21 +2,49 @@
2 2 <template v-if="getShow">
3 3 <LoginFormTitle class="enter-x" />
4 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 6 <Input
7 7 size="large"
8 8 v-model:value="formData.account"
9 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 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 42 </FormItem>
16   - <FormItem name="sms" class="enter-x">
  43 + <FormItem name="smsCaptchaCode" class="enter-x">
17 44 <CountdownInput
18 45 size="large"
19   - v-model:value="formData.sms"
  46 + v-model:value="formData.smsCaptchaCode"
  47 + :sendCodeApi="handleSendMsg"
20 48 :placeholder="t('sys.login.smsCode')"
21 49 />
22 50 </FormItem>
... ... @@ -33,12 +61,14 @@
33 61 </template>
34 62 </template>
35 63 <script lang="ts" setup>
36   - import { reactive, ref, computed, unref } from 'vue';
  64 + import { reactive, ref, computed, unref, onMounted } from 'vue';
37 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 67 import { CountdownInput } from '/@/components/CountDown';
40 68 import { useI18n } from '/@/hooks/web/useI18n';
41 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 73 const FormItem = Form.Item;
44 74 const { t } = useI18n();
... ... @@ -49,16 +79,56 @@
49 79 const loading = ref(false);
50 80  
51 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 123 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD);
58 124  
59 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 134 </script>
... ...
src/views/sys/login/LoginForm.vue
... ... @@ -34,13 +34,15 @@
34 34 />
35 35 </FormItem>
36 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 41 </FormItem>
39 42  
40   - <ARow class="enter-x">
  43 + <!-- <ARow class="enter-x">
41 44 <ACol :span="12">
42 45 <FormItem>
43   - <!-- No logic, you need to deal with it yourself -->
44 46 <Checkbox v-model:checked="rememberMe" size="small">
45 47 {{ t('sys.login.rememberMe') }}
46 48 </Checkbox>
... ... @@ -48,13 +50,12 @@
48 50 </ACol>
49 51 <ACol :span="12">
50 52 <FormItem :style="{ 'text-align': 'right' }">
51   - <!-- No logic, you need to deal with it yourself -->
52 53 <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
53 54 {{ t('sys.login.forgetPassword') }}
54 55 </Button>
55 56 </FormItem>
56 57 </ACol>
57   - </ARow>
  58 + </ARow> -->
58 59  
59 60 <FormItem class="enter-x">
60 61 <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
... ... @@ -64,23 +65,23 @@
64 65 {{ t('sys.login.registerButton') }}
65 66 </Button> -->
66 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 70 <Button block @click="setLoginState(LoginStateEnum.MOBILE)">
70 71 {{ t('sys.login.mobileSignInFormTitle') }}
71 72 </Button>
72 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 75 <Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
75 76 {{ t('sys.login.qrSignInFormTitle') }}
76 77 </Button>
77 78 </ACol> -->
78   - <!-- <ACol :md="6" :xs="24">
  79 + <!-- <ACol :md="6" :xs="24">
79 80 <Button block @click="setLoginState(LoginStateEnum.REGISTER)">
80 81 {{ t('sys.login.registerButton') }}
81 82 </Button>
82 83 </ACol> -->
83   - </ARow>
  84 + <!-- </ARow> -->
84 85 <!--
85 86 <Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
86 87  
... ... @@ -133,8 +134,8 @@
133 134 const imgCaptchaUuid = ref('');
134 135  
135 136 const formData = reactive({
136   - userName: 'admin',
137   - password: '123456',
  137 + userName: '',
  138 + password: '',
138 139 imgCaptchaCode: '',
139 140 imgCaptchaUuid: '',
140 141 });
... ...
src/views/sys/login/useLogin.ts
... ... @@ -53,6 +53,7 @@ export function useFormRules(formData?: Recordable) {
53 53 const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder')));
54 54 const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder')));
55 55 const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder')));
  56 + const getConfirmPasswordFormRule = computed(() => createRule(t('请输入确认密码')));
56 57  
57 58 const validatePolicy = async (_: RuleObject, value: boolean) => {
58 59 return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve();
... ... @@ -75,10 +76,11 @@ export function useFormRules(formData?: Recordable) {
75 76 const passwordFormRule = unref(getPasswordFormRule);
76 77 const smsFormRule = unref(getSmsFormRule);
77 78 const mobileFormRule = unref(getMobileFormRule);
  79 + const confirmPasswordFormRule = unref(getConfirmPasswordFormRule);
78 80  
79 81 const mobileRule = {
80 82 sms: smsFormRule,
81   - mobile: mobileFormRule,
  83 + phone: mobileFormRule,
82 84 };
83 85 switch (unref(currentState)) {
84 86 // register form rules
... ... @@ -97,6 +99,8 @@ export function useFormRules(formData?: Recordable) {
97 99 case LoginStateEnum.RESET_PASSWORD:
98 100 return {
99 101 userName: accountFormRule,
  102 + password: passwordFormRule,
  103 + confirmPassword: confirmPasswordFormRule,
100 104 ...mobileRule,
101 105 };
102 106  
... ...
vite.config.ts
... ... @@ -20,15 +20,15 @@ export default defineApplicationConfig({
20 20 server: {
21 21 proxy: {
22 22 '/basic-api/order': {
23   - target: 'http://39.108.227.113:8010',
  23 + target: 'http://39.108.227.113:8000',
24 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 26 changeOrigin: true,
27 27 ws: true,
28 28 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''),
29 29 },
30 30 '/api/localStorage/upload': {
31   - target: 'http://39.108.227.113:8010',
  31 + target: 'http://39.108.227.113:8000',
32 32 changeOrigin: true,
33 33 ws: true,
34 34 // rewrite: (path) => {
... ...