刘洋 1 год назад
Родитель
Сommit
054f5be57c

+ 3 - 0
components.d.ts

@@ -16,6 +16,7 @@ declare module 'vue' {
     TAside: typeof import('tdesign-vue-next')['Aside']
     TButton: typeof import('tdesign-vue-next')['Button']
     TCheckbox: typeof import('tdesign-vue-next')['Checkbox']
+    TCol: typeof import('tdesign-vue-next')['Col']
     TConfigProvider: typeof import('tdesign-vue-next')['ConfigProvider']
     TContent: typeof import('tdesign-vue-next')['Content']
     TDatePicker: typeof import('tdesign-vue-next')['DatePicker']
@@ -35,7 +36,9 @@ declare module 'vue' {
     TMenuItem: typeof import('tdesign-vue-next')['MenuItem']
     TOption: typeof import('tdesign-vue-next')['Option']
     TPopconfirm: typeof import('tdesign-vue-next')['Popconfirm']
+    TRow: typeof import('tdesign-vue-next')['Row']
     TSelect: typeof import('tdesign-vue-next')['Select']
+    TSpace: typeof import('tdesign-vue-next')['Space']
     TSubmenu: typeof import('tdesign-vue-next')['Submenu']
     TTable: typeof import('tdesign-vue-next')['Table']
     TTabPanel: typeof import('tdesign-vue-next')['TabPanel']

+ 1 - 1
package.json

@@ -29,7 +29,7 @@
     "mockjs": "^1.1.0",
     "nprogress": "^0.2.0",
     "pinia": "^2.0.27",
-    "tdesign-vue-next": "^1.3.11",
+    "tdesign-vue-next": "^1.3.12",
     "tvision-color": "^1.5.0",
     "unplugin-vue-setup-extend-plus": "^1.0.0",
     "vue": "^3.3.4",

+ 5 - 2
src/layout/left-menu.vue

@@ -4,7 +4,7 @@
       :key="key"
       theme="dark"
       v-model:expanded="openKeys"
-      :default-value="activeKey"
+      v-model:value="activeKey"
       :collapsed="appStore.menuCollapse"
       :width="
         (appStore.menuCollapse ? appStore.collapseWidth : appStore.menuWidth) +
@@ -39,7 +39,7 @@ import { ref, watch, onBeforeMount } from 'vue';
 import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
 import { useAppStore, useUserStore } from '@/store';
 import childrenMenu from './children-menu.vue';
-
+import { moduleMap } from '@/router/asyncRoutes';
 const route = useRoute();
 const router = useRouter();
 // const menus = ref([]);
@@ -55,6 +55,9 @@ onBeforeMount(() => {
 });
 onBeforeRouteUpdate((to) => {
   activeKey.value = to.name;
+  let firstPath = to.path.split('/')[1];
+  let curModuleName = moduleMap[firstPath];
+  userStore.setCurPageModule(curModuleName);
 });
 watch(
   () => userStore.moduleMenus,

+ 26 - 6
src/utils/tool.js

@@ -37,10 +37,10 @@ const typeColor = (type = 'default') => {
 export const local = {
   set(table, settings) {
     const _set = JSON.stringify(settings);
-    return localStorage.setItem('sop_'+table, _set);
+    return localStorage.setItem('sop_' + table, _set);
   },
   get(table) {
-    let data = localStorage.getItem('sop_'+table);
+    let data = localStorage.getItem('sop_' + table);
     try {
       data = JSON.parse(data);
     } catch (err) {
@@ -49,7 +49,7 @@ export const local = {
     return data;
   },
   remove(table) {
-    return localStorage.removeItem('sop_'+table);
+    return localStorage.removeItem('sop_' + table);
   },
   clear() {
     return localStorage.clear();
@@ -62,10 +62,10 @@ export const local = {
 export const session = {
   set(table, settings) {
     const _set = JSON.stringify(settings);
-    return sessionStorage.setItem('sop_'+table, _set);
+    return sessionStorage.setItem('sop_' + table, _set);
   },
   get(table) {
-    let data = sessionStorage.getItem('sop_'+table);
+    let data = sessionStorage.getItem('sop_' + table);
     try {
       data = JSON.parse(data);
     } catch (err) {
@@ -74,7 +74,7 @@ export const session = {
     return data;
   },
   remove(table) {
-    return sessionStorage.removeItem('sop_'+table);
+    return sessionStorage.removeItem('sop_' + table);
   },
   clear() {
     return sessionStorage.clear();
@@ -316,3 +316,23 @@ export const getTreeList = (oldDataList, sortField = '') => {
   }, []);
   return formatArray;
 };
+
+/**
+ * 将一维数组转换为二维数组
+ * @param {*} arr
+ * @returns
+ */
+export const toSecondFloorArray = (arr) => {
+  if (!Array.isArray(arr)) {
+    throw new TypeError(`${arr}不是数组`);
+  }
+  const newArr = arr.reduce((initArr, item, index) => {
+    if (index % 2 == 0) {
+      initArr.push([item]);
+    } else {
+      initArr[initArr.length - 1].push(item);
+    }
+    return initArr;
+  }, []);
+  return newArr;
+};

+ 28 - 0
src/views/sop/components/LABEL.vue

@@ -0,0 +1,28 @@
+<template>
+  <div class="label">
+    <p v-if="label" class="sub-label">{{ label }}</p>
+    <div class="read-only"></div>
+  </div>
+</template>
+<script setup name="LABEL">
+import { ref } from 'vue';
+const { config, label } = defineProps(['config', 'label']);
+const value = ref('');
+</script>
+<style lang="less" scoped>
+.label {
+  width: 100%;
+  .sub-label {
+    color: #555;
+    font-size: 14px;
+    margin-bottom: 5px;
+  }
+  .read-only {
+    height: 30px;
+    border-radius: 4px;
+    background-color: #f5f6f8;
+    line-height: 30px;
+    padding-left: 8px;
+  }
+}
+</style>

+ 19 - 0
src/views/sop/components/LABELS.vue

@@ -0,0 +1,19 @@
+<template>
+  <div class="labels">
+    <LABEL
+      :config="item"
+      :label="item.title"
+      :key="item.id"
+      v-for="item in config.children"
+    ></LABEL>
+  </div>
+</template>
+<script setup name="LABEL">
+import LABEL from './LABEL.vue';
+const { config } = defineProps(['config']);
+</script>
+<style lang="less" scoped>
+.labels {
+  width: 100%;
+}
+</style>

+ 16 - 0
src/views/sop/components/POP_SELECT.vue

@@ -0,0 +1,16 @@
+<template>
+  <div class="pop-select"></div>
+</template>
+<script setup name="POPSELECT">
+import { ref } from 'vue';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref('');
+//   onChange({ prop: config.binding, value: value.value });
+</script>
+<style lang="less" scoped>
+.pop-select {
+  width: 100%;
+  height: 32px;
+  border: 1px dashed #ddd;
+}
+</style>

+ 28 - 0
src/views/sop/components/SELECT.vue

@@ -0,0 +1,28 @@
+<template>
+  <t-select v-model="value" @change="change"></t-select>
+</template>
+<script setup name="SELECT">
+import { ref, onMounted } from 'vue';
+import { useRequest } from 'vue-request';
+import { request } from '@/utils/request.js';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref('');
+const options = ref([]);
+const change = () => {
+  onChange({ prop: config.binding, value: value.value });
+};
+const getOptionsApi = () => {
+  request({
+    url: config.dataGrid,
+    method: 'post',
+  });
+};
+const getOptions = async () => {
+  const { data } = useRequest(getOptionsApi);
+  //todo 将接口数据转换成options
+};
+onMounted(() => {
+  getOptions();
+});
+</script>
+<style></style>

+ 3 - 1
src/views/sop/components/TEXT.vue

@@ -1,8 +1,10 @@
 <template>
-  <t-input v-model="value" @input="onInput"></t-input>
+  <t-input v-model="value" @input="onInput" v-if="!config.readable"></t-input>
+  <LABEL :config="config" v-else></LABEL>
 </template>
 <script setup name="TEXT">
 import { ref } from 'vue';
+import LABEL from './LABEL';
 const { config, onChange } = defineProps(['config', 'onChange']);
 const value = ref('');
 const onInput = () => {

+ 19 - 4
src/views/sop/components/my-form-item.vue

@@ -1,11 +1,15 @@
 <template>
-  <RenderTest></RenderTest>
+  <t-form-item :label="config.title" :name="config.binding">
+    <RenderTest></RenderTest>
+  </t-form-item>
 </template>
 <script setup lang="jsx" name="MyFormItem">
 import { defineComponent } from 'vue';
 import TEXT from './TEXT.vue';
+import SELECT from './SELECT.vue';
+import LABELS from './LABELS';
+import LABEL from './LABEL';
 const { config } = defineProps(['config']);
-console.log('config:', config);
 const onChange = (obj) => {
   console.log('obj', obj);
 };
@@ -17,10 +21,21 @@ const RenderTest = defineComponent({
     switch (config.code) {
       case 'TEXT':
         return <TEXT config={config} onChange={onChange}></TEXT>;
+      case 'SELECT':
+        return <SELECT config={config} onChange={onChange}></SELECT>;
+      case 'LABELS':
+        return <LABELS config={config}></LABELS>;
+      case 'LABEL':
+        return <LABEL config={config}></LABEL>;
       default:
-        return <div>你给的code是什么破玩意</div>;
+        return <div>你的code是什么破玩意</div>;
     }
   },
 });
 </script>
-<style></style>
+<style scoped lang="less">
+.my-form-item {
+  width: 50%;
+  padding: 10px;
+}
+</style>

+ 241 - 17
src/views/sop/sop-manage/sop-flow/index.vue

@@ -1,7 +1,19 @@
 <template>
   <div class="sop-flow">
     <div class="page-wrap">
-      <MyFormItem :config="config"></MyFormItem>
+      <t-form ref="form" :labelWidth="130">
+        <t-row
+          :gutter="[{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }, 24]"
+        >
+          <t-col :span="6" v-for="config in formConfig" :key="config.id">
+            <MyFormItem :config="config"></MyFormItem>
+          </t-col>
+        </t-row>
+      </t-form>
+      <div class="m-t-30px m-b-30px text-center">
+        <t-button theme="primary" @click="submitHandle">提交</t-button>
+        <t-button theme="default" class="m-l-20px" @click="back">返回</t-button>
+      </div>
     </div>
   </div>
 </template>
@@ -9,21 +21,233 @@
 <script setup name="SopFlow">
 import { ref } from 'vue';
 import MyFormItem from '../../components/my-form-item.vue';
-const config = ref({
-  id: '1',
-  code: 'TEXT', //编码,TEXT:文本,TEXTAREA:文本域,SELECT:下拉框,RADIO:单选框,CHECKBOX:复选框,DATE:日期,BUTTON:按钮,IMG:图片,VIDEO:视频,AUDIO:音频,FILE:文件,POP_SELECT:弹出选择框,LABEL:标签,TABLE:表格,SIGN:签名,OTHER:其它
-  type: 'FORM', //类型,FORM:表单,TABLE:表格,OTHER:其它
-  formId: 'crm_child_no', //表单控件id(实际会带上流程key,如:f_usertask_start|crm_child_no)
-  formName: 'crm_child_no', //表单控件名称
-  title: '项目子单编号', //表单控件标题
-  inputType: 'STRING', //输入类型,STRING:字符串,INT:整型,LONG:长整型,DOUBLE:浮点型,ENUM:枚举,DATE:日期,BOOL:布尔,BIGDECIMAL:精确浮点
-  required: false, //是否必填,false:非必填,true:必填
-  readable: true, //是否只读,false:非只读,true:只读
-  writable: false, //是否可写,false:非可写,true:可写
-  visable: true, //是否可见,false:不可见,true:可见
-  binding: 'crm_child_no', //绑定的数据字段
-  name: '文本', //名称
-});
+const form = ref();
+let formConfig = ref([
+  {
+    id: '1',
+    code: 'TEXT', //编码,TEXT:文本,TEXTAREA:文本域,SELECT:下拉框,RADIO:单选框,CHECKBOX:复选框,DATE:日期,BUTTON:按钮,IMG:图片,VIDEO:视频,AUDIO:音频,FILE:文件,POP_SELECT:弹出选择框,LABEL:标签,TABLE:表格,SIGN:签名,OTHER:其它
+    type: 'FORM', //类型,FORM:表单,TABLE:表格,OTHER:其它
+    formId: 'crm_child_no', //表单控件id(实际会带上流程key,如:f_usertask_start|crm_child_no)
+    formName: 'crm_child_no', //表单控件名称
+    title: '项目子单编号', //表单控件标题
+    inputType: 'STRING', //输入类型,STRING:字符串,INT:整型,LONG:长整型,DOUBLE:浮点型,ENUM:枚举,DATE:日期,BOOL:布尔,BIGDECIMAL:精确浮点
+    required: false, //是否必填,false:非必填,true:必填
+    readable: true, //是否只读,false:非只读,true:只读
+    writable: false, //是否可写,false:非可写,true:可写
+    visable: true, //是否可见,false:不可见,true:可见
+    binding: 'crm_child_no', //绑定的数据字段
+    name: '文本', //名称
+  },
+  {
+    id: '2',
+    code: 'SELECT',
+    type: 'FORM',
+    formId: 'custom_type',
+    formName: 'custom_type',
+    title: '客户类型',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'custom_type',
+    dataGrid: '/api/admin/widget/custom/list', //需要填充的api
+    name: '下拉框',
+  },
+  {
+    id: '3',
+    code: 'POP_SELECT',
+    type: 'FORM',
+    formId: 'crm_manager',
+    formName: 'crm_manager',
+    title: '派单客户经理',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'crm_manager',
+    dataGrid: '/api/admin/widget/crm/manager',
+    name: '弹出选择框',
+  },
+  {
+    id: '4',
+    code: 'SELECT',
+    type: 'FORM',
+    formId: 'custom_name',
+    formName: 'custom_name',
+    title: '客户名称',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'custom_name',
+    dataGrid: '/api/admin/widget/school/list',
+    name: '下拉框',
+  },
+  {
+    id: '5',
+    code: 'SELECT',
+    type: 'FORM',
+    formId: 'crm_parent_no',
+    formName: 'crm_parent_no',
+    title: '项目母单编号',
+    required: false,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'crm_parent_no',
+    dataGrid: '/api/admin/widget/crm/parent_no/list',
+    name: '下拉框',
+  },
+  {
+    id: '6',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'crm_name',
+    formName: 'crm_name',
+    title: '项目名称',
+    inputType: 'STRING',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    name: '文本',
+  },
+  {
+    id: '7',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'org_name',
+    formName: 'org_name',
+    title: '学院分(子)机构',
+    inputType: 'STRING',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    name: '文本',
+  },
+  {
+    id: '8',
+    code: 'SELECT',
+    type: 'FORM',
+    formId: 'product',
+    formName: 'product',
+    title: '实施产品',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'product',
+    dataGrid: '/api/admin/widget/product/list',
+    name: '下拉框',
+  },
+  {
+    id: '9',
+    code: 'POP_SELECT',
+    type: 'FORM',
+    formId: 'child_manager',
+    formName: 'child_manager',
+    title: '子项目经理',
+    required: true,
+    readable: false,
+    writable: true,
+    visable: true,
+    binding: 'child_manager',
+    dataGrid: '/api/admin/widget/crm/manager',
+    name: '弹出选择框',
+  },
+  // {
+  //   id: '10',
+  //   code: 'LABELS',
+  //   type: 'FORM',
+  //   formId: 'crm_info',
+  //   formName: 'crm_info',
+  //   title: '派单信息',
+  //   inputType: 'STRING',
+  //   required: false,
+  //   readable: true,
+  //   writable: false,
+  //   visable: true,
+  //   name: '标签',
+  // },
+  {
+    id: '11',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'exam_start_time',
+    formName: 'exam_start_time',
+    title: '考试开始时间',
+    inputType: 'STRING',
+    required: false,
+    readable: true,
+    writable: false,
+    visable: true,
+    binding: 'exam_start_time',
+    name: '文本',
+  },
+  {
+    id: '12',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'exam_end_time',
+    formName: 'exam_end_time',
+    title: '考试结束时间',
+    inputType: 'STRING',
+    required: false,
+    readable: true,
+    writable: false,
+    visable: true,
+    binding: 'exam_end_time',
+    name: '文本',
+  },
+  {
+    id: '13',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'remark',
+    formName: 'remark',
+    title: '特殊要求及备注',
+    inputType: 'STRING',
+    required: false,
+    readable: true,
+    writable: false,
+    visable: true,
+    binding: 'remark',
+    name: '文本',
+  },
+  {
+    id: '14',
+    code: 'TEXT',
+    type: 'FORM',
+    formId: 'project_type',
+    formName: 'project_type',
+    title: '项目类型',
+    inputType: 'STRING',
+    required: false,
+    readable: true,
+    writable: false,
+    visable: true,
+    binding: 'project_type',
+    name: '文本',
+  },
+]);
+
+const submitHandle = () => {
+  form.value.validate().then(async (result) => {
+    alert(result);
+    if (result === true) {
+    }
+  });
+};
+const back = () => {
+  history.back();
+};
 </script>
 
-<style></style>
+<style lang="less" scoped>
+.sop-flow {
+  .page-wrap {
+    padding-right: 30%;
+  }
+}
+</style>