zhengyiming
2025-02-12 006e8527857850dfd01371384afa532af5a001f7
Merge branch 'master' of http://120.26.58.240:8888/r/flexJobMiniApp
8个文件已修改
23个文件已添加
1个文件已删除
1221 ■■■■■ 已修改文件
apps/cMiniApp/project.private.config.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/app.config.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/assets/mine/icon-agreement.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/assets/mine/icon-collect.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/assets/mine/icon-recruit.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Input/ChooseInput.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Input/ChooseInputWithAreaPicker.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Input/ChooseInputWithPicker.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Input/NumberInput.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Input/input.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/Portal.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/PortalManager.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/index.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/portal-consumer.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/portal-container.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/portal-host.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Portal/portal.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/UserHome/UserHomeTopView.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/constants/router.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/mine/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/mine/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/editMineInfo/InnerPage.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/editMineInfo/constants/index.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/editMineInfo/editMineInfo.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/editMineInfo/editMineInfo.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/InnerPage.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/MineAgreementSignDetailItem.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/mineAgreementSignDetail.vue 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/mineAgreementSignDetailItem.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/InnerPage.vue 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/mineCurriculumVitae.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/mineCurriculumVitae.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/project.private.config.json
@@ -35,6 +35,13 @@
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "",
                    "pathName": "subpackages/mine/mineCurriculumVitae/mineCurriculumVitae",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                }
            ]
        }
apps/cMiniApp/src/app.config.ts
@@ -79,6 +79,8 @@
        'mineCollectTask/mineCollectTask',
        'mineAgreementSign/mineAgreementSign',
        'mineAgreementSignDetail/mineAgreementSignDetail',
        'mineCurriculumVitae/mineCurriculumVitae',
        'editMineInfo/editMineInfo',
        'setting/setting',
      ],
    },
apps/cMiniApp/src/assets/mine/icon-agreement.png
apps/cMiniApp/src/assets/mine/icon-collect.png
apps/cMiniApp/src/assets/mine/icon-recruit.png
apps/cMiniApp/src/components/Input/ChooseInput.vue
New file
@@ -0,0 +1,37 @@
<template>
  <nut-input
    class="nut-input-text bole-input-text"
    type="text"
    readonly
    alwaysEmbed
    v-bind="$attrs"
  >
    <template #clear>
      <slot name="clear"></slot>
    </template>
    <template #right>
      <slot name="right">
        <RectRight :size="12" class="common-choose-input-icon" />
      </slot>
    </template>
  </nut-input>
</template>
<script setup lang="ts">
import { RectRight } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'ChooseInput',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.common-choose-input-icon {
  //   width: 13px;
  //   height: 23px;
  margin-left: 18px;
  color: boleGetCssVar('text-color', 'primary');
}
</style>
apps/cMiniApp/src/components/Input/ChooseInputWithAreaPicker.vue
New file
@@ -0,0 +1,76 @@
<template>
  <ChooseInput :modelValue="inputValue" @click="handleOpen()"></ChooseInput>
</template>
<script setup lang="ts">
import { useAllAreaList } from '@/hooks';
import Portal from '../Portal';
import ChooseInput from './ChooseInput.vue';
import { Popup, Picker } from '@nutui/nutui-taro';
defineOptions({
  name: 'ChooseInputWithAreaPicker',
});
const { findAreaNameFromCode } = useAllAreaList();
type Props = {
  fieldNames?: object;
  columns: API.AreaTreeNode[];
  modelValue: Array<string | number>;
  title?: string;
};
const props = withDefaults(defineProps<Props>(), {
  title: '选择地址',
  fieldNames: () => ({
    text: 'areaName',
    value: 'areaCode',
    children: 'children',
  }),
});
const inputValue = computed(() =>
  props.modelValue.map((x) => findAreaNameFromCode(Number(x))).join(',')
);
const emit = defineEmits<{
  (e: 'update:modelValue', val: Array<string | number>): void;
}>();
function handleOpen() {
  Portal.add((key) => {
    return h(
      Portal.Container,
      { keyNumber: key, delayOpen: true },
      {
        default: ({ open, onClose }) =>
          h(
            Popup,
            {
              visible: open.value,
              'onUpdate:visible': (value) => !value && onClose(),
              position: 'bottom',
            },
            {
              default: () =>
                h(Picker, {
                  modelValue: props.modelValue,
                  columns: props.columns,
                  fieldNames: props.fieldNames,
                  title: props.title,
                  onCancel: onClose,
                  onConfirm: ({ selectedValue, selectedOptions }) => {
                    emit(
                      'update:modelValue',
                      selectedOptions.map((x) => x.areaCode)
                    );
                    onClose();
                  },
                }),
            }
          ),
      }
    );
  });
}
</script>
apps/cMiniApp/src/components/Input/ChooseInputWithPicker.vue
New file
@@ -0,0 +1,73 @@
<template>
  <ChooseInput :modelValue="inputValue" @click="handleOpen()"></ChooseInput>
</template>
<script setup lang="ts">
import Portal from '../Portal';
import ChooseInput from './ChooseInput.vue';
import { Popup, Picker } from '@nutui/nutui-taro';
import { convertOptions, ValueEnum } from './input';
defineOptions({
  name: 'ChooseInputWithPicker',
});
type Props = {
  enumLabelKey?: string;
  enumValueKey?: string;
  valueEnum?: ValueEnum;
  modelValue: string | number;
};
const props = withDefaults(defineProps<Props>(), {
  enumLabelKey: 'name',
  enumValueKey: 'id',
});
const emit = defineEmits<{
  (e: 'update:modelValue', val: string | number): void;
}>();
const options = computed(() =>
  convertOptions(props.valueEnum, props.enumLabelKey, props.enumValueKey)
);
const inputValue = computed(
  () => options.value?.find((x) => x.value === props.modelValue)?.text ?? ''
);
function handleOpen() {
  console.log('handleOpen: ');
  const _modelValue = [props.modelValue];
  Portal.add((key) => {
    return h(
      Portal.Container,
      { keyNumber: key, delayOpen: true },
      {
        default: ({ open, onClose }) =>
          h(
            Popup,
            {
              visible: open.value,
              'onUpdate:visible': (value) => !value && onClose(),
              position: 'bottom',
            },
            {
              default: () =>
                h(Picker, {
                  modelValue: _modelValue,
                  columns: options.value,
                  onCancel: onClose,
                  onConfirm: ({ selectedValue, selectedOptions }) => {
                    console.log('selectedValue: ', selectedValue, selectedOptions);
                    emit('update:modelValue', selectedOptions[0].value);
                    onClose();
                  },
                }),
            }
          ),
      }
    );
  });
}
</script>
apps/cMiniApp/src/components/Input/NumberInput.vue
New file
@@ -0,0 +1,55 @@
<template>
  <nut-input type="number" :formatter="formatter" formatTrigger="onBlur">
    <template #right>
      <slot name="right"></slot>
    </template>
  </nut-input>
</template>
<script setup lang="ts">
defineOptions({
  name: 'NumberInput',
});
type Props = {
  min?: number;
  max?: number;
  precision?: number;
};
const props = withDefaults(defineProps<Props>(), {
  max: Math.pow(2, 53) - 1,
});
function formatter(value: string): string {
  const newVal = value !== '' ? Number.parseFloat(value) : '';
  if (Number.isNaN(newVal)) {
    return '';
  }
  if (newVal && newVal > props.max) {
    return `${toPrecision(props.max)}`;
  }
  if (props.min !== undefined && newVal && newVal < props.min) {
    return `${toPrecision(props.min)}`;
  }
  return newVal !== '' ? `${toPrecision(newVal)}` : newVal;
}
function toPrecision(num: number) {
  if (props.precision) {
    if (props.precision === 0) return Math.round(num);
    let snum = String(num);
    const pointPos = snum.indexOf('.');
    if (pointPos === -1) return num;
    const nums = snum.replace('.', '').split('');
    const datum = nums[pointPos + props.precision];
    if (!datum) return num;
    const length = snum.length;
    if (snum.charAt(length - 1) === '5') {
      snum = `${snum.slice(0, Math.max(0, length - 1))}6`;
    }
    return Number(snum).toFixed(props.precision);
  }
  return String(num);
}
</script>
apps/cMiniApp/src/components/Input/input.ts
New file
@@ -0,0 +1,31 @@
import _ from 'lodash';
export type ValueEnumItem = { [key: string]: any };
export type ValueEnum = ValueEnumItem[] | Record<string | number, string>;
export type OptionItem = {
  text: string;
  value: string | number;
  [key: string]: any;
};
export function convertOptions(
  valueEnum: ValueEnum,
  enumLabelKey: string,
  enumValueKey: string
): OptionItem[] {
  return _.isArray(valueEnum)
    ? valueEnum.map((x) => ({
        ...x,
        text: x[enumLabelKey],
        value: _.isNaN(Number(x[enumValueKey])) ? x[enumValueKey] : Number(x[enumValueKey]),
      }))
    : Object.keys(valueEnum).map((x) => ({
        value: _.isNaN(Number(x)) ? x : Number(x),
        text: valueEnum[x],
      }));
}
export type ChooseCheckBoxOptionItem = {
  text: string;
  value: string | number;
};
apps/cMiniApp/src/components/Portal/Portal.vue
New file
@@ -0,0 +1,19 @@
<template>
  <PortalConsumer :manager="portalContext">
    <template #default>
      <slot />
    </template>
  </PortalConsumer>
</template>
<script setup lang="ts">
import PortalConsumer from './portal-consumer.vue';
// import PortalContainer from './portal-container';
import { portal, usePortalContext } from './portal';
defineOptions({
  name: 'Portal',
});
const portalContext = usePortalContext();
</script>
apps/cMiniApp/src/components/Portal/PortalManager.vue
New file
@@ -0,0 +1,44 @@
<script lang="ts">
import { State, PortalNode } from './portal';
export default defineComponent({
  name: 'PortalManager',
  setup(props, { expose }) {
    const state = reactive<State>({
      portals: [],
    });
    const mount = (key: number, children: PortalNode) => {
      state.portals.push({ key, children });
    };
    const update = (key: number, children: PortalNode) => {
      state.portals = state.portals.map((item) => {
        if (item.key === key) {
          return { ...item, children };
        }
        return item;
      });
    };
    const unmount = (key: number) => {
      state.portals = state.portals.filter((item) => item.key !== key);
    };
    expose({
      mount,
      update,
      unmount,
    });
    return () => {
      return h(
        'div',
        null,
        state.portals.map((item) => {
          return h('div', { key: item.key }, [item.children]);
        })
      );
    };
  },
});
</script>
apps/cMiniApp/src/components/Portal/index.ts
New file
@@ -0,0 +1,12 @@
import PortalContainer from './portal-container.vue';
import PortalHost from './portal-host.vue';
import { portal } from './portal';
import Portal from './Portal.vue';
export default {
  Host: PortalHost,
  add: portal.add,
  remove: portal.remove,
  Portal: Portal,
  Container: PortalContainer,
};
apps/cMiniApp/src/components/Portal/portal-consumer.vue
New file
@@ -0,0 +1,37 @@
<script lang="ts">
import { PortalMethods } from './portal';
export default defineComponent({
  name: 'PortalConsumer',
  props: {
    manager: {
      type: Object as PropType<PortalMethods>,
    },
  },
  setup(props) {
    const _key = ref<number>();
    const slots = useSlots();
    onMounted(() => {
      if (!props.manager) {
        throw new Error('forgot');
      }
      const defaultSlot = slots.default();
      props.manager.update(_key.value, defaultSlot);
      _key.value = props.manager.mount(defaultSlot);
    });
    onUpdated(() => {
      const defaultSlot = slots.default();
      props.manager.update(_key.value, defaultSlot);
    });
    onUnmounted(() => {
      props.manager.unmount(_key.value);
    });
    return () => null;
  },
});
</script>
apps/cMiniApp/src/components/Portal/portal-container.vue
New file
@@ -0,0 +1,50 @@
<script lang="ts">
import { VNode } from 'vue';
import { portal } from './portal';
export default defineComponent({
  name: 'portal-container',
  props: {
    render: {
      type: Function as PropType<(open: Ref<boolean>, onClose?: () => any) => VNode>,
    },
    keyNumber: {
      type: Number,
    },
    /**
     * 是否延迟设置open为true
     */
    delayOpen: {
      type: Boolean,
    },
  },
  setup(props, { slots }) {
    const open = ref(!props.delayOpen);
    function onClose() {
      open.value = false;
    }
    onMounted(() => {
      if (props.delayOpen) {
        setTimeout(() => {
          open.value = true;
        }, 30);
      }
    });
    watch(open, (open, preOpen) => {
      if (preOpen && !open) {
        setTimeout(() => {
          portal.remove(props.keyNumber);
        }, 300);
      }
    });
    return () => {
      //   const childrenNode = props.render(open, onClose);
      return slots.default?.({ open, onClose });
    };
  },
});
</script>
apps/cMiniApp/src/components/Portal/portal-host.vue
New file
@@ -0,0 +1,104 @@
<template>
  <slot></slot>
  <PortalManager ref="_manager" />
</template>
<script lang="ts">
defineComponent({
  name: 'portal-host',
  inheritAttrs: false,
});
</script>
<script setup lang="ts">
import {
  PortalContextKey,
  Operation,
  getUniqueKey,
  addType,
  removeType,
  TopViewEventEmitter,
  PortalNode,
  PortalManagerInstance,
} from './portal';
import PortalManager from './PortalManager.vue';
const _nextKey = ref(0);
const _queue = ref<Operation[]>([]);
const _manager = ref<PortalManagerInstance>();
onMounted(() => {
  TopViewEventEmitter.on(getUniqueKey(addType), _mount);
  TopViewEventEmitter.on(getUniqueKey(removeType), _unmount);
  while (_queue.value.length && _manager.value) {
    const action = _queue.value.pop();
    if (!action) {
      continue;
    }
    switch (action.type) {
      case 'mount':
        _manager.value.mount(action.key, action.children);
        break;
      case 'update':
        _manager.value.update(action.key, action.children);
        break;
      case 'unmount':
        _manager.value.unmount(action.key);
        break;
    }
  }
});
onUnmounted(() => {
  TopViewEventEmitter.off(getUniqueKey(addType), _mount);
  TopViewEventEmitter.off(getUniqueKey(removeType), _unmount);
});
const _setManager = (manager?: any) => {
  _manager.value = manager;
};
const _mount = (children: PortalNode, _key?: number) => {
  const key = _key || _nextKey.value++;
  if (_manager.value) {
    _manager.value.mount(key, children);
  } else {
    _queue.value.push({ type: 'mount', key, children });
  }
  return key;
};
const _update = (key: number, children: PortalNode) => {
  if (_manager.value) {
    _manager.value.update(key, children);
  } else {
    const op: Operation = { type: 'mount', key, children };
    const index = _queue.value.findIndex(
      (o) => o.type === 'mount' || (o.type === 'update' && o.key === key)
    );
    if (index > -1) {
      _queue.value[index] = op;
    } else {
      _queue.value.push(op);
    }
  }
};
const _unmount = (key: number) => {
  if (_manager.value) {
    _manager.value.unmount(key);
  } else {
    _queue.value.push({ type: 'unmount', key });
  }
};
provide(PortalContextKey, {
  mount: _mount,
  update: _update,
  unmount: _unmount,
});
</script>
apps/cMiniApp/src/components/Portal/portal.ts
New file
@@ -0,0 +1,72 @@
import type { VNode } from 'vue';
import Taro from '@tarojs/taro';
export type PortalNode = VNode | VNode[];
export type State = {
  portals: Array<{
    key: number;
    children: PortalNode;
  }>;
};
export type PortalManagerState = {
  portals: Array<{
    key: number;
    children: PortalNode;
  }>;
};
export type PortalMethods = {
  mount: (children: PortalNode) => number;
  update: (key: number, children: PortalNode) => void;
  unmount: (key: number) => void;
};
export type Operation =
  | { type: 'mount'; key: number; children: PortalNode }
  | { type: 'update'; key: number; children: PortalNode }
  | { type: 'unmount'; key: number };
export const PortalContextKey: InjectionKey<PortalMethods> = Symbol('PortalContextKey');
export function usePortalContext() {
  return inject(PortalContextKey);
}
export function getUniqueKey(key: string) {
  const router = Taro.getCurrentInstance().router;
  const prefix = router.path;
  return `${prefix}_${key}`;
}
// events
export const addType = 'ADD_PORTAL';
export const removeType = 'REMOVE_PORTAL';
export const TopViewEventEmitter = new Taro.Events();
class PortalGuard {
  private nextKey = 10000;
  add = (render: (_key: number) => PortalNode) => {
    const key = this.nextKey++;
    const node = render(key);
    TopViewEventEmitter.trigger(getUniqueKey(addType), node, key);
    return key;
  };
  remove = (key: number) => {
    TopViewEventEmitter.trigger(getUniqueKey(removeType), key);
  };
}
/**
 * portal
 */
export const portal = new PortalGuard();
export type PortalManagerInstance = {
  mount: (key: number, children: PortalNode) => void;
  update: (key: number, children: PortalNode) => void;
  unmount: (key: number) => {
    key: number;
    children: PortalNode;
  }[];
};
apps/cMiniApp/src/components/UserHome/UserHomeTopView.vue
@@ -1,7 +1,7 @@
<template>
  <div class="mine-page-top-view">
    <slot name="avatar"></slot>
    <div class="setting-wrapper" v-if="showUserHomePageBtn" @click="">
    <div class="setting-wrapper" v-if="showUserHomePageBtn" @click="goMineCurriculumVitae">
      <div class="setting-text">
        我的简历<IconFont name="rect-right" size="16" color="#6D6E6E"></IconFont>
      </div>
@@ -12,6 +12,7 @@
<script setup lang="ts">
import { useUser } from '@/hooks';
import Taro from '@tarojs/taro';
import { RouterPath } from '@/constants';
defineOptions({
  name: 'UserHomeTopView',
@@ -28,6 +29,12 @@
});
const { userDetail } = useUser();
function goMineCurriculumVitae() {
  Taro.navigateTo({
    url: RouterPath.mineCurriculumVitae,
  });
}
</script>
<style lang="scss">
@@ -39,14 +46,16 @@
  margin-bottom: 20px;
  .setting-wrapper {
    align-self: center;
    align-self: flex-start;
    display: flex;
    align-items: center;
    margin-top: 8px;
    margin-right: calc(boleGetCssVar('size', 'body-padding-h') * -1);
    .setting-text {
      font-weight: 400;
      font-size: 28px;
      line-height: 40px;
      display: flex;
      align-items: center;
      color: boleGetCssVar('text-color', 'primary');
apps/cMiniApp/src/constants/router.ts
@@ -33,5 +33,7 @@
  mineCollectTask = '/subpackages/mine/mineCollectTask/mineCollectTask',
  mineAgreementSign = '/subpackages/mine/mineAgreementSign/mineAgreementSign',
  mineAgreementSignDetail = '/subpackages/mine/mineAgreementSignDetail/mineAgreementSignDetail',
  mineCurriculumVitae = '/subpackages/mine/mineCurriculumVitae/mineCurriculumVitae',
  editMineInfo = '/subpackages/mine/editMineInfo/editMineInfo',
  setting = '/subpackages/mine/setting/setting',
}
apps/cMiniApp/src/pages/mine/index.scss
@@ -25,7 +25,7 @@
      min-width: 0;
      display: flex;
      flex-direction: column;
      padding: 10px 0;
      padding: 6px 0;
      justify-content: space-between;
      .user-info-item {
apps/cMiniApp/src/pages/mine/index.vue
@@ -75,10 +75,10 @@
        </div>
      </List>
      <List class="mine-list-wrapper mine-setting-list">
        <ListItem :icon="IconSetting" title="我收藏的任务" @click="goMineCollectTask"></ListItem>
        <ListItem :icon="IconSetting" title="协议签约" @click="goMineAgreementSign"></ListItem>
        <ListItem :icon="IconCollect" title="我收藏的任务" @click="goMineCollectTask"></ListItem>
        <ListItem :icon="IconAgreement" title="协议签约" @click="goMineAgreementSign"></ListItem>
        <ListItem :icon="IconSetting" title="设置" @click="goSetting"></ListItem>
        <ListItem :icon="IconSetting" title="我要招人/用人" @click="goSetting"></ListItem>
        <ListItem :icon="IconRecruit" title="我要招人/用人" @click="goSetting"></ListItem>
      </List>
    </ContentScrollView>
  </PageLayoutWithBg>
@@ -88,6 +88,9 @@
import { TransparentNavigationBar, ContentScrollView, UserHomeTopView } from '@/components';
import IconArrow from '@/assets/setting/icon-arrow.png';
import IconSetting from '@/assets/mine/icon-setting.png';
import IconCollect from '@/assets/mine/icon-collect.png';
import IconAgreement from '@/assets/mine/icon-agreement.png';
import IconRecruit from '@/assets/mine/icon-recruit.png';
import IconOrderSign from '@/assets/mine/icon-order-sign.png';
import IconOrderHire from '@/assets/mine/icon-order-hire.png';
import IconOrderCancel from '@/assets/mine/icon-order-cancel.png';
@@ -162,4 +165,11 @@
.mine-setting-badge {
  margin-right: 20px;
}
.mine-setting-list {
  .pro-list-item-icon {
    width: 48px;
    height: 48px;
  }
}
</style>
apps/cMiniApp/src/subpackages/mine/editMineInfo/InnerPage.vue
New file
@@ -0,0 +1,65 @@
<template>
  <ContentScrollView :paddingH="false">
    <nut-form :model-value="form" ref="formRef" :rules="rules">
      <nut-form-item label="姓名:" prop="name">
        <nut-input v-model.trim="form.name" placeholder="请输入企业名称" />
      </nut-form-item>
      <nut-form-item label="手机号:" prop="phone" required>
        <nut-input v-model.trim="form.phone" placeholder="请输入手机号" type="text" />
      </nut-form-item>
      <nut-form-item label="身份:" class="bole-form-item" prop="gender">
        <ChooseInputWithPicker
          v-model="form.gender"
          placeholder="请选择身份"
          :value-enum="MineHireTypeText"
        />
      </nut-form-item>
    </nut-form>
  </ContentScrollView>
  <PageFooter>
    <PageFooterBtn type="primary" @click="handleConfirm">保存</PageFooterBtn>
  </PageFooter>
</template>
<script setup lang="ts">
import { useUserStore } from '@/stores/modules/user';
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import ChooseInputWithPicker from '@/components/Input/ChooseInputWithPicker.vue';
import { MineHireTypeText, MineHireType } from './constants';
defineOptions({
  name: 'InnerPage',
});
const userStore = useUserStore();
const form = reactive({
  name: '',
  phone: '',
  gender: MineHireType.All,
});
const rules = reactive<FormRules>({
  phone: [{ required: true, message: '请输入手机号' }],
});
const formRef = ref<any>(null);
function handleConfirm() {
  if (!formRef.value) return;
  formRef.value.validate().then(({ valid, errors }: any) => {
    if (valid) {
      confirm();
    }
  });
}
function confirm() {}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.task-card-actions-text {
  font-size: 24px;
  line-height: 42px;
}
</style>
apps/cMiniApp/src/subpackages/mine/editMineInfo/constants/index.ts
New file
@@ -0,0 +1,19 @@
export enum MineHireType {
  All = 0,
  InProgress = 10,
  WaitCheck = 20,
  Finished = 30,
}
export const MineHireTypeText = {
  [MineHireType.All]: '全部',
  [MineHireType.InProgress]: '进行中',
  [MineHireType.WaitCheck]: '待验收',
  [MineHireType.Finished]: '已完成',
};
export const MineHireTypeColor = {
  [MineHireType.InProgress]: '#3A71FF',
  [MineHireType.WaitCheck]: '#FF7D00',
  [MineHireType.Finished]: '#9FA4AC',
};
apps/cMiniApp/src/subpackages/mine/editMineInfo/editMineInfo.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/cMiniApp/src/subpackages/mine/editMineInfo/editMineInfo.vue
New file
@@ -0,0 +1,17 @@
<template>
  <PageLayout class="index-page-wrapper" :title="'编辑个人信息'">
    <InnerPage></InnerPage>
  </PageLayout>
</template>
<script setup lang="ts">
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'editMineInfo',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/InnerPage.vue
@@ -1,12 +1,89 @@
<template>
  <LoadingLayout>
    <ContentScrollView :paddingH="false" style="background-color: transparent">
  <div class="mine-agreement-sign-detail">
    <MineAgreementSignDetailCard title="基本信息"></MineAgreementSignDetailCard>
        <MineAgreementSignDetailCard title="基本信息">
          <template #content>
            <MineAgreementSignDetailItem
              label="协议编号"
              detail="QY1052511040446686047"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="协议状态"
              detail="生效中/已终止"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="起始时间"
              detail="2024.05.20"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="终止时间"
              detail="2025.05.19"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="协议类型"
              detail="劳动合同"
            ></MineAgreementSignDetailItem>
          </template>
        </MineAgreementSignDetailCard>
        <MineAgreementSignDetailCard title="签约方信息 - 员工">
          <template #content>
            <MineAgreementSignDetailItem
              label="员工姓名"
              detail="阳阳"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="证件类型"
              detail="居民身份证"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="证件号码"
              detail="622429199105261913"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem label="岗位" detail="保洁"></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="签约时间"
              detail="2024.05.20"
            ></MineAgreementSignDetailItem>
          </template>
        </MineAgreementSignDetailCard>
        <MineAgreementSignDetailCard title="签约方信息 - 公司主体">
          <template #content>
            <MineAgreementSignDetailItem
              label="主体类型"
              detail="公司"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="签约主体"
              detail="宁波人力无忧人力资源"
            ></MineAgreementSignDetailItem>
            <MineAgreementSignDetailItem
              label="签约时间"
              detail="2024.05.20"
            ></MineAgreementSignDetailItem>
          </template>
        </MineAgreementSignDetailCard>
        <MineAgreementSignDetailCard title="签约内容">
          <template #content>
            <MineAgreementSignDetailItem label="协议内容">
              <template #detail>
                <div class="detail-card-btn">查看协议</div>
              </template>
            </MineAgreementSignDetailItem>
          </template>
        </MineAgreementSignDetailCard>
  </div>
    </ContentScrollView>
    <PageFooter>
      <PageFooterBtn type="primary" @click="goToSign">去签约</PageFooterBtn>
    </PageFooter>
  </LoadingLayout>
</template>
<script setup lang="ts">
import { useUserStore } from '@/stores/modules/user';
import MineAgreementSignDetailCard from './MineAgreementSignDetailCard.vue';
import MineAgreementSignDetailItem from './MineAgreementSignDetailItem.vue';
defineOptions({
  name: 'InnerPage',
@@ -15,6 +92,8 @@
const queryState = reactive({});
const userStore = useUserStore();
function goToSign() {}
</script>
<style lang="scss">
@@ -22,5 +101,13 @@
.mine-agreement-sign-detail {
  padding: 20px 28px 0;
  .mine-agreement-sign-detail-card {
    margin-bottom: 24px;
  }
}
.detail-card-btn {
  color: boleGetCssVar('color', 'primary');
}
</style>
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/MineAgreementSignDetailItem.vue
New file
@@ -0,0 +1,62 @@
<template>
  <div class="mine-agreement-sign-detail-item">
    <div
      class="mine-agreement-sign-detail-item-lebel"
      :style="{ width: labelWidth, textAlign: textAlign }"
    >
      <slot name="label">
        {{ label }}
      </slot>
    </div>
    <div class="mine-agreement-sign-detail-item-detail">
      <slot name="detail">
        {{ detail }}
      </slot>
    </div>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'MineAgreementSignDetailItem',
});
type Props = {
  label?: string;
  detail?: string;
  labelWidth?: any;
  textAlign?: any;
};
const props = withDefaults(defineProps<Props>(), {
  labelWidth: '50px',
  textAlign: 'left',
});
</script>
<style lang="scss">
.mine-agreement-sign-detail-item {
  margin-bottom: 24px;
  display: flex;
  align-items: center;
  &:last-child {
    margin-bottom: 0;
  }
  .mine-agreement-sign-detail-item-lebel {
    font-size: 24px;
    line-height: 36px;
    margin-right: 24px;
    color: boleGetCssVar('text-color', 'regular');
  }
  .mine-agreement-sign-detail-item-detail {
    font-size: 24px;
    line-height: 36px;
    color: boleGetCssVar('text-color', 'primary');
    flex: 1;
    min-width: 0;
  }
}
</style>
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/mineAgreementSignDetail.vue
apps/cMiniApp/src/subpackages/mine/mineAgreementSignDetail/mineAgreementSignDetailItem.vue
File was deleted
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/InnerPage.vue
New file
@@ -0,0 +1,255 @@
<template>
  <ContentView>
    <nut-noticebar
      text="个人简历已完善50%,完善简历可提升录用率"
      :left-icon="false"
      background="transparent"
      close-mode
    />
    <div class="mine-curriculum-info-wrapper">
      <UserAvatar :size="60" class="mine-curriculum-avatar" />
      <div class="mine-curriculum-info-content">
        <div class="mine-curriculum-info-item">
          <div class="mine-curriculum-info-item-left">
            <div class="mine-curriculum-info-item-name">
              {{ userStore.userDetail?.userName ?? '' }}
            </div>
            <div class="mine-curriculum-info-item-gender">
              <div class="mine-curriculum-info-item-gender-dot">·</div>
              <img :src="IconAuth" class="mine-curriculum-info-item-gender-icon" />
            </div>
          </div>
          <IconFont name="rect-right" size="16" color="#6D6E6E" @click="goEditMineInfo"></IconFont>
        </div>
        <div class="mine-curriculum-info-item">
          <div class="mine-curriculum-info-item-left">
            <img :src="IconAuth" class="mine-curriculum-info-item-phone-icon" />
            <div class="mine-curriculum-info-item-phone">
              {{ userStore.userDetail?.phoneNumber ?? '' }}
            </div>
          </div>
          <div class="mine-curriculum-info-item-detail">
            {{ '26岁 | 非学生 | 本科' }}
          </div>
        </div>
      </div>
    </div>
    <List class="mine-curriculum-intention">
      <div class="mine-curriculum-intention-content">
        <div class="mine-curriculum-intention-title">
          <div class="mine-curriculum-intention-title-text">求职意向</div>
          <div class="mine-curriculum-intention-title-edit">
            编辑
            <img :src="IconArrow" class="mine-curriculum-intention-title-edit-icon" />
          </div>
        </div>
        <MineAgreementSignDetailItem label="期望岗位" class="mine-curriculum-intention-job">
          <template #detail>
            <div class="mine-curriculum-intention-job-content">
              <div class="mine-curriculum-intention-job-item">客房服务员</div>
              <div class="mine-curriculum-intention-job-item">客房服务员</div>
              <div class="mine-curriculum-intention-job-item">客房服务员</div>
              <div class="mine-curriculum-intention-job-item">客房服务员</div>
            </div>
          </template>
        </MineAgreementSignDetailItem>
        <MineAgreementSignDetailItem label="空闲时间">
          <template #detail>
            <div class="mine-curriculum-intention-bold">不限</div>
          </template>
        </MineAgreementSignDetailItem>
        <MineAgreementSignDetailItem label="求职状态">
          <template #detail>
            <div class="mine-curriculum-intention-bold">积极找工作</div>
          </template>
        </MineAgreementSignDetailItem>
      </div>
      <ListItem title="资格证书">
        <template #extra>
          <div class="mine-curriculum-intention-enit-btn">编辑</div>
        </template>
      </ListItem>
      <ListItem title="工作经验">
        <template #extra>
          <div class="mine-curriculum-intention-enit-btn">编辑</div>
        </template>
      </ListItem>
      <ListItem title="详细信息" class="mine-curriculum-intention-detail">
        <template #extra>
          <div class="mine-curriculum-intention-enit-btn">编辑</div>
        </template>
      </ListItem>
    </List>
  </ContentView>
</template>
<script setup lang="ts">
import { useUserStore } from '@/stores/modules/user';
import { useIsLogin } from '@/hooks';
import MineAgreementSignDetailItem from '../mineAgreementSignDetail/MineAgreementSignDetailItem.vue';
import { List, ListItem } from '@12333/components';
import { RouterPath } from '@/constants';
import IconArrow from '@/assets/setting/icon-arrow.png';
import IconAuth from '@/assets/mine/icon-auth.png';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'InnerPage',
});
const userStore = useUserStore();
const isLogin = useIsLogin();
function goEditMineInfo() {
  Taro.navigateTo({
    url: RouterPath.editMineInfo,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.mine-curriculum-info-wrapper {
  padding: 24px 0 50px;
  display: flex;
  .mine-curriculum-avatar {
    margin-right: 24px;
  }
  .mine-curriculum-info-content {
    display: flex;
    flex-direction: column;
    padding: 12px 0;
    justify-content: space-between;
    flex: 1;
    min-width: 0;
    .mine-curriculum-info-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      .mine-curriculum-info-item-left {
        display: inline-flex;
        align-items: center;
        .mine-curriculum-info-item-name {
          font-size: 32px;
          line-height: 40px;
          font-weight: 600;
          color: boleGetCssVar('text-color', 'primary');
        }
        .mine-curriculum-info-item-gender {
          display: inline-flex;
          align-items: center;
          .mine-curriculum-info-item-gender-dot {
            margin: 0 8px;
            line-height: 40px;
          }
          .mine-curriculum-info-item-gender-icon {
            width: 36px;
            height: 36px;
          }
        }
        .mine-curriculum-info-item-phone {
          font-size: 28px;
          line-height: 40px;
          font-weight: 400;
          color: boleGetCssVar('text-color', 'primary');
        }
        .mine-curriculum-info-item-phone-icon {
          width: 24px;
          height: 24px;
        }
      }
      .mine-curriculum-info-item-detail {
        font-size: 24px;
        line-height: 40px;
        color: boleGetCssVar('text-color', 'primary');
      }
    }
  }
}
.mine-curriculum-intention {
  padding: 30px 0;
  border-radius: 12px;
  .mine-curriculum-intention-content {
    padding: 0 boleGetCssVar('size', 'body-padding-h') 40px;
    border-bottom: 1px solid #f6f6f6;
    .mine-curriculum-intention-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 40px;
      .mine-curriculum-intention-title-text {
        font-size: 32px;
        font-weight: 600;
        color: boleGetCssVar('text-color', 'primary');
      }
      .mine-curriculum-intention-title-edit {
        display: inline-flex;
        align-items: center;
        font-size: 22px;
        color: boleGetCssVar('text-color', 'regular');
        .mine-curriculum-intention-title-edit-icon {
          width: 32px;
          height: 32px;
        }
      }
    }
    .mine-curriculum-intention-job {
      align-items: flex-start;
      .mine-curriculum-intention-job-content {
        display: inline-flex;
        flex-wrap: wrap;
        .mine-curriculum-intention-job-item {
          font-size: 20px;
          color: boleGetCssVar('color', 'primary');
          padding: 6px 16px;
          background-color: #edf2ff;
          border-radius: 4px;
          display: inline-flex;
          align-items: center;
          justify-content: center;
          margin-right: 16px;
          margin-bottom: 14px;
        }
      }
    }
    .mine-curriculum-intention-bold {
      font-weight: 600;
      font-size: 28px;
    }
  }
  .mine-curriculum-intention-enit-btn {
    font-size: 22px;
    color: boleGetCssVar('text-color', 'regular');
  }
  .mine-curriculum-intention-detail {
    .pro-list-item-inner {
      border-bottom: none;
    }
  }
}
</style>
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/mineCurriculumVitae.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/cMiniApp/src/subpackages/mine/mineCurriculumVitae/mineCurriculumVitae.vue
New file
@@ -0,0 +1,17 @@
<template>
  <PageLayoutWithBg class="index-page-wrapper" :title="'我的简历'">
    <InnerPage></InnerPage>
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'mineCurriculumVitae',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>